449 lines
14 KiB
Bash
Executable File
449 lines
14 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
## --------------------------------------
|
|
## -
|
|
## - Add mailboxes read from a flat file
|
|
## -
|
|
## --------------------------------------
|
|
|
|
script_dir="$(dirname $(realpath $0))"
|
|
|
|
log_dir="${script_dir}/log"
|
|
conf_dir="${script_dir}/conf"
|
|
file_dir="${script_dir}/files"
|
|
|
|
conf_file="${conf_dir}/postfix_add_mailboxes.conf"
|
|
|
|
tmp_err_msg="$(mktemp)"
|
|
|
|
|
|
## --- Default Settings
|
|
## ---
|
|
DEFAULT_db_type="pgsql"
|
|
DEFAULT_db_name="postfix"
|
|
DEFAULT_quota="536870912"
|
|
DEFAULT_dovecot_enc_method="SHA512-CRYPT"
|
|
DEFAULT_in_file="${file_dir}/mailboxes_new.lst"
|
|
DEFAULT_log_file="${script_dir}/log/postfix_add_mailboxes.log"
|
|
|
|
## --- some functions
|
|
## ---
|
|
clean_up() {
|
|
|
|
# Perform program exit housekeeping
|
|
rm -f $tmp_err_msg
|
|
exit $1
|
|
}
|
|
|
|
echononl(){
|
|
echo X\\c > /tmp/shprompt$$
|
|
if [ `wc -c /tmp/shprompt$$ | awk '{print $1}'` -eq 1 ]; then
|
|
echo -e -n "$*\\c" 1>&2
|
|
else
|
|
echo -e -n "$*" 1>&2
|
|
fi
|
|
rm /tmp/shprompt$$
|
|
}
|
|
|
|
fatal(){
|
|
echo ""
|
|
echo -e "[ \033[31m\033[1mError\033[m ]: $*"
|
|
echo ""
|
|
echo -e " \033[31m\033[1mInstalllation is canceled\033[m\033[m"
|
|
echo ""
|
|
clean_up 1
|
|
}
|
|
|
|
warn (){
|
|
echo ""
|
|
echo -e "\t[ \033[33m\033[1mWarning\033[m ]: $*"
|
|
echo ""
|
|
}
|
|
|
|
info (){
|
|
echo ""
|
|
echo -e "\t[ \033[33m\033[1mInfo\033[m ]: $*"
|
|
echo ""
|
|
}
|
|
|
|
ok (){
|
|
echo ""
|
|
echo -e "\t[ \033[36m\033[1mOk\033[m ]: $*"
|
|
echo ""
|
|
}
|
|
|
|
error(){
|
|
echo ""
|
|
echo -e "\t[ \033[31m\033[1mFehler\033[m ]: $*"
|
|
echo ""
|
|
}
|
|
|
|
echo_ok() {
|
|
echo -e "\033[75G[ \033[32mok\033[m ]"
|
|
}
|
|
echo_failed(){
|
|
echo -e "\033[75G[ \033[1;31mfailed\033[m ]"
|
|
}
|
|
echo_skipped() {
|
|
echo -e "\033[75G[ \033[33m\033[1mskipped\033[m ]"
|
|
}
|
|
|
|
|
|
## - remove leading/trailling whitespaces
|
|
## -
|
|
trim() {
|
|
local var="$*"
|
|
var="${var#"${var%%[![:space:]]*}"}" # remove leading whitespace characters
|
|
var="${var%"${var##*[![:space:]]}"}" # remove trailing whitespace characters
|
|
echo -n "$var"
|
|
}
|
|
|
|
## ---
|
|
## --- END: functions
|
|
|
|
date_suffix="`date +%Y%m%d-%H%M`"
|
|
|
|
echo ""
|
|
echo ""
|
|
echononl " Loading default Configuration values from $(basename ${conf_file}).."
|
|
if [[ ! -f "$conf_file" ]]; then
|
|
echo_skipped
|
|
else
|
|
source "${conf_file}" > /dev/null 2>&1
|
|
if [[ $? -eq 0 ]]; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
fi
|
|
fi
|
|
|
|
[[ -n "$db_type" ]] || db_type="$DEFAULT_db_type"
|
|
if [[ "$db_type" != "pgsql" ]] && [[ "$db_type" != "mysql" ]]; then
|
|
fatal "Unknown Database Type '$db_type' for Password Database (Parameter db_type)"
|
|
fi
|
|
|
|
if [[ "$db_type" = "mysql" ]]; then
|
|
if [[ -z "$mysql_credential_args" ]]; then
|
|
if [[ -f "/etc/mysql/debian.cnf" ]]; then
|
|
mysql_credential_args="--defaults-file=/etc/mysql/debian.cnf"
|
|
elif [[ -f "/usr/local/mysql/sys-maint.cnf" ]] ; then
|
|
mysql_credential_args="--defaults-file=/usr/local/mysql/sys-maint.cnf"
|
|
else
|
|
fatal "No credentials for access to MySQL is given!"
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
|
|
[[ -n "$db_name" ]] || db_name="$DEFAULT_db_name"
|
|
[[ -n "$quota" ]] || quota="$DEFAULT_quota"
|
|
[[ -n "$in_file" ]] || in_file="$DEFAULT_in_file"
|
|
[[ -n "$log_file" ]] || log_file="$DEFAULT_log_file"
|
|
[[ -n "$dovecot_enc_method" ]] || dovecot_enc_method="$DEFAULT_dovecot_enc_method"
|
|
|
|
|
|
if [[ ! -f "$in_file" ]];then
|
|
fatal "File containing the email/password pairs '$in_file' does not exist !!"
|
|
fi
|
|
|
|
echo ""
|
|
echo ""
|
|
echo -e "\033[32mSettings for script \033[37m\033[1msent_userinfo_postfix.sh\033[m"
|
|
echo ""
|
|
echo " File containing the new mailboxes and passwords.......: $in_file"
|
|
echo ""
|
|
echo " Passsword scheme used for encryption..................: $dovecot_enc_method"
|
|
echo " Mailbox quota to set for each new mailbox.............: $quota ($(echo "scale=2; 536870912 / 1024 /1024" | bc) MB)"
|
|
echo ""
|
|
if [[ "$db_type" = "pgsql" ]] ; then
|
|
echo " Type of postfix databae...............................: PostgreSQL ($db_type)"
|
|
echo " Database name for the postfix DB......................: $db_name"
|
|
elif [[ "$db_type" = "mysql" ]] ; then
|
|
echo " Type of postfix databae...............................: MySQL ($db_type)"
|
|
echo " Database name for the postfix DB......................: $db_name"
|
|
echo " MySQL credential args.................................: $mysql_credential_args"
|
|
fi
|
|
if [[ "$db_type" = "mysql" ]] ; then
|
|
echo " Type of postfix databae...............................: MySQL ($db_type)"
|
|
fi
|
|
|
|
|
|
echo ""
|
|
OK=
|
|
while [ "$OK" != "yes" -o "$OK" != "no" ] ; do
|
|
echononl "\033[1mParameters ok? [yes/no]:\033[m "
|
|
read OK
|
|
## - To lower case
|
|
OK=${OK,,}
|
|
if [ "X$OK" = "X" ]; then
|
|
echo -e "\n\t\033[33m\033[1mAn entry is required!\033[m\n"
|
|
OK=""
|
|
continue
|
|
fi
|
|
if [ "$OK" != "yes" -o "$OK" != "no" ] ; then
|
|
break
|
|
fi
|
|
echo -e "\n\t\033[33m\033[1mWrong entry!\033[m\n"
|
|
done
|
|
[[ $OK = "yes" ]] || fatal "Repeat execution with different parameters."
|
|
|
|
|
|
echo ""
|
|
echononl " Create log directory '$(dirname "$log_file")'.."
|
|
if [[ ! -d "$(dirname "$log_file")" ]] ; then
|
|
mkdir "$(dirname "$log_file")"
|
|
if [[ $? -eq 0 ]]; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
fi
|
|
else
|
|
echo_skipped
|
|
fi
|
|
|
|
|
|
echo
|
|
|
|
## -
|
|
## - Logfile
|
|
## -
|
|
echononl " Backup existing log file.."
|
|
if [ -f "$log_file" ]; then
|
|
mv "$log_file" "${log_file}.${date_suffix}"
|
|
if [ "$?" = "0" ]; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
fi
|
|
else
|
|
echo_skipped
|
|
fi
|
|
|
|
echononl " Create log file $log_file.."
|
|
touch $log_file
|
|
if [ "$?" = "0" ]; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
fi
|
|
|
|
echo ""
|
|
|
|
curdir=`pwd`
|
|
cd /tmp
|
|
|
|
|
|
while read email passwd ; do
|
|
|
|
## - get rid of empty lines
|
|
[[ -z "$email" ]] && continue
|
|
## - get rid of comment lines
|
|
[[ $email =~ ^[[:space:]]*# ]] && continue
|
|
|
|
## - remove leading/trailling whitespaces
|
|
## -
|
|
email=`trim "$email"`
|
|
password=`trim $passwd`
|
|
|
|
## - regex tha email addresses must matc
|
|
## -
|
|
#regex_email="^[a-z0-9!#\$%&'*+/=?^_\`{|}~-]+(\.[a-z0-9!#$%&'*+/=?^_\`{|}~-]+)*@([a-z0-9]([a-z0-9-]*[a-z0-9])?\.)+[a-z0-9]([a-z0-9-]*[a-z0-9])?\$"
|
|
regex_email="^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$"
|
|
|
|
if [[ ! $email =~ $regex_email ]]; then
|
|
error "email: give e-mail address ($email) is NOT VALID"
|
|
echo "[ FAILED ]: The given e-mail address \"${user}@$domain\" is not VALID" >> $log_file
|
|
continue
|
|
fi
|
|
|
|
## - splitt in name and domain part
|
|
## -
|
|
read user domain <<<$(IFS="@" ; echo $email)
|
|
|
|
echo
|
|
echo -e " \033[37m\033[1mHandling E-Mail addess ${user}@${domain}..\033[m"
|
|
|
|
## - check if domain is already configured
|
|
## -
|
|
if [[ "$db_type" = "pgsql" ]] ; then
|
|
domain_exists=`su postgres -c"psql $db_name -At -c\"SELECT 1 FROM domain WHERE domain = '$domain'\""`
|
|
elif [[ "$db_type" = "mysql" ]] ; then
|
|
domain_exists="$(mysql "$mysql_credential_args" "$db_name" \
|
|
-N -s -e"SELECT 1 FROM domain WHERE domain = '$domain'")"
|
|
else
|
|
fatal "Database type '$db_type' is not supported."
|
|
fi
|
|
if [[ "X$domain_exists" = "X" ]] ; then
|
|
warn "Domain $domain is not configured as maildomain."
|
|
echo "[ FAILED ]: Cannot create e-mail address \"${user}@$domain\"" >> $log_file
|
|
echo " Domain $domain is not configured as maildomain." >> $log_file
|
|
continue
|
|
fi
|
|
|
|
if [[ "$user" = "abuse" ]]; then
|
|
warn "E-mail address $email is not supported"
|
|
echo "[ FAILED ]: Cannot create e-mail address \"${user}@$domain\"" >> $log_file
|
|
echo " E-mail address $email is not supported." >> $log_file
|
|
continue
|
|
elif [[ "$user" = "postmaster" ]];then
|
|
warn "E-mail address $email is not supported"
|
|
echo "[ FAILED ]: Cannot create e-mail address \"${user}@$domain\"" >> $log_file
|
|
echo " E-mail address $email is not supported." >> $log_file
|
|
continue
|
|
fi
|
|
|
|
## - If password is not given, then take a default
|
|
## -
|
|
if [[ -z "$passwd" ]]; then
|
|
if [[ -z "$_passwd" ]]; then
|
|
password_accepted=false
|
|
while ! $password_accepted ; do
|
|
passwd=`tr -cd '[:alnum:]#_\!\%/=@-' < /dev/urandom | tr '0' 'O' | fold -w12 | head -n1`
|
|
regex="[#_\!\%/=@-]"
|
|
[[ $passwd =~ $regex ]] || continue
|
|
regex="[123456789].*[123456789]"
|
|
[[ $passwd =~ $regex ]] || continue
|
|
password_accepted=true
|
|
done
|
|
else
|
|
passwd=$_passwd
|
|
fi
|
|
fi
|
|
|
|
if [[ "$db_type" = "pgsql" ]] ; then
|
|
mb_exists=`su postgres -c"psql $db_name -At -c\"SELECT 1 FROM mailbox WHERE username = '${user}@$domain'\""`
|
|
elif [[ "$db_type" = "mysql" ]] ; then
|
|
mb_exists="$(mysql "$mysql_credential_args" "$db_name" \
|
|
-N -s -e"SELECT 1 FROM mailbox WHERE username = '${user}@$domain'")"
|
|
else
|
|
fatal "Database type '$db_type' is not supported."
|
|
fi
|
|
if [[ "X$mb_exists" == "X1" ]] ; then
|
|
warn "A Mailbox ${user}@$domain already exists."
|
|
echo "[ FAILED ]: Cannot create e-mail address \"${user}@$domain\"" >> $log_file
|
|
echo " A Mailbox ${user}@$domain already exists." >> $log_file
|
|
continue
|
|
fi
|
|
|
|
if [[ "$db_type" = "pgsql" ]] ; then
|
|
alias_exists=`su postgres -c"psql $db_name -At -c\"SELECT 1 FROM alias WHERE address = '${user}@$domain'\""`
|
|
elif [[ "$db_type" = "mysql" ]] ; then
|
|
alias_exists="$(mysql "$mysql_credential_args" "$db_name" \
|
|
-N -s -e"SELECT 1 FROM alias WHERE address = '${user}@$domain'")"
|
|
else
|
|
fatal "Database type '$db_type' is not supported."
|
|
fi
|
|
if [[ "X$alias_exists" == "X1" ]] ; then
|
|
warn "A Forwarding Address ${user}@$domain already exists."
|
|
echo "[ FAILED ]: Cannot create e-mail address \"${user}@$domain\"" >> $log_file
|
|
echo " A Forwarding Address ${user}@$domain already exists." >> $log_file
|
|
continue
|
|
fi
|
|
|
|
echononl " Create entry in table \"mailbox\".."
|
|
|
|
if [[ "$db_type" = "pgsql" ]] ; then
|
|
if [[ "$dovecot_enc_method" = "PLAIN" ]]; then
|
|
sudo -u postgres psql $db_name -c "\
|
|
SET client_encoding to 'UTF8'; \
|
|
INSERT INTO mailbox (username,password,name,maildir,local_part,quota,domain,created,modified,active) \
|
|
VALUES ('${user}@$domain', '$passwd','','${domain}/${user}/','$user','$quota','$domain',NOW(),NOW(),'t')" \
|
|
> $tmp_err_msg 2>&1
|
|
else
|
|
sudo -u postgres psql $db_name -c "\
|
|
SET client_encoding to 'UTF8'; \
|
|
INSERT INTO mailbox (username,password,name,maildir,local_part,quota,domain,created,modified,active) \
|
|
VALUES ('${user}@$domain', '$(doveadm pw -s "$dovecot_enc_method" -p "$passwd")','','${domain}/${user}/','$user','$quota','$domain',NOW(),NOW(),'t')" \
|
|
> $tmp_err_msg 2>&1
|
|
fi
|
|
elif [[ "$db_type" = "mysql" ]] ; then
|
|
if [[ "$dovecot_enc_method" = "PLAIN" ]]; then
|
|
$(mysql "$mysql_credential_args" "$db_name" -N -s -e"
|
|
SET NAMES utf8;
|
|
INSERT INTO mailbox (username,password,name,maildir,local_part,quota,domain,created,modified,active)
|
|
VALUES ('${user}@$domain', '$passwd','','${domain}/${user}/','$user','$quota','$domain',NOW(),NOW(),1)" \
|
|
> $tmp_err_msg 2>&1)
|
|
else
|
|
$(mysql "$mysql_credential_args" "$db_name" -N -s -e"
|
|
SET NAMES utf8;
|
|
INSERT INTO mailbox (username,password,name,maildir,local_part,quota,domain,created,modified,active)
|
|
VALUES ('${user}@$domain', '$(doveadm pw -s "$dovecot_enc_method" -p "$passwd")','','${domain}/${user}/','$user','$quota','$domain',NOW(),NOW(),1)" \
|
|
> $tmp_err_msg 2>&1)
|
|
fi
|
|
else
|
|
fatal "Database type '$db_type' is not supported."
|
|
fi
|
|
|
|
if [ "$?" = "0" ]; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
error "$(cat "$tmp_err_msg")"
|
|
echo "[ FAILED ]: Cannot create e-mail address \"${user}@$domain\"" >> $log_file
|
|
continue
|
|
fi
|
|
|
|
echononl " Create entry in table \"alias\".."
|
|
if [[ "$db_type" = "pgsql" ]] ; then
|
|
sudo -u postgres psql $db_name -c "\
|
|
SET client_encoding to 'UTF8'; \
|
|
INSERT INTO alias (address,goto,domain,created,modified) \
|
|
VALUES ('${user}@$domain','${user}@$domain','$domain',NOW(),NOW())" > $tmp_err_msg 2>&1
|
|
elif [[ "$db_type" = "mysql" ]] ; then
|
|
$(mysql "$mysql_credential_args" "$db_name" -N -s -e"
|
|
SET NAMES utf8;
|
|
INSERT INTO alias (address,goto,domain,created,modified)
|
|
VALUES ('${user}@$domain','${user}@$domain','$domain',NOW(),NOW())" \
|
|
> $tmp_err_msg 2>&1)
|
|
else
|
|
fatal "Database type '$db_type' is not supported."
|
|
fi
|
|
if [ "$?" = "0" ]; then
|
|
echo_ok
|
|
echo -e " email: ${user}@$domain"
|
|
echo -e " password: $passwd"
|
|
echo "[ OK ]: e-mail: ${user}@$domain -- password: $passwd" >> $log_file
|
|
else
|
|
echo_failed
|
|
echo "[ FAILED ]: Cannot create e-mail address \"${user}@$domain\"" >> $log_file
|
|
echo " Note: Entry in table \"alias\" was done; Take care, to" >> $log_file
|
|
echo " remove that Entry." >> $log_file
|
|
fi
|
|
|
|
# - Test imap connection on the new mailbox using curl
|
|
# -
|
|
# - Note: turn off history expansion (set +H), to prevent the shell from
|
|
# - interpreting sign "!"
|
|
# -
|
|
set +H
|
|
echononl " Test imap connection to mailbox '${user}@$domain'.."
|
|
curl --url "imap://127.0.0.1" --user "${user}@$domain:${passwd}" > $tmp_err_msg 2>&1
|
|
if [[ $? -ne 0 ]]; then
|
|
echo_failed
|
|
error "Testing an imap connection failed\n\t $(cat "$tmp_err_msg")"
|
|
echo "[ FAILED ]: Testing an imap connection failed!"
|
|
else
|
|
echo_ok
|
|
fi
|
|
set -H
|
|
|
|
done < $in_file
|
|
|
|
echo ""
|
|
echo ""
|
|
echononl "\tMove file '$in_file'.."
|
|
mv "$in_file" "${in_file}.ADDED.$(date +%Y-%m-%d)"
|
|
if [[ $? -eq 0 ]]; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
fi
|
|
|
|
echo
|
|
echo -e "See \033[37m\033[1m$log_file\033[m to see the results again."
|
|
echo ""
|
|
|
|
cd $pwd
|
|
|
|
clean_up 0
|