From d811cbfbd16ecb4bd5c22ab5d682204704668f45 Mon Sep 17 00:00:00 2001 From: Christoph Date: Sat, 12 Jul 2025 11:10:17 +0200 Subject: [PATCH] Backup 'BAK/install_update_dovecot.sh' bevor uploading a new one. --- BAK/install_update_dovecot.sh.00 | 4554 ++++++++++++++++++++++++++++++ 1 file changed, 4554 insertions(+) create mode 100755 BAK/install_update_dovecot.sh.00 diff --git a/BAK/install_update_dovecot.sh.00 b/BAK/install_update_dovecot.sh.00 new file mode 100755 index 0000000..d99a404 --- /dev/null +++ b/BAK/install_update_dovecot.sh.00 @@ -0,0 +1,4554 @@ +#!/usr/bin/env bash + +## =================================================================== +## - Install/Update Dovecot Server +## =================================================================== + + +## ----------------------------------------------------------------- +## ---------------------------------------------------------------- +## --- +## --- For configurations see file conf/install_update_dovecot.conf +## --- +## --- Dont make changes here! +## --- +## ----------------------------------------------------------------- +## ----------------------------------------------------------------- + +# ------------- +# - Settings +# ------------- + +_src_base_dir="$(realpath $(dirname $0))" +conf_file="${_src_base_dir}/conf/install_update_dovecot.conf" +curdir=`pwd` + +log_file="$(mktemp)" + +backup_date="$(date +%Y-%m-%d-%H%M)" + +_backup_crontab_file="/tmp/crontab_root.${backup_date}" + +rc_done="\033[71G[ \033[32mdone\033[m ]" +rc_failed="\033[71G[ \033[31m\033[1mfailed\033[m ]" +rc_skipped="\033[71G[ \033[33m\033[1mskipped\033[m ]" +rc_wait="\033[71G[ \033[5m\033[1m..\033[m ]" + + +# ------------- +# - Functions an Variable +# ------------- +clean_up() { + + + if [[ -f "$_backup_crontab_file" ]]; then + + echononl "(Re)Install previously saved crontab from '$_backup_crontab_file'.." + + crontab $_backup_crontab_file >> $log_file 2>&1 + + if [[ $? -eq 0 ]]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + error "$(cat $log_file)" + fi + + fi + + # Perform program exit housekeeping + rm -f $log_file + blank_line + exit $1 +} + + +echononl(){ + echo X\\c > /tmp/shprompt$$ + if [ `wc -c /tmp/shprompt$$ | awk '{print $1}'` -eq 1 ]; then + echo -e "$*\\c" 1>&2 + else + echo -en "$*" 1>&2 + fi + rm /tmp/shprompt$$ +} + +fatal(){ + echo "" + echo -e "\t[ \033[31m\033[1mFatal\033[m ]: \033[37m\033[1m$*\033[m" + echo "" + echo -e "\t\033[31m\033[1m Skript wird abgebrochen\033[m\033[m\n" + rm -f $log_file + clean_up 1 +} + +error(){ + echo "" + echo -e "\t[ \033[31m\033[1mError\033[m ]: $*" + echo "" +} + +warn(){ + echo "" + echo -e "\t[ \033[33m\033[1mWarning\033[m ]: $*" + echo "" +} + +info(){ + echo "" + echo -e "\t[ \033[32m\033[1mInfo\033[m ]: $*" + echo "" +} + + +blank_line() { + echo "" +} + +echo_ok() { + echo -e "\033[71G[ \033[32mok\033[m ]" +} +echo_failed(){ + echo -e "\033[71G[ \033[1;31mfailed\033[m ]" +} +echo_skipped() { + echo -e "\033[71G[ \033[33m\033[1mskipped\033[m ]" +} + +detect_os_1 () { + + if $(which lsb_release > /dev/null 2>&1) ; then + + os_dist="$(lsb_release -i | awk '{print tolower($3)}')" + os_version="$(lsb_release -r | awk '{print tolower($2)}')" + os_codename="$(lsb_release -c | awk '{print tolower($2)}')" + + if [[ "$os_dist" = "debian" ]]; then + if $(echo "$os_version" | grep -q '\.') ; then + os_version=$(echo "$os_version" | cut --delimiter='.' -f1) + fi + fi + + elif [[ -e "/etc/os-release" ]]; then + + . /etc/os-release + + os_dist=$ID + os_version=${VERSION_ID} + + fi + + # remove whitespace from os_dist and os_version + os_dist="${os_dist// /}" + os_version="${os_version// /}" + +} + + + +# - Support systemd ? +# - +if [[ "X$(which systemd)" = "X" ]]; then + SYSTEMD_EXISTS=false +else + SYSTEMD_EXISTS=true +fi + +if [[ -f "/usr/local/mysql/sys-maint.cnf" ]] ; then + DEFAULT_MYSQL_CREDENTIALS="--defaults-file=/usr/local/mysql/sys-maint.cnf" +elif [[ -f "/etc/mysql/debian.cnf" ]] ; then + DEFAULT_MYSQL_CREDENTIALS="--defaults-file=/etc/mysql/debian.cnf" +else + DEFAULT_MYSQL_CREDENTIALS="" +fi + + +# - Detect OS - Set variable +# - os_dist +# - os_version +# - os_codename +# - +detect_os_1 + + +echo +echononl "\tInclude Configuration file.." +if [[ ! -f $conf_file ]]; then + echo -e "$rc_failed" + fatal "Missing configuration file '$conf_file'" +else + source $conf_file + echo -e "$rc_done" +fi + +if [[ -z "$systemd_support" ]] ; then + if $SYSTEMD_EXISTS ; then + systemd_support=true + else + systemd_support=false + fi +fi + +## - Required parameters +## - +[[ -n "$_update" ]] || fatal "Parameter "_update" not set." +[[ -n "$postmaster_address" ]] || postmaster_address="argus\@oopen.de" +[[ -n "$hostname" ]] || fatal "Missing value for parameter 'hostname'." +[[ -n "$ipv4" ]] || fatal "Missing value for parameter 'ipv4'." +[[ -n "$ipv6" ]] || warn "Missing value for parameter 'ipv6'." + +[[ -n "$database" ]] || fatal "Parameter "database" not set." + +if [[ "$database" != "postgres" ]] && [[ "$database" != "mysql" ]] ; then + fatal "Wrong value for parameter 'database' ({$database}). Only 'mysql' or 'postgres' is allowed." +fi +[[ -n "$dbpassword" ]] || fatal "Parameter "dbpassword" not set." + +[[ -n "$from_address" ]] || fatal ""Parameter "from_address" not set."" +[[ -n "$reply_to" ]] || fatal ""Parameter "reply_to" not set."" +[[ -n "$webmailer" ]] || fatal ""Parameter "webmailer" not set."" +[[ -n "$salutation" ]] || fatal ""Parameter "salutation" not set."" + +## - Some defaults if missing +## - +if [[ -n "$ipv6" ]] ; then + [[ -n "$imap_listener_adresses" ]] || imap_listener_adresses="127.0.0.1 $ipv4 $ipv6" + [[ -n "$imaps_listener_adresses" ]] || imaps_listener_adresses="127.0.0.1 $ipv4 $ipv6" + + [[ -n "$pop_listener_adresses" ]] || pop_listener_adresses="$ipv4 $ipv6" + [[ -n "$pops_listener_adresses" ]] || pops_listener_adresses="127.0.0.1 $ipv4 $ipv6" +else + [[ -n "$imap_listener_adresses" ]] || imap_listener_adresses="127.0.0.1 $ipv4" + [[ -n "$imaps_listener_adresses" ]] || imaps_listener_adresses="127.0.0.1 $ipv4" + + [[ -n "$pop_listener_adresses" ]] || pop_listener_adresses="$ipv4" + [[ -n "$pops_listener_adresses" ]] || pops_listener_adresses="127.0.0.1 $ipv4" +fi + +[[ -n "$xmpp_listener" ]] || xmpp_listener=false + +if $xmpp_listener ; then + # Be compartible with older installations + [[ -n "$xmpp_listener_address" ]] && xmpp_listener_addresses="$xmpp_listener_address" + [[ -n "$xmpp_listener_addresses" ]] || xmpp_listener_addresses="127.0.0.1 $ipv4" + [[ -n "$xmpp_listener_port" ]] || xmpp_listener_port="44444" +fi + +[[ -n "$http_user" ]] || http_user="www-data" +[[ -n "$postfix_main_cf" ]] || postfix_main_cf="/etc/postfix/main.cf" + +[[ -n "$dbname" ]] || dbname="postfix" +[[ -n "$dbuser" ]] || dbuser="postfix" +if [[ -z "$dbhost" ]] ; then + [[ "$database" = "mysql" ]] && dbhost="/run/mysqld/mysqld.sock" + [[ "$database" = "postgres" ]] && dbhost="/run/postgresql" +fi + +[[ -n "$cert_base_dir" ]] || cert_base_dir="/etc/dovecot/ssl" +[[ -n "$server_cert" ]] || server_cert="${cert_base_dir}/mailserver.crt" +[[ -n "$server_key" ]] || server_key="${cert_base_dir}/mailserver.key" +[[ -n "$dh_pem_file" ]] || dh_pem_file="${cert_base_dir}/dh_4096.pem" + +[[ -n "$imap_cert" ]] || imap_cert="${cert_base_dir}/mailserver.crt" +[[ -n "$imap_key" ]] || imap_key="${cert_base_dir}/mailserver.key" + +[[ -n "$pop_cert" ]] || pop_cert="${cert_base_dir}/mailserver.crt" +[[ -n "$pop_key" ]] || pop_key="${cert_base_dir}/mailserver.key" + +[[ -n "$default_pass_scheme" ]] || default_pass_scheme="PLAIN" + +[[ -n "$spam_folder" ]] || spam_folder="Spam" + +[[ -n "$max_userip_connections" ]] || max_userip_connections=24 +[[ -n "$auth_mechanisms" ]] || auth_mechanisms="plain login" + +[[ -n "$service_limit_nofile" ]] || service_limit_nofile=524280 + +declare -i dovecot_major_version=0 +declare -i dovecot_minor_version=0 +declare -i dovecot_patch_level=0 + +echo -e "\033[32m--\033[m" +echo "" +echo "Version Number of Dovecot to install" +echo "" +echo "" +_version= +while [ "X$_version" = "X" ] +do + echononl "Dovecot Version: " + read _version + if [ "X$_version" = "X" ]; then + echo -e "\n\t\033[33m\033[1mA version number is required!\033[m\n" + fi +done + +dovecot_main_version="$(echo $_version | cut -d '.' -f1,2)" +dovecot_major_version="$(echo $_version | cut -d '.' -f1)" +dovecot_minor_version="$(echo $_version | cut -d '.' -f2)" +dovecot_patch_level="$(echo $_version | cut -d '.' -f3)" + +#echo "" +#echo "_version: $_version" +#echo "dovecot_main_version $dovecot_main_version" +#echo "dovecot_major_version $dovecot_major_version" +#echo "dovecot_minor_version $dovecot_minor_version" +#echo "dovecot_patch_level $dovecot_patch_level" +#echo "" + +# 'expire plugin'was rRemoved in version 2.3.14: This plugin is not needed. +# Use mailbox { autoexpunge } Mailbox settings instead. +# +if [[ $dovecot_major_version -gt 2 ]] \ + || ( [[ $dovecot_major_version -eq 2 ]] \ + && [[ $dovecot_minor_version -gt 3 ]] \ + ) \ + || ( [[ $dovecot_major_version -eq 2 ]] \ + && [[ $dovecot_minor_version -eq 3 ]] \ + && [[ $dovecot_patch_level -gt 13 ]] \ + ) ; then + plugin_expire=false +else + plugin_expire=true +fi + +#if $plugin_expire ; then +# info "Install plugin 'expire'.." +#else +# warn "Plugin 'expire' is no longer supported.." +#fi + +#exit 0 + +_log_dir=${_src_base_dir}/log-dovecot-$_version + +echo "" +echo -e "\033[32m--\033[m" +echo "" +echo "Version Number of Pigeonhole to install" +echo "" +echo "" +_pigeonhole= +while [ "X$_pigeonhole" = "X" ] +do + echononl "Pigeonhole Version: " + read _pigeonhole + if [ "X$_pigeonhole" = "X" ]; then + echo -e "\n\t\033[33m\033[1mA version number is required!\033[m\n" + fi +done + + +echo "" +echo -e "\033[32m--\033[m" +echo "" +echo "Is this a fresh new installation or an update?" +echo "" +echo "" +if [[ -n "$_update" ]]; then + if $_update || [[ "${_update,,}" = 'yes' ]] ; then + echo -e "\033[37m\033[1m[1] Update\033[m" + echo "[2] New Installation" + else + echo -e "[1] Update" + echo -e "\033[37m\033[1m[2] New Installation\033[m" + fi + echo "" + echononl "Choose a number or press for highlighted value: " +else + echo -e "[1] Update" + echo "[2] New Installation" + echo "" + echononl "Choose a Number: " +fi +update="" +while [[ "$update" != "true" && "$update" != "false" ]] ; do + read OPTION + case $OPTION in + 1) update=true + ;; + 2) update=false + ;; + '') if [[ -n "$_update" ]] ; then + if $_update || [[ "${_update,,}" = 'yes' ]] ; then + update=true + else + update=false + fi + else + echo "" + echo -e "\tWrong entry! [ 1 = Update ; 2 = New Installation ]" + echo "" + echononl "Reentry: " + fi + ;; + *) update="" + echo "" + if [[ -n "$_IS_RELAY_HOST" ]]; then + echo -e "\tWrong entry! [ 1 = Update ; 2 = New Installation ] or type " + else + echo -e "\tWrong entry! [ 1 = Update ; 2 = New Installation ]" + fi + echo "" + echononl "Reentry: " + ;; + esac +done + + + + +# ------------- +# - List Script Configurations +# ------------- + + +clear; + +echo "" +if $update ;then + echo -e "\tUpdate Dovecot................: $update" +else + echo -e "\tInstall Dovecot first time....: Yes" +fi +echo "" +echo -e "\tDovecot (new) version.........: $_version" +echo -e "\t(Sieve) pigeonhole version....: $_pigeonhole" +echo "" +echo -e "\tSystemd support...............: $systemd_support" +echo "" +echo -e "\tSFolder containing sources....: $_src_base_dir" +echo "" +echo -e "\tPostmaser adress..............: $postmaster_address" +echo -e "\tHostname......................: $hostname" +echo "" +echo -e "\tIPv4 address..................: $ipv4" +echo -e "\tIPv6 address..................: $ipv6" +echo "" +echo -e "\tIMAP listener addresses.......: $imap_listener_adresses" +echo -e "\tIMAPS listener addresses......: $imaps_listener_adresses" +echo "" +echo -e "\tPOP3 listener addresses.......: $pop_listener_adresses" +echo -e "\tPOP3S listener addresses......: $pops_listener_adresses" +echo "" +echo -e "\tPostfix Configuration File....: $postfix_main_cf" +echo "" +echo -e "\tDatenbank.....................: $database" +echo "" +echo -e "\tPostfix database host.........: $dbhost" +echo -e "\tPostfix database name.........: $dbname" +echo -e "\tPostfix database user.........: $dbuser" +echo -e "\tPostfix database password.....: $dbpassword" +echo "" +echo -e "\tDefault password scheme.......: $default_pass_scheme" +echo "" +echo -e "\tCertificat base directory.....: $cert_base_dir" +echo -e "\tServer certificate............: $server_cert" +echo -e "\tServer key....................: $server_key" +if [[ $dovecot_major_version -ge 3 ]] \ + || ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -ge 3 ]] ); then + echo -e "\tDH Parameters file............: $dh_pem_file" +fi +echo "" +echo -e "\tImap certificate..............: $imap_cert" +echo -e "\tImap key......................: $imap_key" +echo "" +echo -e "\tPop certificate...............: $pop_cert" +echo -e "\tPop key.......................: $pop_key" +echo "" + +echo -e "\tSpan folder...................: $spam_folder" +echo -e "\tMax user connections per ip...: $max_userip_connections" +echo "" +echo -e "\tAuth Listener (Jabber)........: $xmpp_listener" +if $xmpp_listener ; then + echo -e "\t Auth Listener Addresses....: $xmpp_listener_addresses" + echo -e "\t AUTH Listener PORT.........: $xmpp_listener_port" +fi +echo "" +echo -e "\tInstall Plugin 'expire'.......: $plugin_expire" +echo "" + +if ! $update ;then + if [[ "$database" = "psql" ]] || [[ "$database" = "postgres" ]]; then + warn "Take care, your PostgreSQL configuration (pg_hba.conf) contains the following line:\n\n\t pg_hba.conf:\n\t \033[1mlocal all postfix trust\033[m" + fi +fi + +echononl "Sind die Angaben richtig [ja/nein]: " +read OK +while [ "X$OK" != "Xyes" -a "X$OK" != "XYes" -a "X$OK" != "Xja" -a "X$OK" != "XJa" \ + -a "X$OK" != "XNo" -a "X$OK" != "Xno" -a "X$OK" != "Xn" -a "X$OK" != "Xnein" -a "X$OK" != "XNein" ] +do + echononl "falsche Angabe! [ja/nein] :" + read OK +done + +[ $OK = "Yes" -o $OK = "yes" -o "$OK" = "ja" -o "$OK" = "Ja" ] || fatal "Edit '$(basename $conf_file)' and correct variables" + + +## - Let make use multiple cores (-j) +## - +export MAKEFLAGS=-j$(expr `grep "^processor" /proc/cpuinfo | sort -u | wc -l` - 1) + + +# ------------- +# - Begin Install/Update +# ------------- + +echo "" + +if $update ;then + _new=false; +else + _new=true; +fi + +if [ "$database" = "mysql" ]; then + db_driver=mysql +else + db_driver=pgsql +fi + +if $_new ; then + if [ "$database" = "mysql" ]; then + + echo "" + echo "--" + echo "" + echo "Gib MySQL credentials für den root user an.." + echo "" + echo "Possible values could be:" + echo " -u root -p" + echo " -u root -S /run/mysqld/mysqld.sock" + echo " --login-path=local" + echo " --defaults-file=/usr/local/mysql/sys-maint.cnf" + echo " --defaults-file=/etc/mysql/debian.cnf" + echo " ..." + echo "" + echo -e " Type \"\033[33mNone\033[m\" if no credentials are needed for root user (MariaDB)" + echo "" + MYSQL_CREDENTIALS="" + if [[ -n "${DEFAULT_MYSQL_CREDENTIALS}" ]] ; then + while [[ -z "${MYSQL_CREDENTIALS}" ]] ; do + echononl "MySQL credentials [${DEFAULT_MYSQL_CREDENTIALS}]: " + read MYSQL_CREDENTIALS + if [[ -z "${MYSQL_CREDENTIALS}" ]] ;then + MYSQL_CREDENTIALS="${DEFAULT_MYSQL_CREDENTIALS}" + fi + done + else + while [[ -z "${MYSQL_CREDENTIALS}" ]] ; do + echononl "MySQL credentials: " + read MYSQL_CREDENTIALS + if "${MYSQL_CREDENTIALS}" ]] ; then + echo -e "\n\t\033[33m\033[1mMySQL credentials are required (or type\033[33mNone\033[m) : " + continue + fi + if [[ "$(trim ${MYSQL_CREDENTIALS,,})" = 'none' ]] ; then + MYSQL_CREDENTIALS="" + break + fi + done + fi + echo "" + echo "--" + echo "" + echo "" + +# echo "" +# echo "--" +# echo "" +# echo "Gib den Benutzernamen des/eines MySQL root user an.." +# echo "" +# _MYSQL_ROOT_USER=root +# MYSQL_ROOT_USER= +# while [ "X$MYSQL_ROOT_USER" = "X" ] +# do +# echononl "MySQL-User [${_MYSQL_ROOT_USER}]: " +# read MYSQL_ROOT_USER +# if [ "X$MYSQL_ROOT_USER" = "X" ]; then +# MYSQL_ROOT_USER=$_MYSQL_ROOT_USER +# fi +# done +# +# +# echo "" +# echo "--" +# echo "" +# echo "Gib ein Passwort für den root user an.." +# echo "" +# _MYSQL_ROOT_PW_1="X" +# _MYSQL_ROOT_PW_2="Y" +# while [ "$_MYSQL_ROOT_PW_1" != "$_MYSQL_ROOT_PW_2" ] +# do +# echononl "Passworteingabe: " +# read -s _MYSQL_ROOT_PW_1 +# echo +# if [ "X$_MYSQL_ROOT_PW_1" = "X" ]; then +# echo -e "\n\t\033[33m\033[1mPassworteingabe erforderlich!\033[m\n" +# continue +# fi +# echononl "Passwortwiederholung: " +# read -s _MYSQL_ROOT_PW_2 +# echo +# if [ "X$_MYSQL_ROOT_PW_2" = "X" ]; then +# echo -e "\n\t\033[33m\033[1mPasswortwiederholung erforderlich!\033[m\n" +# continue +# fi +# if [ "$_MYSQL_ROOT_PW_1" != "$_MYSQL_ROOT_PW_2" ];then +# echo -e "\n\t\033[33m\033[1mPassworteingaben sind nicht identisch!\033[m\n" +# else +# MYSQL_ROOT_PW=$_MYSQL_ROOT_PW_1 +# fi +# done +# MYSQL_CREDENTIALS="-u ${MYSQL_ROOT_USER} -p${MYSQL_ROOT_PW}" + fi +fi + +export PGPASSWORD=$dbpassword + + +echo -e "\033[1mDoing some backups\033[m.." + +echononl "\tBackup existing installation log directory.." +if [[ -d "${_log_dir}" ]]; then + mv "${_log_dir}" "${_log_dir}.${backup_date}" + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + error "Cannot Backup (move) directory '${_log_dir}'" + fi +else + echo -e "$rc_skipped" +fi + +echononl "\tBackup existing installation directory.." +if [[ -d "/usr/local/dovecot-${_version}" ]]; then + mv "/usr/local/dovecot-${_version}" "/usr/local/dovecot-${_version}.${backup_date}" + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + error "Cannot Backup (move) directory '${_log_dir}'" + + echononl "Proceed instllation [yes/no]: " + read OK + OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')" + while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do + echononl "Wrong entry! - repeat [yes/no]: " + read OK + done + [[ $OK = "yes" ]] || fatal "Abbruch durch User" + + fi +else + echo -e "$rc_skipped" +fi + +echononl "\tBackup existing source directory.." +if [[ -d "${_src_base_dir}/dovecot-${_version}" ]]; then + mv "${_src_base_dir}/dovecot-${_version}" "${_src_base_dir}/dovecot-${_version}.${backup_date}" + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + error "Cannot Backup (move) directory '${_src_base_dir}/dovecot-${_version}'" + + echononl "Proceed instllation [yes/no]: " + read OK + OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')" + while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do + echononl "Wrong entry! - repeat [yes/no]: " + read OK + done + [[ $OK = "yes" ]] || fatal "Abbruch durch User" + + fi +else + echo -e "$rc_skipped" +fi + +mkdir -p $_log_dir + + +## ----------------- +## --- Download + +cd ${_src_base_dir} + +echo "" +echo -e "\033[1mDownload sources\033[m.." + +## - Downloud Dovecot 2.2.x +## - +echononl "\tDownload dovecot-${_version}.tar.gz" +if [ ! -f "${_src_base_dir}/dovecot-${_version}.tar.gz" ]; then + wget --no-check-certificate https://dovecot.org/releases/${dovecot_main_version}/dovecot-${_version}.tar.gz > /dev/null 2>&1 + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + error "Direct download of 'dovecot-${_version}.tar.gz' failed + + Download \033[1mdovecot-${_version}.tar.gz\033[m manually and proceed instllation." + + echononl "Proceed instllation [yes/no]: " + read OK + OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')" + while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do + echononl "Wrong entry! - repeat [yes/no]: " + read OK + done + [[ $OK = "yes" ]] || fatal "Abbruch durch User" + fi +else + echo -e "$rc_skipped" +fi + + +## - Download Pigeonhole for Dovecot v2.2 +## - +echononl "\tDownload dovecot-${dovecot_main_version}-pigeonhole-${_pigeonhole}.tar.gz.." +if [ ! -f "${_src_base_dir}/dovecot-${dovecot_main_version}-pigeonhole-${_pigeonhole}.tar.gz" ]; then + wget --no-check-certificate https://pigeonhole.dovecot.org/releases/${dovecot_main_version}/dovecot-${dovecot_main_version}-pigeonhole-${_pigeonhole}.tar.gz > /dev/null 2>&1 + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + error "Direct download of 'dovecot-${dovecot_main_version}-pigeonhole-${_pigeonhole}.tar.gz' failed + + Download \033[1mdovecot-${dovecot_main_version}-pigeonhole-${_pigeonhole}.tar.gz\033[m manually + and proceed instllation." + + echononl "\tProceed instllation [yes/no]: " + read OK + OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')" + while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do + echononl "Wrong entry! - repeat [yes/no]: " + read OK + done + [[ $OK = "yes" ]] || fatal "Abbruch durch User" + + fi +else + echo -e "$rc_skipped" +fi + + + +if $_new ; then + ## - Install reqired debian packages + ## - + echo "" + echo -e "\033[1mInstalling required debian packages\033[m.." + echononl "\tInstalling libpq5 libpq-dev .." + if ! dpkg -l libpq-dev | grep -e "^ii" | grep libpq-dev > /dev/null ; then + apt-get install libpq5 libpq-dev > ${_log_dir}/debian-install.log 2&>1 + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + fatal "installing debian package(s) failed" + fi + else + echo -e "$rc_skipped" + fi + echononl "\tInstalling libkrb5-dev .." + if ! dpkg -l libkrb5-dev | grep -e "^ii" | grep libkrb5-dev > /dev/null ; then + apt-get install libkrb5-dev >> ${_log_dir}/debian-install.log 2&>1 + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + fatal "installing debian package(s) failed" + fi + else + echo -e "$rc_skipped" + fi +fi + + +## ----------------- +## - Create Users/groups needed for dovecot + +echo "" +echo -e "\033[1mCreate required users/groups\033[m.." +echononl "\tCreate group dovecot.." +if ! grep dovecot /etc/group > /dev/null ; then + addgroup --system --gid 91 dovecot > ${_log_dir}/system.log 2>&1 + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + fatal Create group failed + fi +else + echo -e "$rc_skipped" +fi + +echononl "\tCreate user dovecot.." +if ! grep dovecot /etc/passwd > /dev/null ; then + adduser --system --home /var/empty --no-create-home --shell /usr/sbin/nologin \ + --ingroup dovecot --uid 91 dovecot > ${_log_dir}/system.log 2>&1 + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + fatal Create user failed + fi +else + echo -e "$rc_skipped" +fi + +echononl "\tAdd Apache User (${http_user}) to group 'dovecot'.." +if getent group dovecot 2> /dev/null | grep -q "\b${http_user}\b" > /dev/null 2>&1 ; then + echo -e "$rc_skipped" +else + usermod -a -G dovecot $http_user > ${_log_dir}/system.log 2>&1 + if [[ $? -eq 0 ]] ; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + error "Failed to add Apache User (${http_user}) to group 'dovecot'!" + fi +fi + + +echononl "\tCreate group dovenull.." +if ! grep dovenull /etc/group > /dev/null ; then + addgroup --system --gid 65533 dovenull > ${_log_dir}/system.log 2>&1 + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + fatal Create group failed + fi +else + echo -e "$rc_skipped" +fi +echononl "\tCreate user dovenull.." +if ! grep dovenull /etc/passwd > /dev/null ; then + adduser --system --home /var/empty --no-create-home --shell /usr/sbin/nologin \ + --ingroup dovenull --uid 65533 dovenull > ${_log_dir}/system.log 2>&1 + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + fatal Create user failed + fi +else + echo -e "$rc_skipped" +fi + +if $update ; then + + # - Deaktiviere Cronjobs + # - + echo "" + echononl "\tBackup Crontab (user toot) to '$_backup_crontab_file'" + crontab -l > $_backup_crontab_file 2> $log_file + if [[ $? -eq 0 ]]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + error "Backup Crontab to '$_backup_crontab_file' failed" + + # If no crontab was present, the backup file contains + # th string "no crontab fo root". Better to delete the + # backup crontab file.. + # + rm -f $_backup_crontab_file + fi + + echononl "\tRemove crontab for user root.." + crontab -r > $log_file 2>&1 + if [[ $? -eq 0 ]]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + error "" + fi + +fi + + + +## ----------------- +## --- Install Base System + +echo "" +echo -e "\033[1mInstalling Base System\033[m.." + +## - Unpack dovecot sources +## - +cd ${_src_base_dir} +echononl "\tUnpack dovecot-${_version}.tar.gz.." +tar -xzf dovecot-${_version}.tar.gz > /dev/null +if [ "$?" = 0 ]; then + echo -e "$rc_done" +else + echo -e "$rc_failed" + fatal Extracting dovecot failed +fi + +cd dovecot-${_version} + +## - Configure dovecot +## - +config_params=" + --prefix=/usr/local/dovecot-${_version} \ + --with-${db_driver} \ + --with-gssapi=yes + --with-rundir=/run/dovecot" +if $systemd_support ; then + config_params="$config_params \ + --with-systemd" +fi + #--with-systemdsystemunitdir=/etc/systemd/system/" + +echononl "\tConfigure Dovecot.." +#./configure \ +# --prefix=/usr/local/dovecot-${_version} \ +# --with-${db_driver} \ +# --with-gssapi=yes > ${_log_dir}/dovecot-${_version}-configure.log 2>&1 + + #--with-systemdsystemunitdir=/etc/systemd/system \ + +LDFLAGS="-s" \ +./configure $config_params > ${_log_dir}/dovecot-${_version}-configure.log 2>&1 + +if [ "$?" = 0 ]; then + echo -e "$rc_done" +else + echo -e "$rc_failed" + fatal Configuring dovecot failed +fi + +## - Compile dovecot +## - +echononl "\tCompile Dovecot Sources.." +make > ${_log_dir}/dovecot-${_version}-make.log 2>&1 || clean_up 1 +if [ "$?" = 0 ]; then + echo -e "$rc_done" +else + echo -e "$rc_failed" + fatal Compiling dovecot failed +fi + + +## ----------------- +## --- Stop dovecot if running + +echononl "\tStop dovecot service.." +if ps ax 2> /dev/null | grep -q -E "/usr/local/dovecot[0-9.-]*/sbin/dovecot" > /dev/null 2>&1 ; then + if $systemd_support ; then + systemctl stop dovecot > /dev/null 2>&1 + else + /etc/init.d/dovecot stop > /dev/null 2>&1 + fi + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + error "Stopping dovecot service failed" + fi +else + echo -e "$rc_skipped" +fi + +blank_line + +echononl "\tRemove dovecot service file if exists.." +if [[ -f "/etc/systemd/system/dovecot.service" ]] ; then + rm -f "/etc/systemd/system/dovecot.service" > /dev/null 2>&1 + if [[ "$?" -gt 0 ]]; then + echo -e "$rc_failed" + error "Removing file '/etc/systemd/system/dovecot.service' failed." + else + echo -e "$rc_done" + fi +else + echo -e "$rc_skipped" +fi + +echononl "\tRemove dovecot systemd's socket file if exists.." +if [[ -f "/etc/systemd/system/dovecot.socket" ]] ; then + rm -f "/etc/systemd/system/dovecot.socket" > /dev/null 2>&1 + if [[ "$?" -gt 0 ]]; then + echo -e "$rc_failed" + error "Removing systemd's socket file '/etc/systemd/system/dovecot.socket' failed." + else + echo -e "$rc_done" + fi +else + echo -e "$rc_skipped" +fi + +echononl "\tRemove directory '/etc/systemd/system/dovecot.service.d' if exists.." +if [[ -d "/etc/systemd/system/dovecot.service.d" ]] ; then + rm -rf "/etc/systemd/system/dovecot.service.d" > /dev/null 2>&1 + if [[ "$?" -gt 0 ]]; then + echo -e "$rc_failed" + error "Removing directory '/etc/systemd/system/dovecot.service.d' failed." + else + echo -e "$rc_done" + fi +else + echo -e "$rc_skipped" +fi + +blank_line + +## - Install dovecot +## - +echononl "\tInstall Dovecot into Folder /usr/local/dovecot-${_version}" +make install > ${_log_dir}/dovecot-${_version}-install.log 2>&1 || clean_up 1 +if [ "$?" = 0 ]; then + echo -e "$rc_done" +else + echo -e "$rc_failed" + fatal Installing dovecot failed +fi + + +## - Add /usr/local/dovecot/bin to PATH variable +## - +## - Edit /etc/profile and add bevor "export PATH" directive: +## - +## - checkdir="/usr/local/dovecot/bin" +## - if [ -d $checkdir ]; then +## - PATH=$PATH:$checkdir +## - fi +## - +echononl "\tAdd /usr/local/dovecot/bin to PATH variable.." +if ! grep "checkdir=\"/usr/local/dovecot/bin\"" /etc/profile > /dev/null ; then + perl -i -n -p -e "s#^(\s*)(export\ +PATH)#checkdir=\"/usr/local/dovecot/bin\"\nif [ -d \\\$checkdir ]; then\n PATH=\\\$PATH:\\\$checkdir\nfi\n\n\1\2#" /etc/profile +if [ "$?" = 0 ]; then + echo -e "$rc_done" +else + echo -e "$rc_failed" + fatal Adjusting /etc/profile failed +fi +else + echo -e "$rc_skipped" +fi + +echononl "\tCopy Manpages if not exists.." +## - Manpages +## - +if ! grep /usr/local/dovecot/share/man /etc/manpath.config > /dev/null 2<&1 ; then + echo >> /etc/manpath.config + echo "MANDATORY_MANPATH /usr/local/dovecot/share/man /var/cache/man" >> /etc/manpath.config + echo "MANPATH_MAP /usr/local/dovecot/bin /usr/local/dovecot/share/man" >> /etc/manpath.config + echo "MANDB_MAP /usr/local/dovecot/share/man /var/cache/man" >> /etc/manpath.config + echo -e "$rc_done" +else + echo -e "$rc_skipped" +fi + + +## ----------------- +## --- Install Pigeonhole ManageSieve + +cd ${_src_base_dir} +echo "" +echononl "\tExtracting dovecot-${dovecot_main_version}-pigeonhole-${_pigeonhole}.tar.gz.." +gunzip < dovecot-${dovecot_main_version}-pigeonhole-${_pigeonhole}.tar.gz | tar -xf - +if [ "$?" = 0 ]; then + echo -e "$rc_done" +else + echo -e "$rc_failed" + fatal Extracting dovecot-${dovecot_main_version}-pigeonhole-${_pigeonhole}.tar.gz failed +fi +cd dovecot-${dovecot_main_version}-pigeonhole-${_pigeonhole} + + +echononl "\tConfigure Pigeonhole ManageSieve.." +./configure \ + --prefix=/usr/local/dovecot-${_version} \ + --with-dovecot=/usr/local/dovecot-${_version}/lib/dovecot > ${_log_dir}/dovecot-${dovecot_main_version}-pigeonhole-${_pigeonhole}-configure.log 2<&1 +if [ "$?" = 0 ]; then + echo -e "$rc_done" +else + echo -e "$rc_failed" + fatal Configuring Pigeonhole ManageSieve failed +fi + +echononl "\tCompile Pigeonhole ManageSieve.." +make > ${_log_dir}/dovecot-${dovecot_main_version}-pigeonhole-${_pigeonhole}-make.log 2<&1 +if [ "$?" = 0 ]; then + echo -e "$rc_done" +else + echo -e "$rc_failed" + fatal Compiling Pigeonhole ManageSieve failed +fi + +echononl "\tInstall Pigeonhole ManageSieve.." +make install > ${_log_dir}/dovecot-${dovecot_main_version}-pigeonhole-${_pigeonhole}-install.log 2<&1 +if [ "$?" = 0 ]; then + echo -e "$rc_done" +else + echo -e "$rc_failed" + fatal Installing Pigeonhole ManageSieve failed +fi + + +## ----------------- +## --- Configure dovecot services + +_failed=false +echo "" +echo -e "\033[1mConfigure Dovecot\033[m.." + +## - Copy example config files to the config directory +## - +cp -r /usr/local/dovecot-${_version}/share/doc/dovecot/example-config/* \ + /usr/local/dovecot-${_version}/etc/dovecot/ + + +## - edit /usr/local/dovecot/etc/dovecot/dovecot.conf +## - +## - protocols = imap pop3 sieve +## - listen = $ipv4 $ipv6 +## - base_dir =/run/dovecot/ +## - state_dir = /run/dovecot +## - shutdown_clients = no +## - +## - dict { +## - expire = $db_driver:/usr/local/dovecot/etc/dovecot/sql-dict.conf.ext +## - } +## - +echononl "\tAdjust file dovecot.conf.." +if [[ -n "$ipv6" ]]; then + perl -i.ORIG -n -p -e "s#^([ ]*)\#?\ ?(listen\ ?=.*)#\1\#\# \2\n\1listen = $ipv4 $ipv6#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/dovecot.conf || _failed=true +else + perl -i.ORIG -n -p -e "s#^([ ]*)\#?\ ?(listen\ ?=.*)#\1\#\# \2\n\1listen = $ipv4#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/dovecot.conf || _failed=true +fi +perl -i -n -p -e "s#^([ ]*)\#?\ ?(protocols\ ?=.*)#\1\#\# \2\n\1protocols = imap pop3 sieve#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/dovecot.conf || _failed=true +perl -i -n -p -e "s#^([ ]*)\#?\ ?(base_dir\ ?=.*)#\1\#\# \2\n\1base_dir = /run/dovecot/\n\nstate_dir = /run/dovecot#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/dovecot.conf || _failed=true +perl -i -n -p -e "s#^([ ]*)\#?\ ?(shutdown_clients\ ?=.*)#\1\#\# \2\n\1shutdown_clients = no#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/dovecot.conf || _failed=true + +if $plugin_expire ; then + perl -i -n -p \ + -e "s#^([ ]*)(dict\ +{.*)#\1\2\n\1 expire = $db_driver:/usr/local/dovecot/etc/dovecot/sql-dict.conf.ext#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/dovecot.conf || _failed=true +fi + + +if ! $_failed ; then + echo -e "$rc_done" +else + echo -e "$rc_failed" + fatal "Adjusting Adjusting file /usr/local/dovecot-${_version}/etc/dovecot/dovecot.conf failed" +fi + + + +if $_new ; then + + if [ "$db_driver" = "pgsql" ]; then + + echononl "\tCheck if database '$dbname' already exists.." + count=`su - postgres -c "psql -q -A -t -l" 2> ${_log_dir}/error.log | grep -c -e "^$dbname"` + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + error "Checking existence of database '$dbname' failed!" + + echononl "\tcontinue anyway [yes/no]: " + read OK + OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')" + while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do + echononl "Wrong entry! - repeat [yes/no]: " + read OK + done + [[ $OK = "yes" ]] || fatal "Abbruch durch User" + + fi + + if [ $count -eq 0 ];then + echononl "\tCreate database user ${dbuser}.." + echo "CREATE ROLE $dbuser WITH LOGIN NOCREATEDB NOCREATEROLE NOSUPERUSER ENCRYPTED PASSWORD '$dbpassword'" \ + | su - postgres -c "psql" > /dev/null 2>&1 + + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + fatal Creating database user $dbuser failed + fi + + echononl "\tCreate database ${dbname}.." + su - postgres -c "createdb -E utf8 -O ${dbuser} $dbname" + + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + fatal Creating database $dbname failed + fi + fi + + ## - Create table expires in database ${dbname} + ## - + echononl "\tCreate table expires in database ${dbname}.." + if $plugin_expire ; then + cat << EOF | psql -U$dbuser $dbname > ${_log_dir}/error.log 2>&1 + +CREATE TABLE IF NOT EXISTS expires ( + username varchar(100) not null, + mailbox varchar(255) not null, + expire_stamp integer not null, + primary key (username, mailbox) +); +EOF + + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + error "$(cat ${_log_dir}/error.log)" + + echononl "\tcontinue anyway [yes/no]: " + read OK + OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')" + while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do + echononl "Wrong entry! - repeat [yes/no]: " + read OK + done + [[ $OK = "yes" ]] || fatal "Abbruch durch User" + + fi + else + echo -e "$rc_skipped" + fi + + echononl "\tCreate function merge_expires() / trigger mergeexpires.." + if $plugin_expire ; then + cat << EOF | psql -U$dbuser $dbname > /dev/null 2>&1 +CREATE LANGUAGE plpgsql; + +create or replace function merge_expires() returns trigger as \$\$ +begin + update expires set expire_stamp = new.expire_stamp + where username = new.username and mailbox = new.mailbox; + if found then + return null; + else + return new; + end if; +end; +\$\$ language plpgsql; + +create trigger mergeexpires before insert on expires + for each row execute procedure merge_expires(); +EOF + + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + error "$(cat ${_log_dir}/error.log)" + + echononl "\tcontinue anyway [yes/no]: " + read OK + OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')" + while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do + echononl "Wrong entry! - repeat [yes/no]: " + read OK + done + [[ $OK = "yes" ]] || fatal "Abbruch durch User" + fi + else + echo -e "$rc_skipped" + fi + + elif [ "$db_driver" = "mysql" ]; then + + if ! mysql ${MYSQL_CREDENTIALS} -N -s -e \ + "SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = '$dbname'" 2>/dev/null \ + | grep $_db_name > /dev/null 2>&1 ; then + + echononl "\tCreate database ${dbname}.." + mysql ${MYSQL_CREDENTIALS} -N -s -e \ + "CREATE DATABASE IF NOT EXISTS $dbname CHARACTER SET utf8 COLLATE utf8_general_ci" > ${_log_dir}/error.log 2>&1 + + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + error "$(cat ${_log_dir}/error.log)" + + echononl "\tcontinue anyway [yes/no]: " + read OK + OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')" + while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do + echononl "Wrong entry! - repeat [yes/no]: " + read OK + done + [[ $OK = "yes" ]] || fatal "Abbruch durch User" + fi + + echononl "\tCreate database user ${dbuser}.." + mysql ${MYSQL_CREDENTIALS} -N -s -e \ + "GRANT ALL ON ${dbname}.* TO '${dbuser}'@'localhost' IDENTIFIED BY '$dbpassword'" > ${_log_dir}/error.log 2>&1 + + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + error "$(cat ${_log_dir}/error.log)" + + echononl "\tcontinue anyway [yes/no]: " + read OK + OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')" + while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do + echononl "Wrong entry! - repeat [yes/no]: " + read OK + done + [[ $OK = "yes" ]] || fatal "Abbruch durch User" + fi + + echononl "\tFlushing database privileges.." + mysql ${MYSQL_CREDENTIALS} -N -s -e "FLUSH PRIVILEGES" > ${_log_dir}/error.log 2>&1 + + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + error "$(cat ${_log_dir}/error.log)" + + echononl "\tcontinue anyway [yes/no]: " + read OK + OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')" + while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do + echononl "Wrong entry! - repeat [yes/no]: " + read OK + done + [[ $OK = "yes" ]] || fatal "Abbruch durch User" + fi + + fi + + + ## - Create table expires in database ${dbname} + ## - + echononl "\tCreate table expires in database ${dbname}.." + if $plugin_expire ; then + cat << EOF | mysql -u$dbuser -p$dbpassword $dbname > /dev/null 2>&1 + +CREATE TABLE IF NOT EXISTS expires ( + username varchar(100) not null, + mailbox varchar(255) not null, + expire_stamp integer not null, + primary key (username, mailbox) +); +EOF + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + error "Creating table expires failed" + fi + else + echo -e "$rc_skipped" + fi + fi +fi + + +## - create sql-dict.conf.ext file +## - +echononl "\tCreate file sql-dict.conf.ext with plugin 'expire'.." +if $plugin_expire ; then + if [ "$db_driver" = "pgsql" ]; then + + cat </usr/local/dovecot-${_version}/etc/dovecot/sql-dict.conf.ext +connect = host=$dbhost user=$dbuser password=$dbpassword dbname=$dbname + + +# CREATE TABLE expires ( +# username varchar(100) not null, +# mailbox varchar(255) not null, +# expire_stamp integer not null, +# primary key (username, mailbox) +# ); + +## - if using postgres, you need also to create a trigger as follows: +## - +## - first create language plpgsql if not yet created: +## - +# CREATE LANGUAGE plpgsql; +# +# CREATE OR REPLACE FUNCTION merge_expires() RETURNS TRIGGER AS \$\$ +# BEGIN +# UPDATE expires SET expire_stamp = NEW.expire_stamp +# WHERE username = NEW.username AND mailbox = NEW.mailbox; +# IF FOUND THEN +# RETURN NULL; +# ELSE +# RETURN NEW; +# END IF; +# END; +# \$\$ LANGUAGE plpgsql; +# +# CREATE TRIGGER mergeexpires BEFORE INSERT ON expires +# FOR EACH ROW EXECUTE PROCEDURE merge_expires(); + + +map { +pattern = shared/expire/\$user/\$mailbox +table = expires +value_field = expire_stamp + +fields { + username = \$user + mailbox = \$mailbox +} +} +EOF + + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + fatal "Creating file sql-dict.conf.ext failed" + fi + + elif [ "$db_driver" = "mysql" ]; then + + ## - create sql-dict.conf.ext file + ## - + echononl "\tCreate file sql-dict.conf.ext" + cat </usr/local/dovecot-${_version}/etc/dovecot/sql-dict.conf.ext +# CREATE TABLE expires ( +# username varchar(100) not null, +# mailbox varchar(255) not null, +# expire_stamp integer not null, +# primary key (username, mailbox) +# ); + + +map { +pattern = shared/expire/\$user/\$mailbox +table = expires +value_field = expire_stamp + +fields { + username = \$user + mailbox = \$mailbox +} +} +EOF + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + fatal "Creating file sql-dict.conf.ext failed" + fi + fi +else + echo -e "$rc_skipped" +fi + + +## - edit /usr/local/dovecot/etc/dovecot/conf.d/10-master.conf +## - +## - default_process_limit = 1024 +## - default_client_limit = 10240 +## - +## - default_vsz_limit = 512M +## - +## - !! Bemerkung !! +## - +## - Das Hochsetzen des default_client_limit Parameters auf einen Wert größer +## - als 1024 geht nur dann wenn auch die Anzahl der zulässigen "open files" +## - (default = 1024) geändert wird. +## - +## - +## - Systemd System: +## - =============== +## - +## - In der service datei (z.Bsp. /etc/systemd/system/multi-user.target.wants/dovecot.service) +## - den Wert 'LimitNOFILE' hochsetzen: +## - +## - LimitNOFILE=32768 (must be greater or equal of 'default_client_limit') +## - +## - systemctl daemon-reload +## - systemctl restart dovecot.service +## - +## - Im Falle von LX containern muss zusätzlich auf dem hostsystem +## - in der datei '/etc/systemd/system.conf' der Wert für 'DefaultLimitNOFILE' +## - hochgesetzt werden. +## - +## - System V systems: +## - ================= +## - Das Hochsetzen des default_client_limit Parameters auf einen Wert größer +## - als 1024 geht nur dann wenn auch die Anzahl der zulässigen "open files" +## - (default = 1024) geändert wird. Z.Bsp. in der Datei /etc/init.d/dovecot +## - durch Einfügen der zeile: +## - ulimit -n 32768 +## - +## - Linux VServer: +## - put the following lines into /etc/security/limits.conf +## - +## - @staff hard nofile 32768 +## - root hard nofile 32768 +## - +## - !! Mybe you have also create file /etc/vservers/*/ulimits/nofiles.hard +## - with the same contents: +## - +## - @staff hard nofile 32768 +## - @adm hard nofile 32768 +## - root hard nofile 32768 +## - +## - see also http://linux-vserver.org/Ulimit_Nofiles +## - +## - +## - +## - service auth { +## - +## - # Auth Listener (XMPP - Jabber) +## - inet_listener { +## - address = $xmpp_listener_addresses +## - port = $xmpp_listener_port +## - } +## - .. +## - unix_listener auth-userdb { +## - mode = 0666 +## - user = dovecot +## - group = dovecot +## - } +## - .. +## - unix_listener /var/spool/postfix/private/dovecot-auth { +## - mode = 0666 +## - user = postfix +## - group = postfix +## - } +## - .. +## - } +## - +## - service imap-login { +## - inet_listener imap { +## - address = $imap_listener_adresses +## - .. +## - } +## - inet_listener imaps { +## - address = $imaps_listener_adresses +## - .. +## - } +## - +## - process_min_avail = 16 +## - } +## - +## - service pop3-login { +## - inet_listener pop3 { +## - address = $pop_listener_adresses +## - .. +## - } +## - inet_listener pop3s { +## - address = $pops_listener_adresses +## - .. +## - } +## - } +## - +_failed=false +echononl "\tAdjusting file 10-master.conf.." +perl -i.ORIG -n -p -e "s#^([ ]*)(unix_listener\ +auth-userdb.*)#\1\2\n\1 mode = 0666\n\1 user = dovecot\n\1 group = dovecot#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf || _failed=true +perl -i -n -p -e "s#^([ ]*)(\#.*Postfix.*smtp-auth.*)#\1\2\n\1unix_listener /var/spool/postfix/private/dovecot-auth {\n\1 mode = 0666\n\1 user = postfix\n\1 group = postfix\n\1}#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf || _failed=true +perl -i -n -p -e "s#^([ ]*)(inet_listener\ +imap\ .*)#\1\2\n\1 address = $imap_listener_adresses#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf || _failed=true +perl -i -n -p -e "s#^([ ]*)(inet_listener\ +imaps.*)#\1\2\n\1 address = $imaps_listener_adresses#g#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf || _failed=true +perl -i -n -p -e "s#^([ ]*)(\#?process_min_avail\ ?=.*)#\1\#\# \2\n\1process_min_avail = 16#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf || _failed=true +perl -i -n -p -e "s#^([ ]*)(inet_listener\ +pop3\ .*)#\1\2\n\1 address = $pop_listener_adresses#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf || _failed=true +perl -i -n -p -e "s#^([ ]*)(inet_listener\ +pop3s.*)#\1\2\n\1 address = $pops_listener_adresses#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf || _failed=true + +if $xmpp_listener ; then + perl -i -n -p -e "s#^([ ]*)(service auth\s+\{.*)#\1\2\n\n \# Auth Listener (XMPP - Jabber)\n inet_listener {\n address = $xmpp_listener_addresses\n port = $xmpp_listener_port\n }\n#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf || _failed=true +fi + +## - setting default prozcess/client limit +## - +perl -i -n -p -e "s#^([ ]*\#?[ ]*)(default_process_limit.*)#\1\2\ndefault_process_limit = 1024#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf || _failed=true +perl -i -n -p -e "s#^([ ]*\#?[ ]*)(default_client_limit.*)#\1\2\ndefault_client_limit = 10240#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf || _failed=true + +perl -i -n -p -e "s#^([ ]*\#?[ ]*)(default_vsz_limit.*)#\1\2\ndefault_vsz_limit = 512M#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf || _failed=true + +if ! $_failed ; then + echo -e "$rc_done" +else + echo -e "$rc_failed" + fatal "Adjusting file /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf failed" +fi + +blank_line +echononl "\tCreate Cert/Key Directory '$cert_base_dir'.." +if [[ ! -d "$cert_base_dir" ]] ; then + mkdir -p "$cert_base_dir" > $log_file 2>&1 + if [[ $? -eq 0 ]] ; then + echo -e "$rc_done" + + echononl "\tChange Permissions for Cert/Key Directory '$cert_base_dir'.." + chmod 755 "$cert_base_dir" > $log_file 2>&1 + if [[ $? -eq 0 ]] ; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + error "$(cat "$log_file")" + fi + + else + echo -e "$rc_failed" + error "$(cat "$log_file")" + fi +else + echo -e "$rc_skipped" +fi + +## - Since dovecot version 2.3.x SSL DH parameters will be stored +## - permanently on filesystem. So we have to create such a file +## - +## - openssl dhparam -out /etc/postfix/ssl/dh_4096.pem` +## - +if [[ $dovecot_major_version -ge 3 ]] \ + || ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -ge 3 ]] ); then + + if [[ ! -f "$dh_pem_file" ]] ; then + echononl "\tCreate SSL DH parameters '$dh_pem_file'.." + echo -en "$rc_wait" + if [[ "$os_dist" = "debian" ]] && [[ $os_version -gt 11 ]] ; then + openssl dhparam -out "$dh_pem_file" 4096 > /dev/null 2>&1 + else + openssl dhparam -dsaparam -out "$dh_pem_file" 4096 > /dev/null 2>&1 + fi + if [[ $? -eq 0 ]]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + error "Creating DH parameter file '$dh_pem_file' failed." + fi + fi +fi + + + +## - edit /usr/local/dovecot/etc/dovecot/conf.d/10-ssl.conf +## - +## - ssl = required +## - +## - ssl_cert = <$server_cert +## - ssl_key = <$server_key +## - +## - # - 'ssl_dh_parameters_length' is obsolete and no longer needed +## - #ssl_dh_parameters_length = 2048 +## - +## - # - 'ssl_protocols has been' replaced by ssl_min_protocol +## - #ssl_protocols = !SSLv3 +## - ssl_min_protocol = TLSv1.2 +## - +## - ssl_cipher_list = ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA +## - +## - ssl_prefer_server_ciphers = yes +## - +## - +## - there are another possibilities to handle certs, but this did'nt work +## - as i expected.. +## - #local_name imap.warenform.de { +## - # ssl_cert = <$imap_cert +## - # ssl_key = <$imap_key +## - #} +## - #local_name pop.warenform.de { +## - # ssl_cert = <$pop_cert +## - # ssl_key = <$pop_key +## - #} +## - +_failed=false +echononl "\tAdjusting file 10-ssl.conf.." +perl -i.ORIG -n -p -e "s#^(\s*\#*\s*)(ssl\ ?=.*)#\#\1\2\nssl = required#" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-ssl.conf || _failed=true +perl -i -n -p -e "s#^([ ]*)(ssl_cert\ ?=.*)#\1\#\# \2\n\1ssl_cert = <$server_cert#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-ssl.conf || _failed=true +perl -i -n -p -e "s#^([ ]*)(ssl_key\ ?=.*)#\1\#\# \2\n\1ssl_key = <$server_key#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-ssl.conf || _failed=true + +if [[ $dovecot_major_version -ge 3 ]] \ + || ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -ge 3 ]] ); then + if [[ ! -f "$dh_pem_file" ]]; then + if [[ -f "/etc/postfix/ssl/dh_2048.pem" ]]; then + dh_pem_file="/etc/postfix/ssl/dh_2048.pem" + fi + fi + if [[ -f "$dh_pem_file" ]]; then + perl -i -n -p -e "s#^(\s*\#*)(ssl_dh\s*=.*)#\#\1\2\nssl_dh = <$dh_pem_file#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-ssl.conf || _failed=true + else + _failed=true + fi +else + perl -i -n -p -e "s#^([ ]*)\#?(ssl_dh_parameters_length\ ?=.*)#\1\#\# \2\nssl_dh_parameters_length = 2048#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-ssl.conf || _failed=true +fi + +perl -i -n -p -e "s#^([ ]*)\#?(ssl_min_protocol\ ?=.*)#\1\#\# \2\nssl_min_protocol = TLSv1.2#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-ssl.conf || _failed=true + +# - Replace only the first occurence of the match +# - +# - Example: +# - # Replace first occurence of 'width: .*' in file 'filename.css' +# - +# - perl -pi -e '$a=1 if(!$a && s/(width:).*;/$1 100%;/);' filename.css +# - +perl -i -n -p -e '$a=1 if(!$a && s#^([ ]*)\#?(ssl_cipher_list\ ?=.*)#\1\#\# \2\nssl_cipher_list = ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA#);' \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-ssl.conf || _failed=true + + +perl -i -n -p -e "s#^([ ]*)\#?(ssl_prefer_server_ciphers\ ?=.*)#\1\#\# \2\nssl_prefer_server_ciphers = yes#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-ssl.conf || _failed=true + +if ! $_failed ; then + echo -e "$rc_done" +else + echo -e "$rc_failed" + fatal "Adjusting file 10-ssl.conf failed" +fi + + +## - edit /usr/local/dovecot/etc/dovecot/conf.d/10-mail.conf +## - +## - mail_location = maildir:/var/vmail/%d/%n/Maildir +## - +## - mail_uid = vmail +## - mail_gid = vmail +## - +## - first_valid_uid = 5000 +## - last_valid_uid = 5000 +## - +## - mail_temp_dir = /var/vmail/tmp +## - +## - first_valid_gid = 5000 +## - last_valid_gid = 5000 +## - +## - auth_socket_path = /run/dovecot/auth-userdb +## - mail_plugins = quota | mail_plugins = quota expire +## - +## - mailbox_list_index = yes +## - +_failed=false +echononl "\tAdjusting file 10-mail.conf" +perl -i.ORIG -n -p -e "s#^([ ]*)\#?\ ?(mail_location\ +=.*)#\1\#\# \2\n\1mail_location = maildir:/var/vmail/%d/%n/Maildir#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf || _failed=true +perl -i -n -p -e "s#^([ ]*)\#?\ ?(mail_uid.*)#\1\#\# \2\n\1mail_uid = vmail#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf || _failed=true +perl -i -n -p -e "s#^([ ]*)\#?\ ?(mail_gid.*)#\1\#\# \2\n\1mail_gid = vmail#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf || _failed=true +perl -i -n -p -e "s#^([ ]*)\#?\ ?(mail_temp_dir.*)#\1\#\# \2\n\1mail_temp_dir = /var/vmail/tmp#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf || _failed=true +perl -i -n -p -e "s#^([ ]*)\#?\ ?(first_valid_uid.*)#\1\#\# \2\n\1first_valid_uid = 5000#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf || _failed=true +perl -i -n -p -e "s#^([ ]*)\#?\ ?(last_valid_uid.*)#\1\#\# \2\n\1last_valid_uid = 5000#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf || _failed=true +perl -i -n -p -e "s#^([ ]*)\#?\ ?(first_valid_gid.*)#\1\#\# \2\n\1first_valid_gid = 5000#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf || _failed=true +perl -i -n -p -e "s#^([ ]*)\#?\ ?(last_valid_gid.*)#\1\#\# \2\n\1last_valid_gid = 5000#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf || _failed=true +perl -i -n -p -e "s#^([ ]*)\#?\ ?(auth_socket_path\ +=.*)#\1\#\# \2\n\1auth_socket_path = /run/dovecot/auth-userdb#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf || _failed=true + +if $plugin_expire ; then + perl -i -n -p -e "s#^([ ]*)\#?\ ?(mail_plugins\ +=.*)#\1\#\# \2\n\1mail_plugins = quota expire#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf || _failed=true + +else + perl -i -n -p -e "s#^([ ]*)\#?\ ?(mail_plugins\ +=.*)#\1\#\# \2\n\1mail_plugins = quota#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf || _failed=true +fi + +perl -i -n -p -e "s#^([ ]*)\#?\ ?(mailbox_list_index\s*=.*)#\1\#\# \2\n\1mailbox_list_index = yes#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf || _failed=true + +if ! $_failed ; then + echo -e "$rc_done" +else + echo -e "$rc_failed" + fatal "Adjusting file '10-mail.conf' failed" +fi + + + +echononl "\tCreate TEMP directory '/var/vmail/tmp' .." +if [[ ! -d /var/vmail/tmp ]] ; then + mkdir /var/vmail/tmp > /dev/null 2>&1 + if [[ $? -eq 0 ]]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + error "Creating TEMP directory '/var/vmail/tmp' failed." + fi +else + echo -e "$rc_skipped" +fi + +echononl "\tChange ownerchip of directory '/var/vmail/tmp' .." +chown vmail:vmail /var/vmail/tmp > /dev/null 2>&1 +if [[ $? -eq 0 ]]; then + echo -e "$rc_done" +else + echo -e "$rc_failed" + error "Changing ownerchip of directory '/var/vmail/tmp' failed." +fi + +## - edit /usr/local/dovecot/etc/dovecot/conf.d/10-mail.conf +## - +## - comment out namespace section "namespace inbox". we will create namespaces later. +## - in detail, tha means comment out 3 lines: +## - namespace inbox { +## - .. +## - inbox = yes +## - .. +## - } +## - +_failed=false +_found=false +_tmp_file="$(mktemp)" +> $_tmp_file +while IFS='' read -r _line || [[ -n $_line ]] ; do + + if echo "$_line" | grep -i -E "^\s*namespace\s+inbox\s+" > /dev/null 2>&1 ; then + echo "## $_line" >> $_tmp_file + _found=true + continue + fi + + if $_found && echo "$_line" | grep -i -E "^\s*}" > /dev/null 2>&1 ; then + echo "## $_line" >> $_tmp_file + _found=false + continue + fi + + if $_found ; then + echo "## $_line" >> $_tmp_file + else + echo "$_line" >> $_tmp_file + fi +done < "/usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf" +if [[ "$?" != "0" ]] ; then + _failed=true +fi +mv /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf.TMP +if [[ "$?" != "0" ]] ; then + _failed=true +fi +mv $_tmp_file /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf +if [[ "$?" != "0" ]] ; then + _failed=true +fi +chmod 644 /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf +if [[ "$?" != "0" ]] ; then + _failed=true +fi + + +#perl -i -n -p -e "s#^([ ]*)(namespace\ +inbox\ +{\ *)#\1\#\#\ \2#g" \ +# /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf || _failed=true +#perl -i -n -p -e "s#^([ ]*)(inbox\ +=\ +yes\ *)#\1\#\#\ \2#g" \ +# /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf || _failed=true +#perl -i -n -p -e "s#^([ ]*)(}\ *)#\1\#\#\ \2#g" \ +# /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf || _failed=true + +if ! $_failed ; then + echo -e "$rc_done" +else + echo -e "$rc_failed" + fatal "Adjusting file /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf failed" +fi + +## - edit /usr/local/dovecot/etc/dovecot/conf.d/10-mail.conf +## - +## - Add namespaces type private +## - +## - Add: +## - namespace inbox { +## - type = private +## - separator = / +## - prefix = +## - inbox = yes +## - } +## - +echononl "\tAdd namespaces type private to file 10-mail.conf" +cat <> /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf + +## - Namespaces +## - +namespace inbox { + # Namespace type: private, shared or public + type = private + + # Hierarchy separator to use. You should use the same separator for all + # namespaces or some clients get confused. '/' is usually a good one. + # The default however depends on the underlying mail storage format. + #separator = + separator = / + + # Prefix required to access this namespace. This needs to be different for + # all namespaces. For example "Public/". + #prefix = + prefix = + + # Physical location of the mailbox. This is in same format as + # mail_location, which is also the default for it. + #location = + + # There can be only one INBOX, and this setting defines which namespace + # has it. + #inbox = no + inbox = yes + + # If namespace is hidden, it's not advertised to clients via NAMESPACE + # extension. You'll most likely also want to set list=no. This is mostly + # useful when converting from another server with different namespaces which + # you want to deprecate but still keep working. For example you can create + # hidden namespaces with prefixes "~/mail/", "~%u/mail/" and "mail/". + #hidden = no + + # Show the mailboxes under this namespace with LIST command. This makes the + # namespace visible for clients that don't support NAMESPACE extension. + # "children" value lists child mailboxes, but hides the namespace prefix. + #list = yes + + # Namespace handles its own subscriptions. If set to "no", the parent + # namespace handles them (empty prefix should always have this as "yes") + #subscriptions = yes +} +EOF +if [ "$?" = 0 ]; then + echo -e "$rc_done" +else + echo -e "$rc_failed" + fatal "Adjusting file /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf failed" +fi + + +## - edit /usr/local/dovecot/etc/dovecot/conf.d/15-mailboxes.conf +## - +## - Add definitions for mailbox Spam: +## - +## - mailbox Drafts { +## - auto = subscribe +## - special_use = \Drafts +## - } +## - +## - mailbox Trash { +## - auto = subscribe +## - special_use = \Trash +## - } +## - +## - mailbox Sent { +## - auto = subscribe +## - special_use = \Sent +## - } +## - +## - mailbox $spam_folder { +## - auto = subscribe +## - special_use = \Junk +## - } +## - +_failed=false +echononl "\tAdjusting file 15-mailboxes.conf" +perl -i.ORIG -n -p -e "s#^([ ]*)(mailbox\ +Drafts\ +{.*)#\1\2\n\1 auto = subscribe#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/15-mailboxes.conf || _failed=true +if [ "$spam_folder" != "Junk" ]; then + if $plugin_expire ; then + perl -i -n -p -e "s#^([ ]*)(mailbox\ +Junk\ +{.*)#\1mailbox $spam_folder {\n\1 auto = subscribe\n\1 special_use = \\\Junk\n\1}\n\1\2#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/15-mailboxes.conf || _failed=true + perl -i -n -p -e "s#^([ ]*)(mailbox\ +Junk\ +{.*)#\1\2\n\1 auto = no#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/15-mailboxes.conf || _failed=true + else + perl -i -n -p -e "s#^([ ]*)(mailbox\ +Junk\ +{.*)#\1mailbox $spam_folder {\n\1 auto = subscribe\n\1 autoexpunge = 30d\n\1 special_use = \\\Junk\n\1}\n\1\2#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/15-mailboxes.conf || _failed=true + perl -i -n -p -e "s#^([ ]*)(mailbox\ +Junk\ +{.*)#\1\2\n\1 auto = no\n\1 autoexpunge = 30d#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/15-mailboxes.conf || _failed=true + fi +else + if $plugin_expire ; then + perl -i -n -p -e "s#^([ ]*)(mailbox\ +$spam_folder\ +{.*)#\1\2\n\1 auto = subscribe#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/15-mailboxes.conf || _failed=true + else + perl -i -n -p -e "s#^([ ]*)(mailbox\ +$spam_folder\ +{.*)#\1\2\n\1 auto = subscribe\n\1 autoexpunge = 30d#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/15-mailboxes.conf || _failed=true + fi +fi +if $plugin_expire ; then + perl -i -n -p -e "s#^([ ]*)(mailbox\ +Trash\ +{.*)#\1\2\n\1 auto = subscribe#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/15-mailboxes.conf || _failed=true +else + perl -i -n -p -e "s#^([ ]*)(mailbox\ +Trash\ +{.*)#\1\2\n\1 auto = subscribe\n\1 autoexpunge = 3d#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/15-mailboxes.conf || _failed=true +fi +perl -i -n -p -e "s#^([ ]*)(mailbox\ +Sent\ +{.*)#\1\2\n\1 auto = subscribe#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/15-mailboxes.conf || _failed=true +perl -i -n -p -e "s#^([ ]*)(mailbox\ +\"Sent Messages\"\ +{.*)#\1\2\n\1 auto = no#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/15-mailboxes.conf || _failed=true + +if ! $_failed ; then + echo -e "$rc_done" +else + echo -e "$rc_failed" + fatal "Adjusting /usr/local/dovecot-${_version}/etc/dovecot/conf.d/15-mailboxes.conf failed" +fi + + +## - edit /usr/local/dovecot/etc/dovecot/conf.d/10-auth.conf +## - +## - disable_plaintext_auth = no +## - auth_mechanisms = $auth_mechanisms +## - !include auth-sql.conf.ext # comment all other includes +## - auth_username_translation = "%@" +## - +_failed=false +echononl "\tAdjusting file 10-auth.conf" +perl -i.ORIG -n -p -e "s#^([ ]*)\#?\ ?(disable_plaintext_auth\ +=.*)#\1\#\# \2\n\1disable_plaintext_auth = yes#" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-auth.conf || _failed=true +perl -i -n -p -e "s#^([ ]*)\#?\ ?(auth_mechanisms\ +=.*)#\1\#\# \2\n\1auth_mechanisms = $auth_mechanisms#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-auth.conf || _failed=true +perl -i -n -p -e "s#^(\!include\ auth-.*)#\#\1#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-auth.conf || _failed=true +perl -i -n -p -e "s#^\#(\!include\ auth-sql.*)#\1#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-auth.conf || _failed=true +perl -i -n -p -e "s#^([ ]*)\#?\ ?(auth_username_translation\ +=.*)#\1\#\# \2\n\1auth_username_translation = \"%@\"#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-auth.conf || _failed=true + +if ! $_failed ; then + echo -e "$rc_done" +else + echo -e "$rc_failed" + fatal "Adjusting /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-auth.conf failed" +fi + + + +## - edit /usr/local/dovecot/etc/dovecot/conf.d/auth-sql.conf.ext +## - +## - passdb { +## - driver = sql +## - +## - +## - # path for sql configuration file, see example-config/dovecot-sql.conf.ext +## - args = /usr/local/dovecot/etc/dovecot/sql-connect.conf.ext +## - } +## - +## - .. +## - +## - userdb { +## - driver = sql +## - args = /usr/local/dovecot/etc/dovecot/sql-connect.conf.ext +## - } +## - +echononl "\tAdjusting file auth-sql.conf.ext" +perl -i.ORIG -n -p -e "s#^([ ]*)(args\ ?=.*)#\1\#\# \2\n\1args = /usr/local/dovecot/etc/dovecot/sql-connect.conf.ext#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/auth-sql.conf.ext + +if ! $_failed ; then + echo -e "$rc_done" +else + echo -e "$rc_failed" + fatal "Adjusting /usr/local/dovecot-${_version}/etc/dovecot/conf.d/auth-sql.conf.ext failed" +fi + +## - create sql configuration file +## - +echononl "\tCreate sql configuration file sql-connect.conf.ext" +if [ "$db_driver" = "pgsql" ]; then + + cat < /usr/local/dovecot-${_version}/etc/dovecot/sql-connect.conf.ext +driver = $db_driver +## - if using unix-socket (host=/run/postgresql) ensure that +## - coresponding entries in pg_hba.cof fits +## - for example +## - local all all md5 +## - +connect = host=$dbhost user=$dbuser password=$dbpassword dbname=$dbname + +default_pass_scheme = $default_pass_scheme +password_query = SELECT username AS user, password \\ + FROM mailbox \\ + WHERE username = '%u' AND active = true +user_query = SELECT '/var/vmail/' || maildir AS home, \\ + '5000' AS uid, '5000' AS gid \\ + FROM mailbox \\ + WHERE username = '%u' AND active = true + #WHERE username = substring ('%u' from '#"[^-]+#"_*@%%' for '#') || '@%d' and active = true + +## - Query to get a list of all usernames. +## - +iterate_query = SELECT username AS user FROM mailbox +EOF + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + fatal "Adjusting file /usr/local/dovecot-${_version}/etc/dovecot/sql-connect.conf.ext failed" + fi + +elif [ "$db_driver" = "mysql" ]; then + + cat < /usr/local/dovecot-${_version}/etc/dovecot/sql-connect.conf.ext +driver = $db_driver +connect = host=$dbhost user=$dbuser password=$dbpassword dbname=$dbname + +default_pass_scheme = $default_pass_scheme +password_query = SELECT username AS user, password \\ + FROM mailbox \\ + WHERE username = '%u' AND active = true +user_query = SELECT CONCAT('/var/vmail/',maildir) AS home, \\ + '5000' AS uid, '5000' AS gid \\ + FROM mailbox \\ + WHERE username = '%u' AND active = true + +## - Query to get a list of all usernames. +## - +iterate_query = SELECT username AS user FROM mailbox +EOF + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + fatal "Adjusting file /usr/local/dovecot-${_version}/etc/dovecot/sql-connect.conf.ext failed" + fi +fi + + +## - edit /usr/local/dovecot/etc/dovecot/conf.d/10-logging.conf +## - +## - +## - if running inetd-script: +## - +## - log_path = /var/log/dovecot/dovecot.log +## - +## - or for example +## - +## - log_path = syslog +## - syslog_facility = local1 +## - auth_verbose = yes +## - auth_verbose_passwords = plain +## - +## - in conjunction with the the following entries in /etc/rsyslog.conf +## - +## - local1.* -/var/log/dovecot.log +## - local1.info -/var/log/dovecot.info +## - local1.warn -/var/log/dovecot.warn +## - local1.err -/var/log/dovecot.err +## - :msg,contains,"stored mail into mailbox"\ +## - -/var/log/dovecot.lmtp +## - +_failed=false +echononl "\tAdjusting file 10-logging.conf" +perl -i.ORIG -n -p -e "s#^([ ]*)\#?\ ?(log_path\ ?=.*)#\1\#\# \2\n\1log_path = syslog#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-logging.conf || _failed=true +perl -i -n -p -e "s#^([ ]*)\#?\ ?(syslog_facility\ ?=.*)#\1\#\# \2\n\1syslog_facility = local1#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-logging.conf || _failed=true +perl -i -n -p -e "s#^([ ]*)\#?\ ?(auth_verbose\ ?=.*)#\1\#\# \2\n\1auth_verbose = yes#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-logging.conf || _failed=true +perl -i -n -p -e "s#^([ ]*)\#?\ ?(auth_verbose_passwords\ ?=.*)#\1\#\# \2\n\1auth_verbose_passwords = plain#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-logging.conf || _failed=true + +if ! $_failed ; then + echo -e "$rc_done" +else + echo -e "$rc_failed" + fatal "Adjusting /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-logging.conf failed" +fi + + +if $_new ; then + + mkdir -p /var/log/dovecot + + echo + echononl "\tCreate file /etc/rsyslog.d/dovecot.conf" + cat < /etc/rsyslog.d/dovecot.conf + +## - dovecot +## - +local1.info -/var/log/dovecot/dovecot.info +local1.warn -/var/log/dovecot/dovecot.warn +local1.err -/var/log/dovecot/dovecot.err +:msg,contains,"stored mail into mailbox" \\ + -/var/log/dovecot/dovecot.lmtp +local1.* -/var/log/dovecot/dovecot.log +& stop + +EOF + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + fatal "Creating file /etc/rsyslog.d/dovecot.conf failed" + fi + + echononl "\tRestart rsyslog Servive" + if $systemd_support ; then + systemctl restart rsyslog.service > /dev/null 2>&1 + else + /etc/init.d/rsyslog restart > /dev/null 2>&1 + fi + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + error "Restarting rsyslog failed" + fi + + + ## - logrotate for dovecot log-files + ## - + echononl "\tCreate file /etc/logrotate.d/dovecot" + cat < /etc/logrotate.d/dovecot + /var/log/dovecot/dovecot.log + /var/log/dovecot/dovecot.info + /var/log/dovecot/dovecot.warn + /var/log/dovecot/dovecot.err + /var/log/dovecot/dovecot.lmtp { + daily + start 0 + rotate 7 + missingok + notifempty + compress + delaycompress + create 640 root adm + copytruncate + #sharedscripts + #postrotate + #/etc/init.d/dovecot reload > /dev/null + #/bin/kill -usr1 'cat /run/dovecot/master.pid 2>/dev/null' 2>/dev/null || true + #endscript + } +EOF + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + fatal "Creating file /etc/logrotate.d/dovecot failed" + fi + echo +fi + +## - edit /usr/local/dovecot/etc/dovecot/conf.d/15-lda.conf +## - +## - postmaster_address = $postmaster_address +## - hostname = $hostname +## - sendmail_path = /usr/sbin/sendmail +## - lda_mailbox_autocreate = no +## - mail_plugins = $mail_plugins sieve +## - +_failed=false +echononl "\tAdjusting file 15-lda.conf" +perl -i.ORIG -n -p -e "s#^([ ]*)\#?\ ?(postmaster_address\ +=.*)#\1\#\# \2\n\1postmaster_address = $postmaster_address#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/15-lda.conf || _failed=true +perl -i -n -p -e "s#^([ ]*)\#?\ ?(hostname\ +=.*)#\1\#\# \2\n\1hostname = $hostname#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/15-lda.conf || _failed=true +perl -i -n -p -e "s#^([ ]*)\#?\ ?(sendmail_path\ +=.*)#\1\#\# \2\n\1sendmail_path = /usr/sbin/sendmail#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/15-lda.conf || _failed=true +perl -i -n -p -e "s#^([ ]*)\#?\ ?(lda_mailbox_autocreate\ +=.*)#\1\#\# \2\n\1lda_mailbox_autocreate = no#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/15-lda.conf || _failed=true +perl -i -n -p -e "s#^([ ]*)\#?\ ?(mail_plugins\ +=.*)#\1\#\# \2\n\1mail_plugins = \\\$mail_plugins sieve#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/15-lda.conf || _failed=true + +if ! $_failed ; then + echo -e "$rc_done" +else + echo -e "$rc_failed" + fatal "Adjusting /usr/local/dovecot-${_version}/etc/dovecot/conf.d/15-lda.conf failed" +fi + +## - edit /usr/local/dovecot/etc/dovecot/conf.d/20-lmtp +## - +## - lmtp_save_to_detail_mailbox = no +## - mail_plugins = $mail_plugins sieve +## - +_failed=false +echononl "\tAdjusting file 20-lmtp.conf" +perl -i.ORIG -n -p -e "s#^([ ]*)\#?\ ?(lmtp_save_to_detail_mailbox\ +=.*)#\1\#\# \2\n\1lmtp_save_to_detail_mailbox = no#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-lmtp.conf || _failed=true +perl -i -n -p -e "s#^([ ]*)\#?\ ?(mail_plugins\ +=.*)#\1\#\# \2\n\1mail_plugins = \\\$mail_plugins sieve#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-lmtp.conf || _failed=true + +if ! $_failed ; then + echo -e "$rc_done" +else + echo -e "$rc_failed" + fatal "Adjusting /usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-lmtp.conf failed" +fi + + +## - edit /usr/local/dovecot/etc/dovecot/conf.d/20-imap.conf +## - +## - ssl_cert = <$imap_cert +## - ssl_key = <$imap_key +## - mail_max_userip_connections = $max_userip_connections +## - mail_plugins = $mail_plugins imap_quota +## - imap_client_workarounds = delay-newmail +## - +_failed=false +echononl "\tAdjusting file 20-imap.conf" +perl -i.ORIG -n -p -e "s#^([ ]*)\#?\ ?(protocol imap \{)#\1\2\n\n\1 ssl_cert = <$imap_cert\n\1 ssl_key = <$imap_key\n#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-imap.conf || _failed=true +perl -i -n -p -e "s#^([ ]*)\#?\ ?(mail_max_userip_connections\ +=.*)#\1\#\# \2\n\1mail_max_userip_connections = $max_userip_connections#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-imap.conf || _failed=true +perl -i -n -p -e "s#^([ ]*)\#?\ ?(mail_plugins\ +=.*)#\1\#\# \2\n\1mail_plugins = \\\$mail_plugins imap_quota#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-imap.conf || _failed=true +perl -i -n -p -e "s#^([ ]*)\#?\ ?(imap_client_workarounds\ +=.*)#\1\#\# \2\n\1imap_client_workarounds = delay-newmail#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-imap.conf || _failed=true + +if ! $_failed ; then + echo -e "$rc_done" +else + echo -e "$rc_failed" + fatal "Adjusting /usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-imap.conf failed" +fi + + +## - edit /usr/local/dovecot/etc/dovecot/conf.d/20-pop3.conf +## - +## - ssl_cert = <$pop_cert +## - ssl_key = <$pop_key +## - mail_max_userip_connections = 24 +## - pop3_client_workarounds = outlook-no-nuls oe-ns-eoh +## - +_failed=false +echononl "\tAdjusting file 20-pop3.conf" +perl -i.ORIG -n -p -e "s#^([ ]*)\#?\ ?(protocol pop3 \{)#\1\2\n\n\1 ssl_cert = <$pop_cert\n\1 ssl_key = <$pop_key\n#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-pop3.conf || _failed=true +perl -i -n -p -e "s#^([ ]*)\#?\ ?(mail_max_userip_connections\ +=.*)#\1\#\# \2\n\1mail_max_userip_connections = 24#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-pop3.conf || _failed=true +perl -i -n -p -e "s#^([ ]*)\#?\ ?(pop3_client_workarounds\ +=.*)#\1\#\# \2\n\1pop3_client_workarounds = outlook-no-nuls oe-ns-eoh#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-pop3.conf || _failed=true + +if ! $_failed ; then + echo -e "$rc_done" +else + echo -e "$rc_failed" + fatal "Adjusting /usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-pop3.conf failed" +fi + + +## - edit /usr/local/dovecot/etc/dovecot/conf.d/90-plugin.conf +## - +## - Note: +## - Setting "autocreate", "autosubscribe" here is depricated. Use mailbox { auto } setting instead. +## - +## - expire = Trash +## - expire2 = Trash/* +## - expire3 = Spam +## - +## - expire_dict = proxy::expire +## - +## - # Enable caching of dict value in dovecot.index file. This significantly reduces +## - # the number of dict lookups. It makes initial testing more confusing though, so +## - # it's better to enable it only after you've verified that the expire plugin is +## - # working as wanted. (v2.2.16+) +## - expire_cache = yes +## - +_failed=false +echononl "\tAdjusting file 90-plugin.conf" +if $plugin_expire ; then + perl -i.ORIG -n -p -e "s#^([ ]*)(\#?\ ?setting_name\ +=.*)#\1\2\n\n\1expire = Trash\n\1expire2 = Trash/*\n\1expire3 = $spam_folder\n\n\1expire_dict = proxy::expire\n\n\1\# Enable caching of dict value in dovecot.index file. This significantly reduces\n\1\# the number of dict lookups. It makes initial testing more confusing though, so\n\1\# it's better to enable it only after you've verified that the expire plugin is\n\1\# working as wanted. (v2.2.16+)\n\1expire_cache = yes#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-plugin.conf || _failed=true + + + if ! $_failed ; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + fatal "Adjusting /usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-plugin.conf failed" + fi +else + echo -e "$rc_skipped" +fi + + +## - edit /usr/local/dovecot/etc/dovecot/conf.d/90-sieve.conf +## - +## - sieve = ~/.dovecot.sieve +## - #sieve_global_path = /usr/local/dovecot/etc/dovecot/sieve/default.sieve +## - sieve_before = /usr/local/dovecot/etc/dovecot/sieve/move-spam.sieve +## - sieve_dir = ~/sieve +## - sieve_global = /usr/local/dovecot/etc/dovecot/sieve/global/ +## - recipient_delimiter = +## - +_failed=false +echononl "\tAdjusting file 90-sieve.conf" +perl -i.ORIG -n -p -e "s#^([ ]*)\#?\ ?(sieve\ ?=.*)#\1\#\# \2\n\1sieve = ~/.dovecot.sieve#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-sieve.conf || _failed=true +perl -i -n -p -e "s#^([ ]*)\#?\ ?(sieve_before\ ?=.*)#\1\#\# \2\n\1sieve_before =/usr/local/dovecot/etc/dovecot/sieve/move-spam.sieve#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-sieve.conf || _failed=true +perl -i -n -p -e "s#^([ ]*)\#?\ ?(sieve_dir\ ?=.*)#\1\#\# \2\n\1sieve_dir = ~/sieve#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-sieve.conf || _failed=true +perl -i -n -p -e "s#^([ ]*)\#?\ ?(sieve_global\ ?=.*)#\1\#\# \2\n\1sieve_global = /usr/local/dovecot/etc/dovecot/sieve/global/#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-sieve.conf || _failed=true +perl -i -n -p -e "s#^([ ]*)\#?\ ?(recipient_delimiter\ ?=.*)#\1\#\# \2\n\1recipient_delimiter =#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-sieve.conf || _failed=true + +if ! $_failed ; then + echo -e "$rc_done" +else + echo -e "$rc_failed" + fatal "Adjusting /usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-sieve.conf" +fi + +# - Add Setting from Pigeonhole Sieve: Vacation Extension +# - +echononl "\tAdd Setting for included Pigeonhole Sieve: Vacation Extension" +_found=false +_tmp_file="/tmp/dovecot_conf_90-sieve.conf" +cp -a "/usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-sieve.conf" "$_tmp_file" > /dev/null 2>&1 +:> $_tmp_file +while IFS='' read -r _line || [[ -n $_line ]] ; do + + echo "$_line" >> "$_tmp_file" + + if ! $_found && $(echo "$_line" | grep -i -E "^\s*plugin {" > /dev/null 2>&1) ; then + _found=true + + cat <> "$_tmp_file" + + # Add Setting 'sieve_vacation_send_from_recipient' from (included) + # + # Pigeonhole Sieve: Vacation Extension + # ==================================== + # + # sieve_vacation_send_from_recipient + # + # Default: no + # + # Values: Boolean + # + # This setting determines whether vacation messages are sent with the + # SMTP MAIL FROM envelope address set to the recipient address of the + # Sieve script owner. + # + # Normally this is set to <>, which is the default as recommended in the + # specification. This is meant to prevent mail loops. However, there are + # situations for which a valid sender address is required and this setting + # can be used to accommodate for those. + # + sieve_vacation_send_from_recipient = yes + +EOF + fi +done < "/usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-sieve.conf" +cp -a "$_tmp_file" "/usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-sieve.conf" > /dev/null 2>&1 +echo -e "$rc_done" + + +echononl "\tCreate Directory for global sieve scripts" +mkdir -p "/usr/local/dovecot-${_version}/etc/dovecot/sieve/global/" > $log_file 2>&1 +if [ "$?" = 0 ]; then + echo -e "$rc_done" +else + echo -e "$rc_failed" + error "$(cat $log_file)" + + echononl "\tcontinue anyway [yes/no]: " + read OK + OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')" + while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do + echononl "Wrong entry! - repeat [yes/no]: " + read OK + done + [[ $OK = "yes" ]] || fatal "Abbruch durch User" + +fi + + +## - ceate global sieve script +## - +echononl "\tCeate global sieve script" +cat < /usr/local/dovecot-${_version}/etc/dovecot/sieve/move-spam.sieve +require ["fileinto"]; +# rule:[Move Spam] +# Move spam to spam folder +if header :contains "X-Spam-Flag" ["YES"] { + fileinto "$spam_folder"; + #discard; + stop; +} +EOF + +if [ "$?" = 0 ]; then + echo -e "$rc_done" +else + echo -e "$rc_failed" + error "Creating global sieve script failed" + + echononl "\tcontinue anyway [yes/no]: " + read OK + OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')" + while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do + echononl "Wrong entry! - repeat [yes/no]: " + read OK + done + [[ $OK = "yes" ]] || fatal "Abbruch durch User" + +fi + +## - NOTICE: if you pre-compile your (global) scripts, you will increase +## - performance +## - +echononl "\tPrecompile global sieve script" +cd /usr/local/dovecot-${_version}/etc/dovecot/sieve/ +/usr/local/dovecot-${_version}/bin/sievec \ + /usr/local/dovecot-${_version}/etc/dovecot/sieve/move-spam.sieve > $log_file 2>&1 + +if [ "$?" = 0 ]; then + echo -e "$rc_done" +else + echo -e "$rc_failed" + error "$(cat $log_file)" + + echononl "\tcontinue anyway [yes/no]: " + read OK + OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')" + while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do + echononl "Wrong entry! - repeat [yes/no]: " + read OK + done + [[ $OK = "yes" ]] || fatal "Abbruch durch User" + +fi + + +## - you can also give dovecot's delivery service (lda / lmtp) the permissions to write +## - into the sieve directory. then dovecots delivery service will compile the script +## - by first using.. +## - +chown -R vmail:vmail /usr/local/dovecot-${_version}/etc/dovecot/sieve + +if $systemd_support; then + + ## - # - At time, we don't use private tmp directory for divecot. + ## - # - + ## - echononl "\tAdjust Systemd service file, set PrivateTmp=false.." + ## - if [[ -f "/etc/systemd/system/dovecot.service" ]] ; then + ## - + ## - if $(grep -o -E "PrivateTmp\s*=\s*[^[:blank:]]+" /etc/systemd/system/dovecot.service | grep -q true 2> /dev/null ) ; then + ## - perl -i -n -p -e "s/(PrivateTmp\s*=\s*)true/\1false/" /etc/systemd/system/dovecot.service + ## - if [[ $? -eq 0 ]]; then + ## - echo -e "$rc_done" + ## - else + ## - echo -e "$rc_failed" + ## - fi + ## - else + ## - echo -e "$rc_skipped" + ## - fi + ## - else + ## - echo -e "$rc_skipped" + ## - fi + + ## - Increase LimitNOFILE to fit dovecots setting for 'default_client_limit'. + ## - + ## - here: + ## - LimitNOFILE=32768 + ## - + if [[ -f "/lib/systemd/system/dovecot.service" ]] \ + && $(grep -q -E "^LimitNOFILE=" /lib/systemd/system/dovecot.service) ; then + + _LimitNOFILE="$(grep -E "^LimitNOFILE=[[:digit:]]+" /lib/systemd/system/dovecot.service | cut -d'=' -f2)" + + adjust_limit_nofile=false + + if [[ $service_limit_nofile -gt _LimitNOFILE ]] ; then + + adjust_limit_nofile=true + echononl "\tCreate Directory '/etc/systemd/system/dovecot.service.d'.." + if [[ -d "/etc/systemd/system/dovecot.service.d" ]] ; then + echo -e "$rc_skipped" + else + mkdir "/etc/systemd/system/dovecot.service.d" > /dev/null 2>&1 + if [[ $? -eq 0 ]]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + adjust_limit_nofile=false + fi + fi + + fi + + echononl "\tAdjust 'LimitNOFILE' for 'dovecot.service'.." + if ! $adjust_limit_nofile ; then + echo -e "$rc_skipped" + else + cat < /etc/systemd/system/dovecot.service.d/set-limit-nofile.conf +[Service] +LimitNOFILE=$service_limit_nofile +EOF + echo -e "$rc_done" + fi + fi + + + echononl "\tReload systemd .." + systemctl daemon-reload > /dev/null 2>&1 + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + fi + + ## - Make dovecot start at boot time + ## - + echononl "\tMake dovecot start at boottime.." + systemctl enable dovecot > /dev/null 2>&1 + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + fatal "Make dovecot start at boottime (systend service) failed" + fi + +else + + ## - Make dovecot start at boot time + ## - + echononl "\tMake dovecot start at boottime.." + update-rc.d dovecot defaults > /dev/null 2>&1 + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + fatal "Make dovecot start at boottime (init script) failed" + fi + +fi + + +if $_new ; then + + if ! $systemd_support; then + + _create_init="" + echo + echo -n "Create init script /etc/init.d/dovecot ? [y/n]: " + read _create_init + if [ "y" = "$_create_init" -o "Y" = "$_create_init" -o "Yes" = "$_create_init" -o "yes" = "$_create_init" ];then + echononl "\tCreate init script for dovecot .." + ## - running dovecot service via init-script + ## - + cat < /etc/init.d/dovecot +#! /bin/sh +### BEGIN INIT INFO +# Provides: dovecot +# Required-Start: \$syslog \$postgresql +# Required-Stop: \$syslog \$postgresql +# Should-Start: \$local_fs \$time ntp +# Should-Stop: \$local_fs +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Dovecot init script +# Description: Init script for dovecot services +### END INIT INFO + +# Author: Miquel van Smoorenburg . +# Modified for Debian GNU/Linux +# by Ian Murdock . +# + +# Do NOT "set -e" +ulimit -n 32768 + +# PATH should only include /usr/* if it runs after the mountnfs.sh script +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/dovecot/sbin/dovecot:/usr/local/dovecot/bin +DESC="IMAP/POP3 mail server" +NAME=dovecot +DAEMON=/usr/local/dovecot/sbin/dovecot +DAEMON_ARGS="" +SCRIPTNAME=/etc/init.d/\$NAME +CONF=/usr/local/dovecot/etc/dovecot/\${NAME}.conf + +# Read configuration variable file if it is present +[ -r /etc/default/\$NAME ] && . /etc/default/\$NAME + +# Exit if the package is not installed +[ -x "\$DAEMON" ] || exit 0 + +# Exit if the configuration file doesn't exist +[ -f "\$CONF" ] || exit 0 + +# Load the VERBOSE setting and other rcS variables +. /lib/init/vars.sh + +# Define LSB log_* functions. +# Depend on lsb-base (>= 3.0-6) to ensure that this file is present. +. /lib/lsb/init-functions + +# cong file readable? +if [ ! -r \${CONF} ]; then + [ "\$VERBOSE" != no ] && log_daemon_msg "\${CONF}: not readable" "\$NAME" \\ + && log_end_msg 1; + exit 1; +fi + + +# The init script should do nothing if dovecot or another imap/pop3 server +# is being run from inetd, and dovecot is configured to run as an imap or +# pop3 service +if [ -r /etc/inetd.conf ]; then + for p in \`sed -r "s/^ *(([^:]+|\[[^]]+]|\*):)?(pop3s?|imaps?)[ \t].*/\3/;t;d" \\ + /etc/inetd.conf\` + do + for q in \`sed -r "s/^[ \t]*protocols[ \t]*=[ \t]*(([^\"]*)|\"(.*)\")/\2\3/;t;d" \\ + \${CONF}\` + do + if [ \$p = \$q ]; then + exit 0 + fi + done + done +fi + +# determine the location of the PID file +# overide by setting base_dir in conf file or PIDBASE in /etc/defaults/\$NAME +PIDBASE=\${PIDBASE:-\`sed -r "s/^[ \t]*base_dir[ \t]*=[ \t]*([^ \t]*)/\1/;t;d" \${CONF}\`} +PIDFILE=\${PIDBASE:-/run/dovecot/}master.pid + +# +# Function that starts the daemon/service +# +do_start() +{ + # Return + # 0 if daemon has been started + # 1 if daemon was already running + # 2 if daemon could not be started + start-stop-daemon --start --quiet --pidfile \$PIDFILE --exec \$DAEMON --test > /dev/null \\ + || return 1 + start-stop-daemon --start --quiet --pidfile \$PIDFILE --exec \$DAEMON -- \\ + \$DAEMON_ARGS \\ + || return 2 +} + +# +# Function that stops the daemon/service +# +do_stop() +{ + # Return + # 0 if daemon has been stopped + # 1 if daemon was already stopped + # 2 if daemon could not be stopped + # other if a failure occurred + start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile \$PIDFILE --name \${DAEMON##*/} + RETVAL="\$?" + [ "\$RETVAL" = 2 ] && return 2 + # Wait for children to finish too if this is a daemon that forks + # and if the daemon is only ever run from this initscript. + # If the above conditions are not satisfied then add some other code + # that waits for the process to drop all resources that could be + # needed by services started subsequently. A last resort is to + # sleep for some time. + start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --pidfile \$PIDFILE --name \${DAEMON##*/} + [ "\$?" = 2 ] && return 2 + # Many daemons don't delete their pidfiles when they exit. + rm -f \$PIDFILE + return "\$RETVAL" +} + +# +# Function that sends a SIGHUP to the daemon/service +# +do_reload() { + # + # If the daemon can reload its configuration without + # restarting (for example, when it is sent a SIGHUP), + # then implement that here. + # + start-stop-daemon --stop --signal USR1 --quiet --pidfile \$PIDFILE --name \$NAME + return 0 +} + + +case "\$1" in + start) + [ "\$VERBOSE" != no ] && log_daemon_msg "Starting \$DESC" "\$NAME" + do_start + case "\$?" in + 0|1) [ "\$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "\$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + stop) + [ "\$VERBOSE" != no ] && log_daemon_msg "Stopping \$DESC" "\$NAME" + do_stop + case "\$?" in + 0|1) [ "\$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "\$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + reload|force-reload) + log_daemon_msg "Reloading \$DESC" "\$NAME" + do_reload + log_end_msg \$? + ;; + restart) + # + # If the "reload" option is implemented then remove the + # 'force-reload' alias + # + log_daemon_msg "Restarting \$DESC" "\$NAME" + do_stop + case "\$?" in + 0|1) + do_start + case "\$?" in + 0) log_end_msg 0 ;; + 1) log_end_msg 1 ;; # Old process is still running + *) log_end_msg 1 ;; # Failed to start + esac + ;; + *) + # Failed to stop + log_end_msg 1 + ;; + esac + ;; + *) + #echo "Usage: \$SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2 + echo "Usage: \$SCRIPTNAME {start|stop|restart|force-reload}" >&2 + exit 3 + ;; +esac + +exit 0 +EOF + + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + fatal "Creating init script for dovecot failed" + fi + + chmod 755 /etc/init.d/dovecot + + else + echononl "\tCreate init script for dovecot .." + echo -e "$rc_skipped" + fi + + fi + + ## - Add a cronjob to restart dovecot after booting the system. + ## - + ## - Notice: + ## - On normal start, dovecot started its service even if ipv6 is not + ## - yet present and dovecot cannot bind to ipv6 listeners. + ## - + ## - Doimg a restart (after ipv6 adresses are present) fixes this. + ## - + echononl "\tCreate cronjob to restart dovecot service after reboot.." + _crontab_tmp_file=/tmp/crontab_root.$$ + crontab -l > $_crontab_tmp_file 2> /dev/null + + if [[ ! -s $_crontab_tmp_file ]]; then + echo "PATH=/usr/local/dovecot/bin:$PATH" > $_crontab_tmp_file + fi + + if ! grep -q -E "\s*@reboot.*systemctl\s+restart\s+dovecot.service" $_crontab_tmp_file ; then + echo "" >> $_crontab_tmp_file + echo "# - Restart dovecot after reboot" >> $_crontab_tmp_file + echo "# -" >> $_crontab_tmp_file + echo "@reboot sleep 15 ; /bin/systemctl restart dovecot.service" >> $_crontab_tmp_file + crontab $_crontab_tmp_file + echo -e "$rc_done" + else + echo -e "$rc_skipped" + fi + rm -f $_crontab_tmp_file + + + ## - update postfix configuration to play with dovecot lda + ## - + + ## - /etc/postfix/master.cf + ## - + ## - add line + ## - dovecot unix - n n - - pipe + ## - flags=drhu user=vmail:vmail argv=/usr/local/dovecot/libexec/dovecot/dovecot-lda -f ${sender} -d ${user}@${nexthop} + if ! grep -e dovecot-lda /etc/postfix/master.cf > /dev/null ; then + cp -a "/etc/postfix/master.cf" "/etc/postfix/master.cf.$backup_date" + echononl "\tConfigure /etc/postfix/master.cf to play with dovecot lda" + echo -e "\ndovecot unix - n n - - pipe\n flags=drhu user=vmail:vmail argv=/usr/local/dovecot/libexec/dovecot/dovecot-lda -f \${sender} -d \${user}@\${nexthop}" >> /etc/postfix/master.cf + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + fatal "Configuring /etc/postfix/master.cf failed" + fi + fi + + + ## - /etc/postfix/main.cf + ## - + ## - add/uncomment: + ## - + ## - smtpd_tls_auth_only + ## - + ## - smtpd_sasl_type = dovecot + ## - smtpd_sasl_path = private/dovecot-auth + ## - + ## - virtual_transport = dovecot + ## - dovecot_destination_recipient_limit = 1 + ## - + ## - in section restrictions, parameter smtpd_recipient_restrictions + ## - uncomment add + ## - + ## - permit_sasl_authenticated, + ## - + _failed=false + echononl "\tAdjust /etc/postfix/main.cf" + + perl -i.$backup_date -n -p -e "s#^(\s*)(smtpd_tls_auth_only\ *=.*)#smtpd_tls_auth_only = yes#" \ + /etc/postfix/main.cf || _failed=true + perl -i -n -p -e "s#^(\s*)(smtpd_sasl_auth_enable\ *=.*)#smtpd_sasl_auth_enable = no#" \ + /etc/postfix/main.cf || _failed=true + perl -i -n -p -e "s#^(\s*)(smtpd_sasl_type\ *=.*)#smtpd_sasl_type = dovecot#" \ + /etc/postfix/main.cf || _failed=true + perl -i -n -p -e "s#^(\s*)(smtpd_sasl_path\ *=.*)#smtpd_sasl_path = private/dovecot-auth#" \ + /etc/postfix/main.cf || _failed=true + + perl -i -n -p -e "s#^(\s*)(virtual_transport\ *=.*)#virtual_transport = dovecot\ndovecot_destination_recipient_limit = 1#" \ + /etc/postfix/main.cf || _failed=true + + perl -i-n -p -e "s#^(\s*)\#?(permit_sasl_authenticated)#\1\2#" /etc/postfix/main.cf || _failed=true + if ! $_failed ; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + fatal "Adjusting /etc/postfix/main.cf failed" + fi + + + ## - add a cronjob to run expunge scripts, to delete old mails + ## - from users'mailbox. only cleanup spam and trash directories + ## - + echononl "\tCreate cronjob to run expunge scripts" + _crontab_tmp_file=/tmp/crontab_root.$$ + crontab -l > $_crontab_tmp_file 2> /dev/null + + if [[ ! -s $_crontab_tmp_file ]]; then + echo "PATH=/usr/local/dovecot/bin:$PATH" > $_crontab_tmp_file + fi + + if ! grep -e "/usr/local/dovecot/bin/doveadm\ *expunge" $_crontab_tmp_file > /dev/null ; then + echo "" >> $_crontab_tmp_file + echo "# - cleanup spam and trash directories of users'mailboxes" >> $_crontab_tmp_file + echo "# -" >> $_crontab_tmp_file + echo "13 3 * * * /usr/local/dovecot/bin/doveadm expunge -A mailbox Trash* savedbefore 3d; /usr/local/dovecot/bin/doveadm expunge -A mailbox ${spam_folder}* savedbefore 30d" >> $_crontab_tmp_file + crontab $_crontab_tmp_file + echo -e "$rc_done" + else + echo -e "$rc_skipped" + fi + rm -f $_crontab_tmp_file + +fi # if $_new + + +echo +echo -e "\033[1mChange (from lda) to lmtp-service\033[m" + +## ----------------- +## --- Change (from lda) to lmtp-service + +## - edit /usr/local/dovecot/etc/dovecot/dovecot.conf +## - +## - add "lmtp" to protocols +## - +_failed=false +echononl "\tAdd lmtp to protocols (dovecot.conf)" +perl -i -n -p -e "s#^([ ]*)(protocols\ +=\ +.*)#\1\2 lmtp#" \ + /usr/local/dovecot-${_version}/etc/dovecot/dovecot.conf || _failed=true +if ! $_failed ; then + echo -e "$rc_done" +else + echo -e "$rc_failed" + fatal "Adding lmtp to protocols in file /usr/local/dovecot-${_version}/etc/dovecot/dovecot.conf failed" +fi + + +## - edit /usr/local/dovecot/etc/dovecot/conf.d/10-master.conf +## - +## - unix_listener /var/spool/postfix/private/dovecot-lmtp { +## - mode = 0600 +## - user = postfix +## - group = postfix +## - } +## - +echononl "\tAdding dovecot-lmtp listener to 10-master.conf" +perl -i -n -p -e "s#^([ ]*)(unix_listener\ +lmtp\ .*)#\1unix_listener /var/spool/postfix/private/dovecot-lmtp {\n user = postfix\n mode = 0660\n group = postfix#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf +if ! $_failed ; then + echo -e "$rc_done" +else + echo -e "$rc_failed" + fatal "Adjusting file /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf failed" +fi + + +# - /etc/postfix/main.cf +# - +# - comment in: +# - #virtual_transport = dovecot +# - #dovecot_destination_recipient_limit = .. +# - +# - change: +# - smtpd_sasl_auth_enable = yes +# - smtpd_sasl_type = dovecot +# - smtpd_sasl_path = private/dovecot-auth +# - virtual_transport = lmtp:unix:private/dovecot-lmtp +var="smtpd_sasl_auth_enable" +val="yes" +echononl "\t${postfix_main_cf}: adjust '${var}'.." +if ! $(grep -E -q "^\s*${var}\s*=\s*${val}" ${postfix_main_cf} 2> /dev/null) ; then + perl -i -n -p -e "s#^(\s*)(${var}\ *=.*)#${var} = ${val}#" \ + /etc/postfix/main.cf > $log_file 2>&1 + if [[ $? -eq 0 ]]; then + echo_ok + changed=true + else + echo_failed + error "$(cat "$log_file")" + fi +else + echo_skipped +fi + +var="smtpd_sasl_type" +val="dovecot" +echononl "\t${postfix_main_cf}: adjust '${var}'.." +if ! $(grep -E -q "^\s*${var}\s*=\s*${val}" ${postfix_main_cf} 2> /dev/null) ; then + perl -i -n -p -e "s#^(\s*)(${var}\ *=.*)#${var} = ${val}#" \ + /etc/postfix/main.cf > $log_file 2>&1 + if [[ $? -eq 0 ]]; then + echo_ok + changed=true + else + echo_failed + error "$(cat "$log_file")" + fi +else + echo_skipped +fi + +var="smtpd_sasl_path" +val="private/dovecot-auth" +echononl "\t${postfix_main_cf}: adjust '${var}'.." +if ! $(grep -E -q "^\s*${var}\s*=\s*${val}" ${postfix_main_cf} 2> /dev/null) ; then + perl -i -n -p -e "s#^(\s*)(${var}\ *=.*)#${var} = ${val}#" \ + /etc/postfix/main.cf > $log_file 2>&1 + if [[ $? -eq 0 ]]; then + echo_ok + changed=true + else + echo_failed + error "$(cat "$log_file")" + fi +else + echo_skipped +fi + +var="virtual_transport" +val="lmtp:unix:private/dovecot-lmtp" +echononl "\t${postfix_main_cf}: adjust '${var}'.." +if ! $(grep -E -q "^\s*${var}\s*=\s*${val}" ${postfix_main_cf} 2> /dev/null) ; then + perl -i -n -p -e "s#^(\s*)(${var}\ *=.*)#${var} = ${val}#" \ + /etc/postfix/main.cf > $log_file 2>&1 + if [[ $? -eq 0 ]]; then + echo_ok + else + echo_failed + changed=true + error "$(cat "$log_file")" + fi +else + echo_skipped +fi + + +echononl "\tComment variable 'dovecot_destination_recipient_limit'.." +if $(grep -E -q "^\s*dovecot_destination_recipient_limit" ${postfix_main_cf} 2> /dev/null) ; then + perl -i-n -p -e "s/^(\s*)(dovecot_destination_recipient_limit.*)/\1\#\2/" /etc/postfix/main.cf > $log_file 2>&1 + if [[ $? -eq 0 ]]; then + echo_ok + changed=true + else + echo_failed + error "$(cat "$log_file")" + fi +else + echo_skipped +fi + + + +## ----------------- +## --- Configure quota support for dovecot + +echo +echo -e "\033[1mConfigure quota support for dovecot\033[m" + + +## - take care quota plugins (quota,imap-quota) will +## - be loaded: +## - +## - there are two quota related plugins: +## - +## - * quota: implements the actual quota handling and includes also all the quota backends. +## - * imap_quota: for reporting quota information via imap. +## - +## - enable them in configuration files, e.g.: +## - +## - conf.d/10-mail.conf: +## - +## - # space separated list of plugins to load for all services. plugins specific to +## - # imap, lda, etc. are added to this list in their own .conf files. +## - mail_plugins = $mail_plugins quota +## - +## - conf.d/20-imap.conf: +## - +## - protocol imap { +## - # space separated list of plugins to load (default is global mail_plugins). +## - mail_plugins = $mail_plugins imap_quota +## - } +## - +## - we have done it befor, at the basic configuration +## - + +## - configure dict service +## - +## - edit /usr/local/dovecot/etc/dovecot/conf.d/10-master.conf +## - +## - add: +## - +## - service dict { +## - unix_listener dict { +## - mode = 0600 +## - user = vmail +## - } +## - } +## - +_failed=false +echononl "\tConfigure dict service (10-master.conf)" +perl -i -n -p -e "s#^([ ]*)(unix_listener\ +dict.*)#\1\2\n\1 mode = 0600\n\1 user = vmail#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf || _failed=true +if ! $_failed ; then + echo -e "$rc_done" +else + echo -e "$rc_failed" + fatal "Adjusting file /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf failed" +fi + + +## - edit /usr/local/dovecot/etc/dovecot/dovecot.conf +## - +## - add: +## - +## - dict { +## - quota = $db_driver:/usr/local/dovecot/etc/dovecot/sql-dict.conf.ext +## - } +_failed=false +echononl "\tAdjust file dovecot.conf for (dict) quota service" +perl -i -n -p -e "s#^([ ]*)(dict\ +{.*)#\1\2\n\1 quota = $db_driver:/usr/local/dovecot/etc/dovecot/sql-dict.conf.ext#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/dovecot.conf || _failed=true +if ! $_failed ; then + echo -e "$rc_done" +else + echo -e "$rc_failed" + fatal "Adjusting file /usr/local/dovecot-${_version}/etc/dovecot/dovecot.conf failed" +fi + + +if $_new ; then + + if [ "$db_driver" = "pgsql" ]; then + + echononl "\tCreate table quota2 in database \"$dbname\".." + cat << EOF | psql -U$dbuser $dbname > /dev/null 2>&1 +CREATE TABLE IF NOT EXISTS quota2 ( + username varchar(100) not null, + bytes bigint not null default 0, + messages integer not null default 0, + primary key (username) +); +EOF + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + error "Creating table quota2 in database \"$dbname\" failed" + fi + + echononl "\tCreate Trigger mergequota2.." + cat << EOF | psql -U$dbuser $dbname > /dev/null 2>&1 +CREATE PROCEDURAL LANGUAGE plpgsql; + +CREATE FUNCTION merge_quota2() RETURNS trigger + LANGUAGE plpgsql + AS \$\$ + BEGIN + IF NEW.messages < 0 OR NEW.messages IS NULL THEN + -- ugly kludge: we came here from this function, really do try to insert + IF NEW.messages IS NULL THEN + NEW.messages = 0; + ELSE + NEW.messages = -NEW.messages; + END IF; + return NEW; + END IF; + + LOOP + UPDATE quota2 SET bytes = bytes + NEW.bytes, + messages = messages + NEW.messages + WHERE username = NEW.username; + IF found THEN + RETURN NULL; + END IF; + + BEGIN + IF NEW.messages = 0 THEN + INSERT INTO quota2 (bytes, messages, username) VALUES (NEW.bytes, NULL, NEW.username); + ELSE + INSERT INTO quota2 (bytes, messages, username) VALUES (NEW.bytes, -NEW.messages, NEW.username); + END IF; + return NULL; + EXCEPTION WHEN unique_violation THEN + -- someone just inserted the record, update it + END; + END LOOP; + END; + \$\$; +CREATE TRIGGER mergequota2 + BEFORE INSERT ON quota2 + FOR EACH ROW + EXECUTE PROCEDURE merge_quota2(); +EOF + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + fatal "Creating function merge_quota2() / trigger merge_quota2 failed" + fi + + elif [ "$db_driver" = "mysql" ]; then + echononl "\tCreate table quota2 in database \"$dbname\".." + cat << EOF | mysql -u$dbuser -p$dbpassword $dbname > /dev/null 2>&1 +CREATE TABLE IF NOT EXISTS quota2 ( + username varchar(100) not null, + bytes bigint not null default 0, + messages integer not null default 0, + primary key (username) +); +EOF + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + error "Creating table quota2 in database \"$dbname\" failed" + fi + fi + +fi + +_failed=false +echononl "\tRenew file sql-dict.conf.ext" +if [ "$db_driver" = "pgsql" ]; then + + cat </usr/local/dovecot-${_version}/etc/dovecot/sql-dict.conf.ext +## - if using unix-socket (host=/run/postgresql) ensure that +## - coresponding entries in pg_hba.cof fits +## - for example +## - local all all md5 +## - +connect = host=$dbhost user=$dbuser password=$dbpassword dbname=$dbname + +# CREATE TABLE quota2 ( +# username varchar(100) not null, +# bytes bigint not null default 0, +# messages integer not null default 0, +# primary key (username) +# ); +# +## - if using postgres, you need also to create a trigger as follows: +## - +## - first create language plpgsql if not yet created: +## - +# CREATE PROCEDURAL LANGUAGE plpgsql; +# +# CREATE FUNCTION merge_quota2() RETURNS trigger +# LANGUAGE plpgsql +# AS \$\$ +# BEGIN +# IF NEW.messages < 0 OR NEW.messages IS NULL THEN +# -- ugly kludge: we came here from this function, really do try to insert +# IF NEW.messages IS NULL THEN +# NEW.messages = 0; +# ELSE +# NEW.messages = -NEW.messages; +# END IF; +# return NEW; +# END IF; +# +# LOOP +# UPDATE quota2 SET bytes = bytes + NEW.bytes, +# messages = messages + NEW.messages +# WHERE username = NEW.username; +# IF found THEN +# RETURN NULL; +# END IF; +# +# BEGIN +# IF NEW.messages = 0 THEN +# INSERT INTO quota2 (bytes, messages, username) VALUES (NEW.bytes, NULL, NEW.username); +# ELSE +# INSERT INTO quota2 (bytes, messages, username) VALUES (NEW.bytes, -NEW.messages, NEW.username); +# END IF; +# return NULL; +# EXCEPTION WHEN unique_violation THEN +# -- someone just inserted the record, update it +# END; +# END LOOP; +# END; +# \$\$; +# +# +# ALTER FUNCTION public.merge_quota2() OWNER TO postfix; +# +# CREATE TRIGGER mergequota2 +# BEFORE INSERT ON quota2 +# FOR EACH ROW +# EXECUTE PROCEDURE merge_quota2(); + +map { + pattern = priv/quota/storage + table = quota2 + username_field = username + value_field = bytes +} +map { + pattern = priv/quota/messages + table = quota2 + username_field = username + value_field = messages +} +EOF + if [[ "$?" -gt 0 ]]; then + _failed=true + fi + + if $plugin_expire ; then + cat <> /usr/local/dovecot-${_version}/etc/dovecot/sql-dict.conf.ext + +# CREATE TABLE expires ( +# username varchar(100) not null, +# mailbox varchar(255) not null, +# expire_stamp integer not null, +# primary key (username, mailbox) +# ); + +## - if using postgres, you need also to create a trigger as follows: +## - +## - first create language plpgsql if not yet created: +## - +# CREATE LANGUAGE plpgsql; +# +# CREATE OR REPLACE FUNCTION merge_expires() RETURNS TRIGGER AS \$\$ +# BEGIN +# UPDATE expires SET expire_stamp = NEW.expire_stamp +# WHERE username = NEW.username AND mailbox = NEW.mailbox; +# IF FOUND THEN +# RETURN NULL; +# ELSE +# RETURN NEW; +# END IF; +# END; +# \$\$ LANGUAGE plpgsql; +# +# CREATE TRIGGER mergeexpires BEFORE INSERT ON expires +# FOR EACH ROW EXECUTE PROCEDURE merge_expires(); + +map { + pattern = shared/expire/\$user/\$mailbox + table = expires + value_field = expire_stamp + + fields { + username = \$user + mailbox = \$mailbox + } +} +EOF + if [[ "$?" -gt 0 ]]; then + _failed=true + fi + + fi + + if ! $_failed ; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + fatal "Recreating file /usr/local/dovecot-${_version}/etc/dovecot/sql-dict.conf.ext failed" + fi + + ## - you also have to update the userdb's query in file + ## - "/usr/local/dovecot/etc/dovecot/sql-connect.conf.ext" to + ## - support extra variable "quota_rule" + ## - + echononl "\tRenew file sql-connect.conf.ext" +cat < /usr/local/dovecot-${_version}/etc/dovecot/sql-connect.conf.ext +driver = $db_driver +## - if using unix-socket (host=/run/postgresql) ensure that +## - coresponding entries in pg_hba.cof fits +## - for example +## - local all all md5 +## - +connect = host=$dbhost user=$dbuser password=$dbpassword dbname=$dbname + +default_pass_scheme = $default_pass_scheme +password_query = SELECT username AS user, password \\ + FROM mailbox \\ + WHERE username = '%u' AND active = true +user_query = SELECT '/var/vmail/' || maildir AS home, \\ + '5000' AS uid, '5000' AS gid, \\ + '*:bytes=' || quota AS quota_rule \\ + FROM mailbox \\ + WHERE username = '%u' AND active = true + +## - Query to get a list of all usernames. +## - +iterate_query = SELECT username AS user FROM mailbox +EOF + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + fatal "Recreating file /usr/local/dovecot-${_version}/etc/dovecot/sql-connect.conf.ext failed" + fi + +elif [ "$db_driver" = "mysql" ]; then + cat </usr/local/dovecot-${_version}/etc/dovecot/sql-dict.conf.ext +connect = host=$dbhost user=$dbuser password=$dbpassword dbname=$dbname + +# CREATE TABLE quota2 ( +# username varchar(100) not null, +# bytes bigint not null default 0, +# messages integer not null default 0, +# primary key (username) +# ); + +map { + pattern = priv/quota/storage + table = quota2 + username_field = username + value_field = bytes +} +map { + pattern = priv/quota/messages + table = quota2 + username_field = username + value_field = messages +} +EOF + if [[ "$?" -gt 0 ]]; then + _failed=true + fi + + if $plugin_expire ; then + cat <> /usr/local/dovecot-${_version}/etc/dovecot/sql-dict.conf.ext + +# CREATE TABLE expires ( +# username varchar(100) not null, +# mailbox varchar(255) not null, +# expire_stamp integer not null, +# primary key (username, mailbox) +# ); + +map { + pattern = shared/expire/\$user/\$mailbox + table = expires + value_field = expire_stamp + + fields { + username = \$user + mailbox = \$mailbox + } +} +EOF + if [[ "$?" -gt 0 ]]; then + _failed=true + fi + + fi + + if ! $_failed ; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + fatal "Recreating file /usr/local/dovecot-${_version}/etc/dovecot/sql-dict.conf.ext failed" + fi + + ## - you also have to update the userdb's query in file + ## - "/usr/local/dovecot/etc/dovecot/sql-connect.conf.ext" to + ## - support extra variable "quota_rule" + ## - + echononl "\tRenew file sql-connect.conf.ext" +cat < /usr/local/dovecot-${_version}/etc/dovecot/sql-connect.conf.ext +driver = $db_driver +connect = host=$dbhost user=$dbuser password=$dbpassword dbname=$dbname + +default_pass_scheme = $default_pass_scheme +password_query = SELECT username AS user, password \\ + FROM mailbox \\ + WHERE username = '%u' AND active = true +user_query = SELECT CONCAT('/var/vmail/',maildir) AS home, \\ + '5000' AS uid, '5000' AS gid, \\ + CONCAT('*:bytes=',quota) AS quota_rule \\ + FROM mailbox \\ + WHERE username = '%u' AND active = true + +## - Query to get a list of all usernames. +## - +iterate_query = SELECT username AS user FROM mailbox +EOF + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + fatal "Recreating file /usr/local/dovecot-${_version}/etc/dovecot/sql-connect.conf.ext failed" + fi +fi + + +## - configure stats service (10-master.conf) +## - +echononl "\tConfigure stats service (10-master.conf)" +cat <> /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf + +service stats { + + fifo_listener stats-mail { + user = vmail + group = dovecot + mode = 0660 + } + + unix_listener stats-reader { + user = vmail + group = dovecot + mode = 0660 + } + + unix_listener stats-writer { + user = vmail + group = dovecot + mode = 0660 + } +} +EOF +if [[ $? -gt 0 ]] ; then + echo -e "$rc_failed" + error "Configure stats service (10-master.conf) failed!" +else + echo -e "$rc_done" +fi + + + +## - configure post-login service (10-master.conf) +## - +## - see also: https://wiki.dovecot.org/PostLoginScripting +## - +echononl "\tAdd script '/usr/local/dovecot-${_version}/bin/post-login.sh'.." +cat < /usr/local/dovecot-${_version}/bin/post-login.sh +#!/usr/bin/env bash + +touch ~/.last_login + +exec "\$@" +EOF +if [[ $? -gt 0 ]] ; then + echo -e "$rc_failed" + error "Adding script '/usr/local/dovecot-${_version}/bin/post-login.sh' failed!" +else + echo -e "$rc_done" +fi + +echononl "\tSet Permissions of 'post-login.sh' .." +chmod 755 "/usr/local/dovecot-${_version}/bin/post-login.sh" > /dev/null 2>&1 +if [[ $? -gt 0 ]] ; then + echo -e "$rc_failed" + error "Setting permissions to '/usr/local/dovecot-${_version}/bin/post-login.sh' failed!" +else + echo -e "$rc_done" +fi + +_failed=false +echononl "\tConfigure post-login service (10-master.conf)" +perl -i -n -p -e "s#^(\s*)(service\s+imap\s+{.*)#\1\2\n\1 \# tell imap to do post-login lookup using a socket called \"imap-postlogin\"\n\1 executable = imap post-login\n#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf || _failed=true +perl -i -n -p -e "s#^(\s*)(service\s+pop3\s+{.*)#\1\2\n\1 \# tell imap to do post-login lookup using a socket called \"imap-postlogin\"\n\1 executable = pop3 post-login\n#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf || _failed=true +cat <> /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf + +service post-login { + # all post-login scripts are executed via script-login binary + executable = script-login /usr/local/dovecot/bin/post-login.sh + + # the script process runs as the user specified here: + user = vmail + + # this UNIX socket listener must use the same name as given to imap executable + unix_listener post-login { + } +} +EOF +if [[ $? -gt 0 ]] ; then + _failed=true +fi + +if ! $_failed ; then + echo -e "$rc_done" +else + echo -e "$rc_failed" + fatal "Configuring 'post-login' service failed!" +fi + + +## - edit /usr/local/dovecot/etc/dovecot/conf.d/90-quota.conf +## - +## - add to the end of file or in seperate plugin-blocks +## - as designed in that file: +## - plugin { +## - # sql backend: +## - quota = dict:user quota::proxy::quota +## - +## - quota_rule = *:storage=1g +## - quota_rule2 = trash:storage=+100m +## - +## - quota_warning = storage=80%% quota-warning 80 %u +## - quota_warning2 = storage=95%% quota-warning 95 %u +## - } +## - +## - service quota-warning { +## - executable = script /usr/local/bin/quota-warning.sh +## - user = vmail +## - unix_listener quota-warning { +## - user = vmail +## - mode = 0666 +## - } +## - } +## - +echononl "\tAdjust file 90-quota.conf" +cp -a /usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-quota.conf \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-quota.conf.ORIG +cat <>/usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-quota.conf + +## - +plugin { + # SQL backend: + quota = dict:User quota::proxy::quota + + quota_rule = *:storage=1G + quota_rule2 = Trash:storage=+200M + + quota_warning = storage=80%% quota-warning 80 %u + quota_warning2 = storage=95%% quota-warning 95 %u +} + +service quota-warning { + executable = script /usr/local/bin/quota-warning.sh + user = vmail + unix_listener quota-warning { + user = vmail + mode = 0666 + } +} +EOF +if [ "$?" = 0 ]; then + echo -e "$rc_done" +else + echo -e "$rc_failed" + fatal "Adjusting file /usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-quota.conf failed" +fi + + +if $_new ; then + + echononl "\tCreate quota warning script.." + ## - create the user-warning script + ## - + cat </usr/local/bin/quota-warning.sh +#!/usr/bin/env bash + +# author: zhang huangbin +# purpose: send mail to notify user when his mailbox quota exceeds a +# specified limit. +# project: iredmail (http://www.iredmail.org/) + +LANG=en_US.UTF-8 + +percent=\$1 +user=\$2 + +cat << EOF | /usr/local/dovecot/libexec/dovecot/deliver -d \${user} -c /usr/local/dovecot/etc/dovecot/dovecot.conf -o "plugin/quota=dict:User quota::noenforcing:proxy::quota" +date: \`date +"%a, %e %b %Y %H:%M:%S %z"\` +from: $from_address +reply-to: $reply_to +to:\${user} +subject: mailbox quota warning: \${percent}% belegt. +content-type: text/plain; + charset=utf-8 + +Hallo! + +Deine Mailbox für das Postfach + \${user} +ist nun zu über \${percent}% voll. Damit Du weiterhin E-Mails +empfangen kannst, lösche bitte vorhandene E-Mails vom Server. + +Dies geht zum Beispiel via Webmailer: + $webmailer + +Viele Grüße + +$salutation +${_EOF:-EOF} +EOF + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + fatal "Create quota warning script /usr/local/bin/quota-warning.sh failed" + fi + + chmod 755 /usr/local/bin/quota-warning.sh + +fi + + +## ----------------- +## --- Configure ACL support for dovecot + +## - What to do: +## - +## - 1.) Add shared namespace +## - 2.) Add plugins to the several plugin lists +## - - "acl" to variable mail_plugins in 10-mail.conf +## - - "acl-imap" to variable mail_plugins in 20-imap.conf +## - +## - 3.a) Add acl to the plugin part in 90-acl.conf +## - +## - 3.b) To make shared mailboxes visible a database (dict) is needed. +## - This can also be a dict file. +## - Add acl_shared_dict to the plugin part of 90-acl.conf +## - +## - 4.) If using SQL backend, also a rule "acl =" in "dict" section +## - of file dovecont.conf needed +## - + + +## - edit /usr/local/dovecot/etc/dovecot/conf.d/10-mail.conf +## - +## - Add namespaces type shared to 10-mail.conf +## - Take care to enable ACL plugin also, otherwise all users can access all the shared +## - mailboxes, assuming they have permissions on filesystem level to do so. +## - we will do that later.. +## - namespace { +## - type = shared +## - separator = / +## - prefix = shared/%%u/ +## - location = maildir:/var/vmail/%%d/%%n/Maildir:INDEX=~/Maildir/shared/%%u +## - subscriptions = no +## - list = children +## - } +## - +echononl "\tAdd namespaces type shared to 10-mail.conf" +cat <> /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf + +namespace { + #type = shared + #separator = / + type = shared + separator = / + + # Mailboxes are visible under "shared/user@domain/" + # %%n, %%d and %%u are expanded to the destination user. + #prefix = shared/%%u/ + prefix = shared/%%u/ + + # Mail location for other users' mailboxes. Note that %variables and ~/ + # expands to the logged in user's data. %%n, %%d, %%u and %%h expand to the + # destination user's data. + #location = maildir:%%h/Maildir:INDEX=~/Maildir/shared/%%u + location = maildir:/var/vmail/%%d/%%n/Maildir:INDEX=~/Maildir/shared/%%u + + # Use the default namespace for saving subscriptions. + subscriptions = no + + # List the shared/ namespace only if there are visible shared mailboxes. + list = children +} +EOF +if [ "$?" = 0 ]; then + echo -e "$rc_done" +else + echo -e "$rc_failed" + fatal "Adding namespaces to /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf failed" +fi + +## - edit /usr/local/dovecot/etc/dovecot/conf.d/20-imap.conf +## - +## - mail_plugins = $mail_plugins imap_quota imap_acl +## - +_failed=false +echononl "\tAdd mail_plugin imap_acl to 20-imap.conf" +perl -i -n -p -e "s#^([ ]*)\#?\ ?(mail_plugins\ +=.*)#\1\#\# \2\n\1mail_plugins = \\\$mail_plugins imap_quota imap_acl#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-imap.conf || _failed=true +if ! $_failed ; then + echo -e "$rc_done" +else + echo -e "$rc_failed" + fatal "Adjusting file /usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-imap.conf failed" +fi + +## - edit /usr/local/dovecot/etc/dovecot/conf.d/10-mail.conf +## - +## - mail_plugins = quota expire acl +## - +_failed=false +echononl "\tAdd mail_plugin acl to 10-mail.conf" + +if $plugin_expire ; then + perl -i -n -p -e "s#^([ ]*)\#?\ ?(mail_plugins\ +=.*)#\1\#\# \2\n\1mail_plugins = quota expire acl#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf || _failed=true +else + perl -i -n -p -e "s#^([ ]*)\#?\ ?(mail_plugins\ +=.*)#\1\#\# \2\n\1mail_plugins = quota acl#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf || _failed=true +fi + +if ! $_failed ; then + echo -e "$rc_done" +else + echo -e "$rc_failed" + fatal "Adjusting file /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf failed" +fi + + +## - !! Notice !! +## - There a two possibilities, configuring acl backend: +## - - flat file +## - - SQL dictionary +## - +## - On rage.so36.net we actually uses SQL dictionary not a flat file + +## ----------------- +## - Using a flat file as dictionary backend +## - + +## - edit /usr/local/dovecot/etc/dovecot/conf.d/90-acl.conf +## - +## - plugin { +## - # Without global ACLs: +## - acl = vfile +## - +## - # With global ACLs in /etc/dovecot/acls/ directory: +## - #acl = vfile:/etc/dovecot/acls +## - #acl = vfile:/etc/dovecot/acls:cache_secs=300 +## - } +## - +## - plugin { +## - #acl_shared_dict = file:/run/dovecot/shared-mailboxes.db +## - acl_shared_dict = file:/var/vmail/shared-mailboxes.db +## - } +## - +#perl -i.ORIG -n -p -e "s#^([ ]*)\#?\ ?(acl\ +=.*)#\1\#\# \2\n\n\1\# Without global ACLs:\n\1acl = vfile\n\n\1\# With global ACLs in /etc/dovecot/acls/ directory:\n\1\#acl = vfile:/etc/dovecot/acls\n\1\#acl = vfile:/etc/dovecot/acls:cache_secs=300#g" \ +# /usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-acl.conf +#perl -i -n -p -e "s#^([ ]*)\#?\ ?(acl_shared_dict\ +=.*)#\1\#\# \2\n\1acl_shared_dict = file:/var/vmail/shared-mailboxes.db#g" \ +# /usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-acl.conf + +## - +## - End: Using a flat file as dictionary backend +## ------------------------------------------------------------------------ + + +## ------------------------------------------------------------------------ +## - Using SQL dictionary +## - + +## - edit /usr/local/dovecot/etc/dovecot/conf.d/90-acl.conf +## - +## - plugin { +## - ## acl = vfile:/etc/dovecot/global-acls:cache_secs=300 +## - +## - # Without global ACLs: +## - acl = vfile +## - .. +## - } +## - plugin { +## - acl_shared_dict = proxy::acl +## - } +## - +_failed=false +echononl "\tConfigure acl (90-acl.conf)" +perl -i.ORIG -n -p -e "s#^([ ]*)\#?\ ?(acl\ +=.*)#\1\#\# \2\n\n\1\# Without global ACLs:\n\1acl = vfile\n\n\1\# With global ACLs in /etc/dovecot/acls/ directory:\n\1\#acl = vfile:/etc/dovecot/acls\n\1\#acl = vfile:/etc/dovecot/acls:cache_secs=300#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-acl.conf || _failed=true +perl -i -n -p -e "s#^([ ]*)\#?\ ?(acl_shared_dict\ +=.*)#\1\#\# \2\n\1acl_shared_dict = proxy::acl#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-acl.conf || _failed=true +if ! $_failed ; then + echo -e "$rc_done" +else + echo -e "$rc_failed" + fatal "Adjusting file /usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-acl.conf failed" +fi + +## - edit /usr/local/dovecot/etc/dovecot/dovecot.conf +## - +## - dict { +## - acl = $db_driver:/usr/local/dovecot/etc/dovecot/sql-dict.conf.ext +## - ... +## - } +## - +_failed=false +echononl "\tAdjust file dovecot.conf for (dict) acl service" +perl -i -n -p -e "s#^([ ]*)(dict\ +{.*)#\1\2\n\1 acl = $db_driver:/usr/local/dovecot/etc/dovecot/sql-dict.conf.ext#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/dovecot.conf || _failed=true +if ! $_failed ; then + echo -e "$rc_done" +else + echo -e "$rc_failed" + fatal "Adjusting file /usr/local/dovecot-${_version}/etc/dovecot/dovecot.conf failed" +fi + +if $_new ; then + if [ "$db_driver" = "pgsql" ]; then + + ## - Create tables user_shares / anyone_shares + ## - + echononl "\tCreate table user_share" + cat << EOF | psql -U$dbuser $dbname > /dev/null 2>&1 +CREATE TABLE IF NOT EXISTS user_shares ( + from_user varchar(100) not null, + to_user varchar(100) not null, + dummy char(1) DEFAULT '1', -- always '1' currently + primary key (from_user, to_user) +); +COMMENT ON TABLE user_shares IS 'User from_user shares folders to user to_user.'; +EOF + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + error "Creating table user_shares failed" + fi + + echononl "\tCreate table anyone_shares" + cat << EOF | psql -U$dbuser $dbname > /dev/null 2>&1 +CREATE TABLE IF NOT EXISTS anyone_shares ( + from_user varchar(100) not null, + dummy char(1) DEFAULT '1', -- always '1' currently + primary key (from_user) +); +COMMENT ON TABLE anyone_shares IS 'User from_user shares folders to anyone.'; +EOF + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + error "Creating table anyone_shares failed" + fi + + elif [ "$db_driver" = "mysql" ]; then + + ## - Create table user_shares / anyone_shares + ## - + echononl "\tCreate table user_share" + cat << EOF | mysql -u$dbuser -p$dbpassword $dbname > /dev/null 2>&1 +CREATE TABLE IF NOT EXISTS user_shares ( + from_user varchar(100) not null, + to_user varchar(100) not null, + dummy char(1) DEFAULT '1', -- always '1' currently + primary key (from_user, to_user) +) COMMENT = 'User from_user shares folders to user to_user.'; +EOF + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + error "Creating table user_shares failed" + fi + + echononl "\tCreate table anyone_shares" + cat << EOF | mysql -u$dbuser -p$dbpassword $dbname > /dev/null 2>&1 +CREATE TABLE IF NOT EXISTS anyone_shares ( + from_user varchar(100) not null, + dummy char(1) DEFAULT '1', -- always '1' currently + primary key (from_user) +) COMMENT = 'User from_user shares folders to anyone.'; +EOF + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + error "Creating table anyone_shares failed" + fi + fi +fi + + +_failed=false +echononl "\tRenew file sql-dict.conf.ext" +if [ "$db_driver" = "pgsql" ]; then + + ## - adjust/renew file /usr/local/dovecot/etc/dovecot/sql-dict.conf.ext + ## - + cat </usr/local/dovecot-${_version}/etc/dovecot/sql-dict.conf.ext +## - if using unix-socket (host=/run/postgresql) ensure that +## - coresponding entries in pg_hba.cof fits +## - for example +## - local all all md5 +## - +connect = host=$dbhost user=$dbuser password=$dbpassword dbname=$dbname + +## - NOTE: +## - +## - All changes on database (CREATE TABLE / CREATE TRIGGER / what else..) +## - need to be done as the dbuser (here postfix) under whom dovecot +## - accesses the database. If not, you have to change the permissiond to allow +## - dovecot dbuser to access the createt table/trigger/... +## - + +# CREATE TABLE quota2 ( +# username varchar(100) not null, +# bytes bigint not null default 0, +# messages integer not null default 0, +# primary key (username) +# ); +# +## - if using postgres, you need also to create a trigger as follows: +## - +## - first create language plpgsql if not yet created: +## - +# CREATE PROCEDURAL LANGUAGE plpgsql; +# +# CREATE FUNCTION merge_quota2() RETURNS trigger +# LANGUAGE plpgsql +# AS \$\$ +# BEGIN +# IF NEW.messages < 0 OR NEW.messages IS NULL THEN +# -- ugly kludge: we came here from this function, really do try to insert +# IF NEW.messages IS NULL THEN +# NEW.messages = 0; +# ELSE +# NEW.messages = -NEW.messages; +# END IF; +# return NEW; +# END IF; +# +# LOOP +# UPDATE quota2 SET bytes = bytes + NEW.bytes, +# messages = messages + NEW.messages +# WHERE username = NEW.username; +# IF found THEN +# RETURN NULL; +# END IF; +# +# BEGIN +# IF NEW.messages = 0 THEN +# INSERT INTO quota2 (bytes, messages, username) VALUES (NEW.bytes, NULL, NEW.username); +# ELSE +# INSERT INTO quota2 (bytes, messages, username) VALUES (NEW.bytes, -NEW.messages, NEW.username); +# END IF; +# return NULL; +# EXCEPTION WHEN unique_violation THEN +# -- someone just inserted the record, update it +# END; +# END LOOP; +# END; +# \$\$; +# +# +# ALTER FUNCTION public.merge_quota2() OWNER TO postfix; +# +# CREATE TRIGGER mergequota2 +# BEFORE INSERT ON quota2 +# FOR EACH ROW +# EXECUTE PROCEDURE merge_quota2(); + +map { + pattern = priv/quota/storage + table = quota2 + username_field = username + value_field = bytes +} +map { + pattern = priv/quota/messages + table = quota2 + username_field = username + value_field = messages +} +EOF + if [[ "$?" -gt 0 ]]; then + _failed=true + fi + + if $plugin_expire ; then + cat <> /usr/local/dovecot-${_version}/etc/dovecot/sql-dict.conf.ext + +# CREATE TABLE expires ( +# username varchar(100) not null, +# mailbox varchar(255) not null, +# expire_stamp integer not null, +# primary key (username, mailbox) +# ); + +## - if using postgres, you need also to create a trigger as follows: +## - +## - first create language plpgsql if not yet created: +## - +# CREATE LANGUAGE plpgsql; +# +# CREATE OR REPLACE FUNCTION merge_expires() RETURNS TRIGGER AS \$\$ +# BEGIN +# UPDATE expires SET expire_stamp = NEW.expire_stamp +# WHERE username = NEW.username AND mailbox = NEW.mailbox; +# IF FOUND THEN +# RETURN NULL; +# ELSE +# RETURN NEW; +# END IF; +# END; +# \$\$ LANGUAGE plpgsql; +# +# CREATE TRIGGER mergeexpires BEFORE INSERT ON expires +# FOR EACH ROW EXECUTE PROCEDURE merge_expires(); + + +map { + pattern = shared/expire/\$user/\$mailbox + table = expires + value_field = expire_stamp + + fields { + username = \$user + mailbox = \$mailbox + } +} +EOF + if [[ "$?" -gt 0 ]]; then + _failed=true + fi + fi + cat <> /usr/local/dovecot-${_version}/etc/dovecot/sql-dict.conf.ext + + +# CREATE TABLE user_shares ( +# from_user varchar(100) not null, +# to_user varchar(100) not null, +# dummy char(1) DEFAULT '1', -- always '1' currently +# primary key (from_user, to_user) +# ); +# COMMENT ON TABLE user_shares IS 'User from_user shares folders to user to_user.'; +# +# CREATE TABLE anyone_shares ( +# from_user varchar(100) not null, +# dummy char(1) DEFAULT '1', -- always '1' currently +# primary key (from_user) +# ); +# COMMENT ON TABLE anyone_shares IS 'User from_user shares folders to anyone.'; + +map { + pattern = shared/shared-boxes/user/\$to/\$from + table = user_shares + value_field = dummy + + fields { + from_user = \$from + to_user = \$to + } +} + +map { + pattern = shared/shared-boxes/anyone/\$from + table = anyone_shares + value_field = dummy + + fields { + from_user = \$from + } +} +EOF + if [[ "$?" -gt 0 ]]; then + _failed=true + fi + + if ! $_failed ; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + fatal "Recreating file /usr/local/dovecot-${_version}/etc/dovecot/sql-dict.conf.ext failed" + fi + +elif [ "$db_driver" = "mysql" ]; then + + ## - adjust/renew file /usr/local/dovecot/etc/dovecot/sql-dict.conf.ext + ## - + cat </usr/local/dovecot-${_version}/etc/dovecot/sql-dict.conf.ext +connect = host=$dbhost user=$dbuser password=$dbpassword dbname=$dbname + +# CREATE TABLE quota2 ( +# username varchar(100) not null, +# bytes bigint not null default 0, +# messages integer not null default 0, +# primary key (username) +# ); + +map { + pattern = priv/quota/storage + table = quota2 + username_field = username + value_field = bytes +} +map { + pattern = priv/quota/messages + table = quota2 + username_field = username + value_field = messages +} +EOF + if [[ "$?" -gt 0 ]]; then + _failed=true + fi + + if $plugin_expire ; then + cat <> /usr/local/dovecot-${_version}/etc/dovecot/sql-dict.conf.ext + +# CREATE TABLE expires ( +# username varchar(100) not null, +# mailbox varchar(255) not null, +# expire_stamp integer not null, +# primary key (username, mailbox) +# ); + + +map { + pattern = shared/expire/\$user/\$mailbox + table = expires + value_field = expire_stamp + + fields { + username = \$user + mailbox = \$mailbox + } +} +EOF + if [[ "$?" -gt 0 ]]; then + _failed=true + fi + fi + cat <> /usr/local/dovecot-${_version}/etc/dovecot/sql-dict.conf.ext + + +# CREATE TABLE user_shares ( +# from_user varchar(100) not null, +# to_user varchar(100) not null, +# dummy char(1) DEFAULT '1', -- always '1' currently +# primary key (from_user, to_user) +# ) COMMENT = 'User from_user shares folders to user to_user.'; +# +# CREATE TABLE anyone_shares ( +# from_user varchar(100) not null, +# dummy char(1) DEFAULT '1', -- always '1' currently +# primary key (from_user) +# ) COMMENT = 'User from_user shares folders to anyone.'; + +map { + pattern = shared/shared-boxes/user/\$to/\$from + table = user_shares + value_field = dummy + + fields { + from_user = \$from + to_user = \$to + } +} + +map { + pattern = shared/shared-boxes/anyone/\$from + table = anyone_shares + value_field = dummy + + fields { + from_user = \$from + } +} +EOF + if [[ "$?" -gt 0 ]]; then + _failed=true + fi + if ! $_failed ; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + fatal "Recreating file /usr/local/dovecot-${_version}/etc/dovecot/sql-dict.conf.ext failed" + fi +fi + +## - +## - End: Using SQL dictionary +## ------------------------------------------------------------------------ + + +## ----------------- +## --- Configure managesieve support for dovecot + +## - edit /usr/local/dovecot/etc/dovecot/conf.d/20-managesieve.conf +## - +## - service managesieve-login { +## - inet_listener sieve { +## - #address = 127.0.0.1 $ipv4 $ipv6 +## - address = 127.0.0.1 +## - port = 4190 +## - } +## - .. +## - } +## - +_failed=false +echononl "\tConfigure managesieve 20-managesieve.conf" +perl -i.ORIG -n -p -e "s#^([ ]*)\#?\ ?(service managesieve-login\ +{.*)#\1service managesieve-login {#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-managesieve.conf || _failed=true +if [[ -n "$ipv6" ]]; then + perl -i -n -p -e "s#^([ ]*)\#?\ ?(inet_listener\ +sieve\ +{.*)#\1inet_listener sieve {\n\1 \#address = 127.0.0.1 $ipv4 $ipv6\n\1 address = 127.0.0.1\n\1 port = 4190\n\1}\n\1\#\# \2#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-managesieve.conf || _failed=true +else + perl -i -n -p -e "s#^([ ]*)\#?\ ?(inet_listener\ +sieve\ +{.*)#\1inet_listener sieve {\n\1 \#address = 127.0.0.1 $ipv4\n\1 address = 127.0.0.1\n\1 port = 4190\n\1}\n\1\#\# \2#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-managesieve.conf || _failed=true +fi +perl -i -n -p -e "s#^([ ]*\#?\ ?vsz_limit.*)#\1\n}#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-managesieve.conf || _failed=true +perl -i -n -p -e "s#^([ ]*)\#?\ ?(service managesieve\ +{.*)#\1service managesieve {#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-managesieve.conf || _failed=true + +# since divecot 2.2.4: process_count changed to process_limit. +# +#perl -i -n -p -e "s#^([ ]*\#?\ ?process_count.*)#\1\n}#g" \ +# /usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-managesieve.conf || _failed=true +perl -i -n -p -e "s#^([ ]*\#?\ ?process_limit.*)#\1\n}#g" \ + /usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-managesieve.conf || _failed=true + +if ! $_failed ; then + echo -e "$rc_done" +else + echo -e "$rc_failed" + fatal "Adjusting file /usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-managesieve.conf failed" +fi + +#_set_link="" +#echo +#echo "Set symlink " +#echo -e -n " /usr/local/dovecot --> dovecot-${_version} /usr/local/dovecot? [y/n]: " +#read _set_link +#if [ "y" = "$_set_link" -o "Y" = "$_set_link" -o "Yes" = "$_set_link" -o "yes" = "$_set_link" ];then +# echononl "\tCreate symlink.." +# rm -f /usr/local/dovecot +# ln -s dovecot-${_version} /usr/local/dovecot +# if [ "$?" = 0 ]; then +# echo -e "$rc_done" +# else +# echo -e "$rc_failed" +# fatal "Creating Symlink /usr/local/dovecot --> dovecot-${_version} /usr/local/dovecot failed" +# fi +#fi + + +## - Add a cronjob to check if certifice/key for dovecot service is-up-to-date +## - +echononl "\tCreate cronjob for checking if certifice/key for dovecot service is-up-to-date" + +if [[ -f "$_backup_crontab_file" ]] ; then + + if ! grep -e "/root/bin/monitoring/check_cert_for_dovecot.sh" "$_backup_crontab_file" > /dev/null ; then + echo "" >> $_backup_crontab_file + echo "# - Check if cert/key for dovecot service is up-to-date" >> $_backup_crontab_file + echo "# -" >> $_backup_crontab_file + echo "46 05 * * * /root/bin/monitoring/check_cert_for_dovecot.sh" >> $_backup_crontab_file + crontab $_backup_crontab_file + echo -e "$rc_done" + else + echo -e "$rc_skipped" + fi + +else + + _crontab_tmp_file=/tmp/crontab_root.$$ + crontab -l > $_crontab_tmp_file 2> /dev/null + + if [[ ! -s $_crontab_tmp_file ]]; then + echo "PATH=/usr/local/dovecot/bin:$PATH" > $_crontab_tmp_file + fi + + if ! grep -e "/root/bin/monitoring/check_cert_for_dovecot.sh" $_crontab_tmp_file > /dev/null ; then + echo "" >> $_crontab_tmp_file + echo "# - Check if cert/key for dovecot service is up-to-date" >> $_crontab_tmp_file + echo "# -" >> $_crontab_tmp_file + echo "46 05 * * * /root/bin/monitoring/check_cert_for_dovecot.sh" >> $_crontab_tmp_file + crontab $_crontab_tmp_file + echo -e "$rc_done" + else + echo -e "$rc_skipped" + fi + rm -f $_crontab_tmp_file + +fi + +echononl "\tRun script 'check_cert_for_dovecot.sh' if possible.." +if [[ -x "/root/bin/monitoring/check_cert_for_dovecot.sh" ]] ; then + /root/bin/monitoring/check_cert_for_dovecot.sh > $log_file 2>&1 + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + error "$(cat "$log_file")" + + echononl "\tcontinue anyway [yes/no]: " + read OK + OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')" + while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do + echononl "Wrong entry! - repeat [yes/no]: " + read OK + done + [[ $OK = "yes" ]] || fatal "Abbruch durch User" + + fi +else + echo -e "$rc_skipped" +fi + + +blank_line +echononl "\tCreate symlink '/usr/local/dovecot' --> 'dovecot-${_version}'.." +rm -f /usr/local/dovecot +ln -s dovecot-${_version} /usr/local/dovecot +if [ "$?" = 0 ]; then + echo -e "$rc_done" +else + echo -e "$rc_failed" + fatal "Creating Symlink /usr/local/dovecot --> dovecot-${_version} /usr/local/dovecot failed" +fi + +#_restart="" +#echo +#echo -e -n "Start/Restart services (dovecot/postfix)? [y/n]: " +#read _restart +#if [ "y" = "$_restart" -o "Y" = "$_restart" -o "Yes" = "$_restart" -o "yes" = "$_restart" ];then +# echononl "\tStart dovecot service.." +# if $systemd_support ; then +# systemctl start dovecot +# else +# /etc/init.d/dovecot start > /dev/null 2>&1 +# fi +# if [ "$?" = 0 ]; then +# echo -e "$rc_done" +# else +# echo -e "$rc_failed" +# error "Starting dovecot service failed" +# fi +# echononl "\tRestart postfix.." +# if $SYSTEMD_EXISTS ; then +# systemctl restart postfix +# else +# /etc/init.d/postfix restart > /dev/null 2>&1 +# fi +# if [ "$?" = 0 ]; then +# echo -e "$rc_done" +# else +# echo -e "$rc_failed" +# fatal "Restarting postfix failed" +# fi +#fi + +echononl "\tStart dovecot service.." +if $systemd_support ; then + systemctl start dovecot +else + /etc/init.d/dovecot start > /dev/null 2>&1 +fi +if [ "$?" = 0 ]; then + echo -e "$rc_done" +else + echo -e "$rc_failed" + error "Starting dovecot service failed" +fi +echononl "\tRestart postfix.." +if $SYSTEMD_EXISTS ; then + systemctl restart postfix +else + /etc/init.d/postfix restart > /dev/null 2>&1 +fi +if [ "$?" = 0 ]; then + echo -e "$rc_done" +else + echo -e "$rc_failed" + fatal "Restarting postfix failed" +fi + +blank_line +echononl "\tSet '_update=true' in file '$(basename "$conf_file")'.." +if grep -q -E "^\s*_update=false" "$conf_file" 2> /dev/null ; then + perl -i -n -p -e "s/^\s*_update=.*/_update=true/" "$conf_file" + if [ "$?" = 0 ]; then + echo -e "$rc_done" + else + echo -e "$rc_failed" + error "Adjusting '"$conf_file"' (set _update=true) failed!" + fi +else + echo -e "$rc_skipped" +fi + +echo -e " + +\033[33m\033[1mNotice:\033[m +The Dovecot Service is configured to support more than 128 simultanously connections. + +So, you have to \033[1mincrease /proc/sys/fs/inotify/max_user_instances\033[m (default is 128): + + # echo \"fs.inotify.max_user_instances = 2048\" >> /etc/sysctl.conf + # sysctl -p + +If you are running dovecot on a Virtual Guest System, you have to do that on the +Host (Root) System. + +" + +clean_up 0