2010-01-20 14:53:09 +01:00
#!/bin/sh
2010-01-25 14:43:13 +01:00
#
# 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.
2010-01-20 14:53:09 +01:00
set -u
2010-01-20 16:13:51 +01:00
# Display usage.
2010-01-20 14:53:09 +01:00
usage ()
{
local - progname
progname=$1
echo "Usage :"
echo
echo "$progname emailaccount [emailalias]"
2010-01-26 19:14:51 +01:00
echo "$progname -h"
2010-01-20 14:53:09 +01:00
echo
2013-02-10 18:48:33 +01:00
echo "First form adds an email account named emailaccount if it doesn't already exist"
2010-01-20 16:13:51 +01:00
echo "and creates an alias named emailalias for this email account if specified."
2010-01-20 14:53:09 +01:00
echo
2010-01-20 16:13:51 +01:00
echo "Second form prints this help."
2010-01-20 14:53:09 +01:00
}
2010-01-20 16:13:51 +01:00
# Test an email is valid and exit if it isn't.
2010-01-20 14:53:09 +01:00
test_email ()
{
local -
user=$(echo "$1" | cut -d '@' -f 1)
if [ -z "$user" ]
then
2010-01-20 16:19:02 +01:00
echo "Error! Missing user in email account." >&2
2010-01-20 14:53:09 +01:00
exit 1
fi
domain=$(echo "$1" | cut -d '@' -f 2)
if echo "$domain" | grep -E -v "^([[:alnum:]]+\.)+[[:alnum:]]+$" > /dev/null
then
2010-01-20 16:19:02 +01:00
echo "Error! Invalid domain for email account." >&2
2010-01-20 14:53:09 +01:00
exit 1
fi
}
2010-01-20 16:13:51 +01:00
# Ask a question to the user. Return 1 if the answer is negative,
# or 0 if it is positive.
2010-01-20 14:53:09 +01:00
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
}
2010-01-20 16:13:51 +01:00
# Test number of argument is correct and their value are correct also.
2010-01-20 14:53:09 +01:00
test_args ()
{
2010-01-20 17:14:16 +01:00
local - user domain
2010-01-26 19:14:51 +01:00
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)) ]
2010-01-20 14:53:09 +01:00
then
2010-01-20 16:19:02 +01:00
echo "Error! Too many arguments." >&2
2010-01-20 14:53:09 +01:00
exit 1
fi
2010-01-26 19:14:51 +01:00
# Test email arguments
eval test_email "\$$OPTIND"
emailuser="$user"
emaildomain="$domain"
if [ $# -eq $((OPTIND+1)) ]
2010-01-20 14:53:09 +01:00
then
2010-01-26 19:14:51 +01:00
eval test_email "\$$((OPTIND+1))"
aliasuser="$user"
aliasdomain="$domain"
if [ "$emaildomain" != "$aliasdomain" ]
2010-01-20 14:53:09 +01:00
then
2010-01-26 19:14:51 +01:00
echo "Error! Domain of the alias must be identical to the domain of the email account." >&2
exit 1
2010-01-20 14:53:09 +01:00
fi
fi
}
2010-01-20 16:13:51 +01:00
# Are we root?
2010-01-20 14:53:09 +01:00
must_sudo ()
{
uid="$(id -u)"
[ ! $uid -eq 0 ]
return $?
}
2010-01-20 16:13:51 +01:00
# This function tries to become root with sudo and execute this script.
# NB: This function doesn't return.
2010-01-20 14:53:09 +01:00
try_sudo ()
{
local - ret
echo "You aren't root. Trying to use sudo to become root…"
2010-01-20 16:13:51 +01:00
sudo $0 "$@" # Try to execute the script with sudo
2010-01-20 14:53:09 +01:00
ret=$?
if [ ! $ret -eq 0 ]
then
2010-01-20 16:19:02 +01:00
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
2010-01-20 14:53:09 +01:00
fi
exit $ret
}
2010-01-20 16:13:51 +01:00
# Test cyrus password is OK.
2010-01-20 14:53:09 +01:00
test_cyrus_admin ()
{
local -
2010-01-25 19:20:18 +01:00
cyruser=$(grep -E "^[[:blank:]]*admins:" /etc/imapd.conf | cut -d ':' -f 2- | sed -r "s/[[:alnum:]]+@[[:alnum:].]+//g" | tr -d ' ')
2011-02-05 17:49:33 +01:00
cyrpwd=$(cat /root/passwords/cyrus_main_admin_password)
2010-01-20 16:19:02 +01:00
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 ; }
2010-01-20 14:53:09 +01:00
}
2010-01-20 16:13:51 +01:00
# Ask a password to the user and create the entry in sasldb database.
2010-01-20 14:53:09 +01:00
ask_and_create_password ()
{
local - newemailpassword
emailpassword=""
newemailpassword="different"
while [ "$emailpassword" != "$newemailpassword" ]
do
emailpassword=""
2010-01-20 16:13:51 +01:00
echo "What password do you want for your email account?"
2010-01-20 14:53:09 +01:00
while [ -z "$emailpassword" ]
do
2010-01-20 16:13:51 +01:00
echo -n "Password: "
2010-01-20 14:53:09 +01:00
read emailpassword
done
newemailpassword=""
2010-01-20 16:13:51 +01:00
echo "Please re-enter your password to ensure you typed it correctly."
2010-01-20 14:53:09 +01:00
while [ -z "$newemailpassword" ]
do
2010-01-20 16:13:51 +01:00
echo -n "Password (bis): "
2010-01-20 14:53:09 +01:00
read newemailpassword
done
if [ "$emailpassword" != "$newemailpassword" ]
then
2010-01-20 16:13:51 +01:00
echo "Passwords don't match!"
2010-01-20 14:53:09 +01:00
fi
done
echo "$emailpassword" | saslpasswd2 -p -u "$emaildomain" "$emailuser"
}
2010-01-20 16:13:51 +01:00
# Check if a password already exists in the sasldb database.
2010-01-20 14:53:09 +01:00
# Then ask a password to the user and create the entry in sasldb
2010-01-20 16:13:51 +01:00
# database if password doesn't exist are user want to change it.
2010-01-20 14:53:09 +01:00
create_sasldb_password ()
{
local - first_ask next_ask
sasldblistusers2 | grep "$emailuser@$emaildomain" > /dev/null
if [ $? -eq 0 ]
then
2010-01-20 16:13:51 +01:00
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?"
2010-01-20 14:53:09 +01:00
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
2010-01-20 16:13:51 +01:00
# in cyrus and postfix if necessary.
2010-01-20 14:53:09 +01:00
update_virtual_domains ()
{
local -
2013-02-10 18:48:33 +01:00
grep "loginrealms:" /etc/imapd.conf | grep "$emaildomain" > /dev/null
2010-01-20 14:53:09 +01:00
if [ ! $? -eq 0 ]
then
2013-02-10 18:48:33 +01:00
sed -r -i "s/^([[:blank:]]*loginrealms): ?(.*)$/\1: $emaildomain \2/" /etc/imapd.conf
2010-01-20 14:53:09 +01:00
fi
2013-02-10 18:48:33 +01:00
grep -E "virtual_mailbox_domains[[:blank:]]*=" /etc/postfix/main.cf | grep "$emaildomain" /dev/null
2010-01-20 14:53:09 +01:00
if [ ! $? -eq 0 ]
then
2013-02-10 18:48:33 +01:00
sed -r -i "s/^([[:blank:]]*virtual_mailbox_domains[[:blank:]]*)= ?(.*)$/\1= $emaildomain \2/" /etc/postfix/main.cf
2010-01-20 14:53:09 +01:00
fi
}
# Print the first parameter and then the second parameter at a distance
2010-01-20 16:13:51 +01:00
# of $3 tabs.
2010-01-20 14:53:09 +01:00
echo_with_tabs ()
{
local - nbchars nbtabs
nbchars=$(echo "$1" | wc -m)
nbtabs=$(($3-nbchars/8))
2010-01-20 15:53:23 +01:00
[ $nbtabs -lt 1 ] && nbtabs=1
2010-01-20 14:53:09 +01:00
echo -n "$1"
for i in $(seq $nbtabs)
do
echo -n "\t"
done
echo "$2"
}
2010-01-20 16:13:51 +01:00
# Add requested alias to postfix virtual_alias_maps.
2010-01-20 14:53:09 +01:00
update_email_aliases ()
{
local -
2010-01-25 19:24:08 +01:00
grep -E "[[:blank:]]*$aliasuser@$aliasdomain[[:blank:]]+$emailuser@$emaildomain" /etc/postfix/virtual > /dev/null
2010-01-20 14:53:09 +01:00
if [ ! $? -eq 0 ]
then
echo_with_tabs "$aliasuser@$aliasdomain" "$emailuser@$emaildomain" 4 >> /etc/postfix/virtual
fi
2010-01-20 15:03:14 +01:00
postmap /etc/postfix/virtual
2010-01-20 14:53:09 +01:00
}
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
2010-01-20 16:13:51 +01:00
echo -n "Supported mechanism for imap authentification are: "
2010-01-20 14:53:09 +01:00
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
2010-01-20 16:13:51 +01:00
echo "."
2010-01-20 14:53:09 +01:00
}
2013-02-10 18:48:33 +01:00
# Ask Postfix and Cyrus to reload their configuration
reload_config ()
2010-01-20 14:53:09 +01:00
{
local -
2013-02-10 18:48:33 +01:00
invoke-rc.d --quiet cyrus2.2 reload
2010-01-20 14:53:09 +01:00
if [ ! $? -eq 0 ]
then
2013-02-10 18:48:33 +01:00
echo "Error! Cyrus failed to reload its configuration." >&2
2010-01-20 14:53:09 +01:00
exit 1
fi
2010-01-20 15:01:31 +01:00
invoke-rc.d --quiet postfix reload
2010-01-20 14:53:09 +01:00
if [ ! $? -eq 0 ]
then
2013-02-10 18:48:33 +01:00
echo "Error! Postfix failed to reload its configuration." >&2
2010-01-20 14:53:09 +01:00
exit 1
fi
}
# Create the mailbox
create_mail_account ()
{
local - nblines
2013-02-10 18:48:33 +01:00
nblines=$(echo "listmailbox user/$emailuser@$emaildomain" | cyradm --user $cyruser --pass $cyrpwd localhost | wc -l)
2010-01-20 14:53:09 +01:00
if [ $nblines -eq 0 ]
then
echo "Mailbox for $emailuser@$emaildomain doesn't exist, creating it…"
2013-02-10 18:48:33 +01:00
echo "createmailbox user/$emailuser@$emaildomain" | cyradm --user $cyruser --pass $cyrpwd localhost
2010-01-20 14:53:09 +01:00
fi
}
main ()
{
2010-01-26 11:15:39 +01:00
local - ret
2010-01-20 14:53:09 +01:00
# 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
2013-02-10 18:48:33 +01:00
create_sasldb_password
update_virtual_domains
aliasuser="${aliasuser:-""}"
if [ -n "$aliasuser" ]
2010-01-20 14:53:09 +01:00
then
2013-02-10 18:48:33 +01:00
update_email_aliases
2010-01-20 14:53:09 +01:00
fi
2013-02-10 18:48:33 +01:00
create_mail_account
display_infos
reload_config
return 0
2010-01-20 14:53:09 +01:00
}
2010-01-26 11:14:24 +01:00
main "${@:-""}"
2010-01-20 14:53:09 +01:00
exit $?