Add a script for managing email accounts

This initial version can:
- create a mailbox (cyradm)
- create a mail alias (virtual_{alias|local}_map)
- create a valid recipient for postfix ({virtual|local}_recipient_map)
- create a password for the account (saslpasswd2)
- print settings to set in the MUA to use this account
- test arguments
This commit is contained in:
Thomas Preud'homme 2010-01-20 14:53:09 +01:00 committed by Thomas Preud'homme
parent 0632e91565
commit 1f0be8664b
1 changed files with 399 additions and 0 deletions

399
email_account/email_account Executable file
View File

@ -0,0 +1,399 @@
#!/bin/sh
set -u
# Display usage
usage ()
{
local - progname
progname=$1
echo "Usage :"
echo
echo "$progname emailaccount [emailalias]"
echo "$progname -h | --help"
echo
echo "Fist form add an email account named emailaccount if it doesn't already exist"
echo "and create an alias named emailalias for this email account if specified"
echo
echo "Second and third form print this help"
}
# Test an email is valid and exit if it isn't
test_email ()
{
local -
user=$(echo "$1" | cut -d '@' -f 1)
if [ -z "$user" ]
then
echo "Missing user in email account"
exit 1
fi
domain=$(echo "$1" | cut -d '@' -f 2)
if echo "$domain" | grep -E -v "^([[:alnum:]]+\.)+[[:alnum:]]+$" > /dev/null
then
echo "Invalid domain for email account"
exit 1
fi
}
ask_user_default_no ()
{
local - answer
answer="unset"
echo -n "$1 [y/N] "
while [ -n "$answer" -a "$answer" != "y" -a "$answer" != "Y" -a "$answer" != "n" -a "$answer" != "N" ]
do
read answer
if [ -z "$answer" -o "$answer" = "n" -o "$answer" = "N" ]
then
return 1
fi
if [ "$answer" = "y" -o "$answer" = "Y" ]
then
break
fi
echo -n "$2 [y/N] "
done
return 0
}
# Test number of argument is correct and their value are correct also
test_args ()
{
local - user domain first_ask next_ask
if [ \( $# -ge 1 -a "$1" = "-h" -a $# -gt 1 \) -o $# -gt 2 ]
then
echo "Too many arguments"
exit 1
fi
if [ $# -eq 0 -o "$1" = "-h" -o "$1" = "-help" ]
then
usage $(basename $0)
exit 0
else
# Test email arguments
test_email "$1"
emailuser="$user"
emaildomain="$domain"
if [ $# -eq 2 ]
then
test_email "$2"
aliasuser="$user"
aliasdomain="$domain"
if [ "$emaildomain" != "$aliasdomain" ]
then
echo "Domain of the alias must be identical to the domain of the email account"
exit 1
fi
fi
fi
first_ask="Be aware that you'll need to restart cyrus twice and postfix once. Are you ready ?"
next_ask="Incorrect answer. Are you ready to restart cyrus and postfix ?"
ask_user_default_no "$first_ask" "$next_ask"
if [ $? -eq 1 ]
then
echo "Ok, exiting_"
exit 1
fi
}
# Are we root ?
must_sudo ()
{
uid="$(id -u)"
[ ! $uid -eq 0 ]
return $?
}
# This function try to become root with sudo and execute this script
# NB: This function doesn't return
try_sudo ()
{
local - ret
echo "You aren't root. Trying to use sudo to become root…"
sudo $0 "$@"
ret=$?
if [ ! $ret -eq 0 ]
then
echo "You must be root or being able to become root by sudo without password to create an email account or add an email alias"
fi
exit $ret
}
# Test cyrus password is ok
test_cyrus_admin ()
{
local -
cyruser=$(grep -E "^[[:space:]]*admins:" /etc/imapd.conf | cut -d ':' -f 2- | sed -r "s/[[:alnum:]]+@[[:alnum:].]+//g" | tr -d ' ')
cyrpwd=$(cat /root/cyrus_main_admin_password)
testsaslauthd -u $cyruser -p $cyrpwd > /dev/null || { echo "Password for main cyrus admin has changed but has not been modified in /root/" && exit 1 ; }
}
# Save cyrus state and make it cyradm ready, that is save and change
# allowplaintext and virtdomain and make it listen on localhost:imap
# instead of *:imap
save_cyrus_state_and_become_cyradm_ready ()
{
local -
sed -r -i "s/^(.*cmd=\"imapd.* listen=\")(imap\".*)$/\1localhost:\2/" /etc/cyrus.conf
sed -r -i "s/^([[:space:]]*allowplaintext:.*)$/#\1\nallowplaintext: 1/" /etc/imapd.conf
sed -r -i "s/^([[:space:]]*virtdomains:.*)$/#\1\nvirtdomains: userid/" /etc/imapd.conf
invoke-rc.d cyrus2.2 restart
if [ ! $? -eq 0 ]
then
echo "Restarting cyrus failed. The requested action coudn't be performed."
echo "Look at the logs and restart Cyrus manually."
return 1
fi
return 0
}
# Ask a password to the user and create the entry in sasldb database
ask_and_create_password ()
{
local - newemailpassword
emailpassword=""
newemailpassword="different"
while [ "$emailpassword" != "$newemailpassword" ]
do
emailpassword=""
echo "What password do you want for your email account ?"
while [ -z "$emailpassword" ]
do
echo -n "Password : "
read emailpassword
done
newemailpassword=""
echo "Re-enter your password to ensure you type it in correctly"
while [ -z "$newemailpassword" ]
do
echo -n "Password (bis) : "
read newemailpassword
done
if [ "$emailpassword" != "$newemailpassword" ]
then
echo "Password don't match"
fi
done
echo "$emailpassword" | saslpasswd2 -p -u "$emaildomain" "$emailuser"
}
# Check if a password already exist in the sasldb database.
# Then ask a password to the user and create the entry in sasldb
# database if password doesn't exist are user want to change it
create_sasldb_password ()
{
local - first_ask next_ask
sasldblistusers2 | grep "$emailuser@$emaildomain" > /dev/null
if [ $? -eq 0 ]
then
first_ask="There is already a password for this user, do you want to change it ?"
next_ask="Do you want to change the existing password for your email account ?"
ask_user_default_no "$first_ask" "$next_ask"
if [ $? -eq 0 ]
then
ask_and_create_password
else
emailpassword="has remained unchanged"
fi
else
ask_and_create_password
fi
}
# Add the domain of the email account to the list of virtual domain
# in cyrus and postfix if necessary
update_virtual_domains ()
{
local -
grep "defaultdomain:" /etc/imapd.conf | grep "$emaildomain" > /dev/null
if [ ! $? -eq 0 ]
then
grep "loginrealms:" /etc/imapd.conf | grep "$emaildomain" > /dev/null
if [ ! $? -eq 0 ]
then
sed -r -i "s/^([[:space:]]*loginrealms): ?(.*)$/\1: $emaildomain \2/" /etc/imapd.conf
fi
fi
grep "mydomain[[:space:]]*=" /etc/postfix/main.cf | grep "$emaildomain" > /dev/null
if [ ! $? -eq 0 ]
then
grep "virtual_mailbox_domains[[:space:]]*=" /etc/postfix/main.cf | grep "$emaildomain" /dev/null
if [ ! $? -eq 0 ]
then
sed -r -i "s/^([[:space:]]*virtual_mailbox_domains[[:space:]]*)= ?(.*)$/\1= $emaildomain \2/" /etc/postfix/main.cf
fi
fi
}
# Print the first parameter and then the second parameter at a distance
# of $3 tabs
echo_with_tabs ()
{
local - nbchars nbtabs
nbchars=$(echo "$1" | wc -m)
nbtabs=$(($3-nbchars/8))
echo -n "$1"
for i in $(seq $nbtabs)
do
echo -n "\t"
done
echo "$2"
}
# Add requested email to postfix virtual_mailbox_maps
update_postfix_email_account ()
{
local -
grep "^[[:space:]]*$emailuser@$emaildomain" /etc/postfix/vmailbox > /dev/null
if [ ! $? -eq 0 ]
then
echo_with_tabs "$emailuser@$emaildomain" "whatever" 4 >> /etc/postfix/vmailbox
fi
if [ ! $# -eq 0 ]
then
grep "^[[:space:]]*$aliasuser@$aliasdomain" /etc/postfix/vmailbox > /dev/null
if [ ! $? -eq 0 ]
then
echo_with_tabs "$aliasuser@$aliasdomain" "whatever" 4 >> /etc/postfix/vmailbox
fi
fi
}
# Add requested alias to postfix virtual_alias_maps
update_email_aliases ()
{
local -
grep "$aliasuser@$aliasdomain[[:space:]]+$emailuser@$emaildomain" /etc/postfix/virtual > /dev/null
if [ ! $? -eq 0 ]
then
echo_with_tabs "$aliasuser@$aliasdomain" "$emailuser@$emaildomain" 4 >> /etc/postfix/virtual
fi
}
display_infos ()
{
local - imap imaps imapret imapsret security
set +u
grep "defaultdomain:" /etc/imapd.conf | grep "$emaildomain" > /dev/null
if [ $? -eq 0 ]
then
echo "Your email login is $emailuser and your password $emailpassword"
else
echo "Your email login is $emailuser@$emaildomain and your password $emailpassword"
fi
echo -n "supported mechanism for imap authentification are : "
sed -r -n "{s/sasl_mech_list: *(.*)$/\1/;t success;T;: success;p}" /etc/imapd.conf
echo -n "The imap server listen on port "
imap=$(grep -E "^[^#]+cmd=\"imapd[^#]+listen=\"imap\"" /etc/cyrus.conf)
imapret=$?
if [ $imapret -eq 0 ]
then
security=$(echo "$imap" | sed -r -n "{s/^.*cmd=\".* -s.*$/(SSL\/TLS)/;t success;T;: success;p}")
if [ -z "$security" ]
then
security="(STARTTLS)"
fi
echo -n "143 ($security)"
fi
imaps=$(grep -E "^[^#]+cmd=\"imapd[^#]+listen=\"imaps\"" /etc/cyrus.conf)
imapsret=$?
if [ $imapsret -eq 0 ]
then
security=$(echo "$imaps" | sed -r -n "{s/^.*cmd=\".* -s.*$/(SSL\/TLS)/;t success;T;: success;p}")
if [ -z "$security" ]
then
security="(STARTTLS)"
fi
if [ $imapret -eq 0 ]
then
echo -n " and on port "
fi
echo -n "993 ($security)"
fi
echo
}
# Restore cyrus state as it was before making it cyradm ready, that is
# restore allowplaintext, virtdomain and make it listen on *:imap
# instead of localhost:imap
restore_cyrus_state ()
{
local -
sed -r -i "s/^(.*cmd=\"imapd.* listen=\")localhost:(imap\".*)$/\1\2/" /etc/cyrus.conf
# Ok let's explain that sed line
# First you must understand that for each line all the commands inside
# the {} block and separated by ; are executed
# When the allowplaintext commented line is found, the # is removed by
# a s/pattern/replacement/ command. Then, as this substitution is
# successful, we jump at success which copy the substituted line in
# the hold space, get the next line in the pattern space and replace
# it by the substituted line. We've just deleted the next line. Then,
# we print the line in the pattern space. If from the beginning we
# have a non allowplaintext line, then T makes us jump to fail and
# print the line in the pattern space (that is the current line)
sed -r -n -i "{s/^#([[:space:]]*allowplaintext:.*)$/\1/;t success;T fail;: success;h;n;g;: fail;p}" /etc/imapd.conf
# Same as for allowplaintext above
sed -r -n -i "{s/^#([[:space:]]*virtdomains:.*)$/\1/;t success;T fail;: success;h;n;g;: fail;p}" /etc/imapd.conf
invoke-rc.d --quiet cyrus2.2 restart
if [ ! $? -eq 0 ]
then
echo "Restarting cyrus failed"
exit 1
fi
invoke-rc.d --quiet postfix restart
if [ ! $? -eq 0 ]
then
echo "Restarting postfix failed"
exit 1
fi
}
# Create the mailbox
create_mail_account ()
{
local - nblines
nblines=$(echo "listmailbox user.$emailuser@$emaildomain" | cyradm --user $cyruser --auth login --pass $cyrpwd localhost | wc -l)
if [ $nblines -eq 0 ]
then
echo "Mailbox for $emailuser@$emaildomain doesn't exist, creating it…"
echo "createmailbox user.$emailuser@$emaildomain" | cyradm --user $cyruser --auth login --pass $cyrpwd localhost
fi
}
main ()
{
ret=0
# This test should be useless if rights on this file are corrects
# (that is 770 for root:gt owner)
test_args "$@"
if must_sudo
then
try_sudo "$@"
fi
test_cyrus_admin
save_cyrus_state_and_become_cyradm_ready
if [ $? -eq 0 ]
then
create_sasldb_password
update_virtual_domains
aliasuser="${aliasuser:-""}"
if [ -n "$aliasuser" ]
then
update_postfix_email_account 1
update_email_aliases
else
update_postfix_email_account
fi
create_mail_account
display_infos
else
ret=1
fi
restore_cyrus_state
return $ret
}
main "$@"
exit $?