mailsystem/install_update_dovecot.sh

4555 lines
139 KiB
Bash
Executable File

#!/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 <RETURN> 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 <RETURN>"
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<number of cores +1>)
## -
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<Passwort>"
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 <<EOF >/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 <<EOF >/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 <<EOF >> /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 <<EOF > /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 <<EOF > /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 <<EOF > /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 <<EOF > /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 <<EOF >> "$_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 <<EOF > /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 <<EOF > /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 <<EOF > /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 <miquels@cistron.nl>.
# Modified for Debian GNU/Linux
# by Ian Murdock <imurdock@gnu.ai.mit.edu>.
#
# 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 <<EOF >/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 <<EOF >> /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 <<EOF > /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 <<EOF >/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 <<EOF >> /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 <<EOF > /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 <<EOF >> /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 <<EOF > /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 <<EOF >> /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 <<EOF >>/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 <<EOF >/usr/local/bin/quota-warning.sh
#!/usr/bin/env bash
# author: zhang huangbin <michaelbibby (at) gmail.com>
# 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 <<EOF >> /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 <<EOF >/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 <<EOF >> /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 <<EOF >> /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 <<EOF >/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 <<EOF >> /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 <<EOF >> /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