scripts/email_account/email_account

355 lines
8.8 KiB
Plaintext
Raw Permalink Normal View History

#!/bin/sh
#
# email_account, Copyright © 2010 Thomas Preud'homme
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# email_account is a helper to create e-mail accounts in a configuration
# using Postfix mail transport agent with vhosts and Cyrus IMAP server,
# in a Debian environment.
set -u
# Display usage.
usage ()
{
local - progname
progname=$1
echo "Usage :"
echo
echo "$progname emailaccount [emailalias]"
echo "$progname -h"
echo
echo "First form adds an email account named emailaccount if it doesn't already exist"
echo "and creates an alias named emailalias for this email account if specified."
echo
echo "Second form prints 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 "Error! Missing user in email account." >&2
exit 1
fi
domain=$(echo "$1" | cut -d '@' -f 2)
if echo "$domain" | grep -E -v "^([[:alnum:]]+\.)+[[:alnum:]]+$" > /dev/null
then
echo "Error! Invalid domain for email account." >&2
exit 1
fi
}
# Ask a question to the user. Return 1 if the answer is negative,
# or 0 if it is positive.
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
while getopts "h" opt
do
case $opt in
"h")
if [ $# -gt 1 ]
then
echo "Error! Too many arguments." >&2
exit 1
fi
usage $(basename "$0")
exit 0 ;;
esac
done
if [ $# -eq 1 -a -z "$1" ]
then
usage $(basename "$0")
exit 0
fi
if [ $# -gt $((OPTIND+1)) ]
then
echo "Error! Too many arguments." >&2
exit 1
fi
# Test email arguments
eval test_email "\$$OPTIND"
emailuser="$user"
emaildomain="$domain"
if [ $# -eq $((OPTIND+1)) ]
then
eval test_email "\$$((OPTIND+1))"
aliasuser="$user"
aliasdomain="$domain"
if [ "$emaildomain" != "$aliasdomain" ]
then
echo "Error! Domain of the alias must be identical to the domain of the email account." >&2
exit 1
fi
fi
}
# Are we root?
must_sudo ()
{
uid="$(id -u)"
[ ! $uid -eq 0 ]
return $?
}
# This function tries 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 "$@" # Try to execute the script with sudo
ret=$?
if [ ! $ret -eq 0 ]
then
echo "Error! You must be root or being able to become root by sudo without password to create an email account or add an email alias." >&2
fi
exit $ret
}
# Test cyrus password is OK.
test_cyrus_admin ()
{
local -
cyruser=$(grep -E "^[[:blank:]]*admins:" /etc/imapd.conf | cut -d ':' -f 2- | sed -r "s/[[:alnum:]]+@[[:alnum:].]+//g" | tr -d ' ')
cyrpwd=$(cat /root/passwords/cyrus_main_admin_password)
testsaslauthd -u $cyruser -p $cyrpwd > /dev/null || { echo "Error! Password for main cyrus admin has changed but has not been modified in /root/" >&2 && exit 1 ; }
}
# 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 "Please re-enter your password to ensure you typed it correctly."
while [ -z "$newemailpassword" ]
do
echo -n "Password (bis): "
read newemailpassword
done
if [ "$emailpassword" != "$newemailpassword" ]
then
echo "Passwords don't match!"
fi
done
echo "$emailpassword" | saslpasswd2 -p -u "$emaildomain" "$emailuser"
}
# Check if a password already exists 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 "loginrealms:" /etc/imapd.conf | grep "$emaildomain" > /dev/null
if [ ! $? -eq 0 ]
then
sed -r -i "s/^([[:blank:]]*loginrealms): ?(.*)$/\1: $emaildomain \2/" /etc/imapd.conf
fi
grep -E "virtual_mailbox_domains[[:blank:]]*=" /etc/postfix/main.cf | grep "$emaildomain" /dev/null
if [ ! $? -eq 0 ]
then
sed -r -i "s/^([[:blank:]]*virtual_mailbox_domains[[:blank:]]*)= ?(.*)$/\1= $emaildomain \2/" /etc/postfix/main.cf
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))
[ $nbtabs -lt 1 ] && nbtabs=1
echo -n "$1"
for i in $(seq $nbtabs)
do
echo -n "\t"
done
echo "$2"
}
# Add requested alias to postfix virtual_alias_maps.
update_email_aliases ()
{
local -
grep -E "[[:blank:]]*$aliasuser@$aliasdomain[[:blank:]]+$emailuser@$emaildomain" /etc/postfix/virtual > /dev/null
if [ ! $? -eq 0 ]
then
echo_with_tabs "$aliasuser@$aliasdomain" "$emailuser@$emaildomain" 4 >> /etc/postfix/virtual
fi
postmap /etc/postfix/virtual
}
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 "."
}
# Ask Postfix and Cyrus to reload their configuration
reload_config ()
{
local -
invoke-rc.d --quiet cyrus2.2 reload
if [ ! $? -eq 0 ]
then
echo "Error! Cyrus failed to reload its configuration." >&2
exit 1
fi
invoke-rc.d --quiet postfix reload
if [ ! $? -eq 0 ]
then
echo "Error! Postfix failed to reload its configuration." >&2
exit 1
fi
}
# Create the mailbox
create_mail_account ()
{
local - nblines
nblines=$(echo "listmailbox user/$emailuser@$emaildomain" | cyradm --user $cyruser --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 --pass $cyrpwd localhost
fi
}
main ()
{
local - ret
# 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
create_sasldb_password
update_virtual_domains
aliasuser="${aliasuser:-""}"
if [ -n "$aliasuser" ]
then
update_email_aliases
fi
create_mail_account
display_infos
reload_config
return 0
}
main "${@:-""}"
exit $?