diff --git a/email_account/email_account b/email_account/email_account new file mode 100755 index 0000000..a0b3cce --- /dev/null +++ b/email_account/email_account @@ -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 $?