467 lines
15 KiB
Bash
Executable File
467 lines
15 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# Installing a mailserver including postfix postfixadmin and dovecot
|
|
#
|
|
# MTA = Mail Transport Agent (postfix)
|
|
# MDA = Mail Delivery Agent (dovecot)
|
|
# MUA = Mail User Agent (Mail program used by the user)
|
|
|
|
toolName=mailserver
|
|
mtaName=postfix
|
|
mtaUser=postfix
|
|
mtaDeps="$mtaName $mtaName-mysql"
|
|
mtaConfLoc="/etc/$mtaName"
|
|
mtaMysqlConfLoc="$mtaConfLoc/sql"
|
|
mdaName=dovecot
|
|
mdaConfLoc="/etc/$mdaName"
|
|
mdaConfDir="$mdaConfLoc/conf.d"
|
|
mdaDeps="dovecot-imapd dovecot-lmtpd dovecot-mysql dovecot-managesieved dovecot-sieve"
|
|
|
|
# Get script working directory
|
|
# (when called from a different directory)
|
|
WDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >>/dev/null 2>&1 && pwd )"
|
|
CONFIG=0
|
|
CONFIG_FILE_NAME="${toolName}.cfg"
|
|
CONFIG_FILE_TEMPLATE="$WDIR/${CONFIG_FILE_NAME}.example"
|
|
|
|
step_config() {
|
|
if [ $(id -u) -ne 0 ] ; then
|
|
endReturn -o 1 "No root"
|
|
fi
|
|
initSeqConfig "$CONFIG_FILE_NAME" "$CONFIG_FILE_TEMPLATE"
|
|
if [ $? -eq 0 ] ; then
|
|
CONFIG=1
|
|
echoseq " Domain: $MAS_DOMAIN"
|
|
elif [ $? -eq 1 ] ; then
|
|
# Config $CONFIG_FILE_NAME created. Needs modification first
|
|
[ $DRY -eq 0 ] && return -1
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
step_1_info() { echo "Update apt repositories"; }
|
|
step_1_alias() { ALIAS="install"; }
|
|
step_1() {
|
|
exe apt update
|
|
}
|
|
|
|
step_2_info() { echo "Install $mtaName"; }
|
|
step_2() {
|
|
local aptOpt=
|
|
if [ $QUIET -ne 0 ];then
|
|
aptOpt="-y"
|
|
else
|
|
read -p "In the following dialog chose \"Internet site\" and enter $MAS_DOMAIN as your domain. Enter to continue..."
|
|
fi
|
|
exe apt install $mtaDeps $aptOpt
|
|
}
|
|
|
|
step_3_info() { echo "Enable $mtaName"; }
|
|
step_3() {
|
|
exe systemctl enable $mtaName
|
|
echo -e " [I] Printing $mtaName status\n"
|
|
exe service $mtaName status
|
|
echo -e "\n [I] Installed postfix version: $(postconf mail_version)"
|
|
}
|
|
|
|
step_4_info() { echo "$mtaName basic domain configuration"; }
|
|
step_4() {
|
|
exe postconf -e "myhostname = mail.$MAS_DOMAIN"
|
|
exe postconf -e "mydomain = $MAS_DOMAIN"
|
|
exe postconf -e "myorigin = $MAS_DOMAIN"
|
|
exe postconf -e "mydestination = $MAS_DOMAIN, \$myhostname, mail.\$mydomain, localhost.\$mydomain, localhost"
|
|
}
|
|
|
|
step_5_info() { echo "$mtaName enable submission service"; }
|
|
step_5() {
|
|
echoseq -e " [I] Copy following lines...\n"
|
|
exe cat "$mtaConfSubmission"
|
|
exe read -rep $'\nPress Enter to open the '$mtaConfLoc'/master.cf'
|
|
exe vi $mtaConfLoc/master.cf
|
|
exe echoseq
|
|
exe cat "$mtaConfSmtps"
|
|
exe read -rep $'\nPress Enter to open the '$mtaConfLoc'/master.cf'
|
|
exe vi $mtaConfLoc/master.cf
|
|
}
|
|
mtaConfSubmission="$WDIR/$toolName/submissionService"
|
|
mtaConfSmtps="$WDIR/$toolName/smtpsService"
|
|
|
|
step_6_info() { echo "Configure TLS"; }
|
|
step_6() {
|
|
exe postconf "smtpd_tls_cert_file = /etc/letsencrypt/live/$MAS_DOMAIN/fullchain.pem"
|
|
exe postconf "smtpd_tls_key_file = /etc/letsencrypt/live/$MAS_DOMAIN/privkey.pem"
|
|
|
|
#Force TLSv1.3 or TLSv1.2
|
|
exe postconf "smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1"
|
|
exe postconf "smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1"
|
|
exe postconf "smtp_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1"
|
|
exe postconf "smtp_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1"
|
|
|
|
echoseq " [I] Restarting $mtaName"
|
|
exe service $mtaName restart
|
|
}
|
|
|
|
step_7_info() {
|
|
echo "Restrict client access"
|
|
echoinfo "Mainly PTR record check"
|
|
}
|
|
step_7() {
|
|
exe postconf -e "smtpd_client_restrictions = permit_mynetworks, reject_unknown_client_hostname"
|
|
}
|
|
|
|
step_8_info() { echo "Install $mdaName"; }
|
|
step_8() {
|
|
exe apt install $mdaDeps
|
|
echoseq -e "\n [I] Installed version: $(dovecot --version)"
|
|
}
|
|
|
|
step_9_info() {
|
|
echo "Configure $mdaName"
|
|
}
|
|
step_9() {
|
|
outColor green
|
|
cat <<MDA_EOF
|
|
# Configuring Mailbox Location
|
|
[/etc/dovecot/conf.d/10-mail.conf]
|
|
mail_location = maildir:~/Maildir
|
|
mail_privileged_group = mail
|
|
|
|
usermod -aG mail dovecot
|
|
|
|
# Configuring Authentication Mechanism
|
|
[/etc/dovecot/conf.d/10-auth.conf]
|
|
disable_plaintext_auth = yes
|
|
# Login with full mail address
|
|
auth_username_format = %n
|
|
# "login" to support older mail clients
|
|
auth_mechanisms = plain login
|
|
|
|
# Configure SSL/TLS Encryption
|
|
[/etc/dovecot/conf.d/10-ssl.conf]
|
|
ssl = required
|
|
ssl_cert = </etc/letsencrypt/live/$MAS_DOMAIN/fullchain.pem
|
|
ssl_key = </etc/letsencrypt/live/$MAS_DOMAIN/privkey.pem
|
|
ssl_min_protocol = TLSv1.2
|
|
ssl_prefer_server_ciphers = yes
|
|
ssl_dh = </etc/dovecot/dh.pem
|
|
|
|
openssl dhparam -out /etc/dovecot/dh.pem 4096
|
|
|
|
# SASL Authentication Between Postfix and Dovecot
|
|
[/etc/dovecot/conf.d/10-master.conf]
|
|
# Add to service auth {
|
|
service auth {
|
|
unix_listener /var/spool/postfix/private/auth {
|
|
mode = 0600
|
|
user = postfix
|
|
group = postfix
|
|
}
|
|
}
|
|
|
|
# Auto-subscribe Drafts, Sent, Junk and Trash Folder
|
|
and auto delete after 30 days
|
|
[/etc/dovecot/conf.d/15-mailboxes.conf]
|
|
# Add "auto = create" to folder e.g.:
|
|
mailbox Trash {
|
|
auto = subscribe
|
|
autoexpunge = 30d
|
|
special_use = \\Trash
|
|
}
|
|
|
|
# Using Dovecot to Deliver Email to Message Store
|
|
Make sure lmtp protocol is installed with dovecot-lmtp
|
|
[/etc/dovecot/conf.d/10-master.conf]
|
|
# Change lmtp service definition to:
|
|
service lmtp {
|
|
unix_listener /var/spool/postfix/private/dovecot-lmtp {
|
|
mode = 0600
|
|
user = postfix
|
|
group = postfix
|
|
}
|
|
}
|
|
|
|
postconf -e "mailbox_transport = lmtp:unix:private/dovecot-lmtp"
|
|
postconf -e "smtputf8_enable = no"
|
|
|
|
# Clean outgoing mail header from sensitiv information
|
|
[/etc/postfix/master.cf]
|
|
smtps inet n - y - - smtpd
|
|
[...]
|
|
-o cleanup_service_name=headclean
|
|
#add below "cleanup"
|
|
headclean unix n - - - 0 cleanup
|
|
-o header_checks=regexp:/etc/postfix/sender_header_checks
|
|
|
|
[/etc/postfix/sender_header_checks]
|
|
/^Received:/ IGNORE
|
|
/^X-PHP-Originating-Script:/ IGNORE
|
|
/^X-Originating-IP:/ IGNORE
|
|
/^X-Mailer:/ IGNORE
|
|
/^User-Agent:/ IGNORE
|
|
MDA_EOF
|
|
}
|
|
|
|
step_20_info() {
|
|
echo "Install postfixadmin and create mysql database"
|
|
echoinfo "Virtualize mailboxes, domains and aliases by using a mysql database"
|
|
}
|
|
step_20_alias() { ALIAS="virtual"; }
|
|
step_20() {
|
|
local qOpt=
|
|
if [ $QUIET -ne 0 ] ; then
|
|
qOpt="-q"
|
|
fi
|
|
exe $WDIR/postfixadmin.sh ${qOpt} install
|
|
}
|
|
|
|
step_21_info() { echo "Create $mtaName mysql query files"; }
|
|
step_21() {
|
|
# eval needed to expand sourced configuration variables
|
|
local localMysqlUser=`eval "echo \"$MAS_VIRTUAL_USER_PART\""`
|
|
|
|
exe mkdir -p "$mtaMysqlConfLoc"
|
|
|
|
local mtaFile
|
|
local mtaVar
|
|
local mtaMysqlFiles=(\
|
|
"mysql_virtual_domains_maps"\
|
|
"mysql_virtual_mailbox_maps"\
|
|
"mysql_virtual_alias_domain_mailbox_maps"\
|
|
"mysql_virtual_alias_maps"\
|
|
"mysql_virtual_alias_domain_maps"\
|
|
"mysql_virtual_alias_domain_catchall_maps"\
|
|
)
|
|
|
|
for mtaFile in ${mtaMysqlFiles[@]}
|
|
do
|
|
eval 'mtaVar=$MAS_'${mtaFile}
|
|
echoseq " [I] creating ${mtaFile}.cf"
|
|
exe echo -e "$localMysqlUser\n$mtaVar" > "$mtaMysqlConfLoc/${mtaFile}.cf"
|
|
done
|
|
|
|
exe chown -R root:${mtaUser} "$mtaMysqlConfLoc"
|
|
exe chmod 640 "${mtaMysqlConfLoc}"/*
|
|
}
|
|
|
|
step_22_info() { echo "Modify $mtaName configuration for virtual mailboxes"; }
|
|
step_22() {
|
|
exe postconf -e "virtual_mailbox_domains = proxy:mysql:/etc/postfix/sql/mysql_virtual_domains_maps.cf"
|
|
exe postconf -e "virtual_mailbox_maps = proxy:mysql:/etc/postfix/sql/mysql_virtual_mailbox_maps.cf, proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_domain_mailbox_maps.cf"
|
|
exe postconf -e "virtual_alias_maps = proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_maps.cf, proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_domain_maps.cf, proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_domain_catchall_maps.cf"
|
|
exe postconf -e "virtual_transport = lmtp:unix:private/dovecot-lmtp"
|
|
|
|
# Apex domain removed, it is handled as virtual domain now
|
|
exe postconf -e "mydestination = \$myhostname, localhost.\$mydomain, localhost"
|
|
# Base location for the virtual maildirs
|
|
exe postconf -e "virtual_mailbox_base = $MAS_VIRTUAL_FOLDER_BASE"
|
|
exe postconf -e "virtual_minimum_uid = $MAS_VIRTUAL_USER_ID"
|
|
exe postconf -e "virtual_uid_maps = static:$MAS_VIRTUAL_USER_ID"
|
|
exe postconf -e "virtual_gid_maps = static:$MAS_VIRTUAL_USER_ID"
|
|
}
|
|
|
|
step_23_info() { echo "Create virtual user $MAS_VIRTUAL_USER and folder $MAS_VIRTUAL_FOLDER_BASE"; }
|
|
step_23() {
|
|
exe mkdir -p "$MAS_VIRTUAL_FOLDER_BASE"
|
|
exe groupadd --gid $MAS_VIRTUAL_USER_ID $MAS_VIRTUAL_USER
|
|
exe adduser --disabled-login --disabled-password --home "$MAS_VIRTUAL_FOLDER_BASE" --uid $MAS_VIRTUAL_USER_ID --gid $MAS_VIRTUAL_USER_ID $MAS_VIRTUAL_USER
|
|
exe chown -R ${MAS_VIRTUAL_USER}: "$MAS_VIRTUAL_FOLDER_BASE"
|
|
exe chmod -R 770 "$MAS_VIRTUAL_FOLDER_BASE"
|
|
|
|
echoseq " [I] Restarting $mtaName"
|
|
exe service $mtaName restart
|
|
}
|
|
|
|
step_24_info() { echo "$mdaName virtualisation configuration instructions"; }
|
|
step_24() {
|
|
echo "# Configuring Mailbox Location"
|
|
echo " [/etc/dovecot/conf.d/10-mail.conf]"
|
|
echo " mail_location = maildir:~/Maildir"
|
|
echo " mail_home = ${MAS_VIRTUAL_FOLDER_BASE}/%d/%n"
|
|
echo
|
|
echo "# Configure authentication"
|
|
echo " [/etc/dovecot/conf.d/10-auth.conf]"
|
|
echo " # Username with domain"
|
|
echo " auth_username_format = %u"
|
|
echo " # Find and uncomment following line"
|
|
echo " !include auth-sql.conf.ext"
|
|
echo " # Comment following line to prevent local users from sending mail"
|
|
echo " # without having registered an email address"
|
|
echo " #!include auth-system.conf.ext"
|
|
echo " # Debug login issues in /var/log/maillog by adding:"
|
|
echo " auth_debug = yes"
|
|
echo " auth_debug_passwords = yes"
|
|
echo
|
|
echo "# Adding mysql login information"
|
|
echo " [/etc/dovecot/dovecot-sql.conf.ext]"
|
|
echo " driver = mysql"
|
|
echo " connect = host=$MAS_DBHOST dbname=$MAS_DBNAME user=$MAS_DBUSER password='${MAS_DBPASS}'"
|
|
echo " default_pass_scheme = MD5"
|
|
echo " password_query = SELECT username AS user,password FROM mailbox WHERE username = '%u' AND active='1'"
|
|
echo " user_query = SELECT maildir, $MAS_VIRTUAL_USER_ID AS uid, $MAS_VIRTUAL_USER_ID AS gid FROM mailbox WHERE username = '%u' AND active='1'"
|
|
echo " iterate_query = SELECT username AS user FROM mailbox"
|
|
}
|
|
|
|
step_25_info() {
|
|
echo "Configure sieve for virtual users"
|
|
}
|
|
step_25() {
|
|
echo "# Sieve script configuration"
|
|
echo " [$mdaConfDir/90-sieve.conf]"
|
|
echo " sieve = file:/var/vmail/%d/%n/sieve;active=/var/vmail/%d/%n/.dovecot.sieve"
|
|
echo " sieve_extensions = +notify +imapflags +vnd.dovecot.execute"
|
|
echo " sieve_plugins = sieve_extprograms"
|
|
echo " sieve_user_log = file:/var/vmail/%d/%n/sieve/sieve.log"
|
|
echo
|
|
echo "# Enable sieve for lmtp"
|
|
echo " [$mdaConfDir/20-lmtp.conf]"
|
|
echo " postmaster_address = postmaster@$MAS_DOMAIN"
|
|
echo " mail_plugins = $mail_plugins sieve"
|
|
echo
|
|
echo "# Enable excution of external programs (e.g. to send xmpp messages on certain keywords)"
|
|
echo " [$mdaConfDir/90-sieve-extprograms.conf]"
|
|
echo " sieve_execute_bin_dir = /usr/lib/dovecot/sieve-execute"
|
|
echo
|
|
echo "# Notes on execution of scripts"
|
|
echo " * Scripts are executed with the $MAS_VIRTUAL_USER user"
|
|
echo " * Scripts must no be writeable by others"
|
|
echo " (chown root:$MAS_VIRTUAL_USER script; chmod 750 script)"
|
|
echo " * \$HOME is set to the virtual users home"
|
|
echo " (e.g. /var/vmail/$MAS_DOMAIN/max)"
|
|
echo
|
|
echo "# Notes about sendxmpp"
|
|
echo " * .sendxmpprc resides in every virtual users home"
|
|
echo " and must be owned by $MAS_VIRTUAL_USER"
|
|
echo " (chown $MAS_VIRTUAL_USER: .sendxmpprc; chmod 700 .sendxmpprc)"
|
|
}
|
|
|
|
step_50_info() { echo "Adding default relay host for sending mails"; }
|
|
step_50_alias() { ALIAS="default_relay"; }
|
|
step_50() {
|
|
if [ ! -f "$saslPassFile" ] ; then
|
|
exe postconf -e "relayhost = $MAS_RELAYHOST"
|
|
exe postconf -e "smtp_sasl_auth_enable = yes"
|
|
exe postconf -e "smtp_sasl_password_maps = hash:$saslPassFile"
|
|
addConf -s "$MAS_RELAYHOST $MAS_RELAYUSER:$MAS_RELAYPASS" "$saslPassFile"
|
|
fi
|
|
echoseq " [I] Updating $saslPassFile"
|
|
exe postmap "$saslPassFile"
|
|
}
|
|
saslPassFile="$mtaConfLoc/sasl_password"
|
|
|
|
step_52_info() {
|
|
echo "Grant access for specific (local) hostnames"
|
|
echoinfo "Workaround when local clients connect to 25 with different ips (v6)"
|
|
}
|
|
step_52_alias() { ALIAS="client_access"; }
|
|
step_52() {
|
|
if [ ! -f "$mtaClientAccessLoc" ] ; then
|
|
echo " [I] Generating $mtaClientAccessLoc"
|
|
exep "echo \"# myhost.lan OK\" > \"$mtaClientAccessLoc\""
|
|
echo " [I] Don't forget to add the following"
|
|
echo " [$mtaConfLoc/main.cf]"
|
|
echo " smtpd_relay_restrictions ="
|
|
echo " check_client_access hash:$mtaClientAccessLoc"
|
|
fi
|
|
echoseq " [I] Updating $mtaClientAccessLoc"
|
|
exe postmap "$mtaClientAccessLoc"
|
|
}
|
|
mtaClientAccessLoc="$mtaConfLoc/client_access"
|
|
|
|
step_54_info() {
|
|
echo "Deny recipient access for listed mail addresses"
|
|
}
|
|
step_54_alias() { ALIAS="recipient_access"; }
|
|
step_54() {
|
|
if [ ! -f "$mtaRecipientAccessLoc" ] ; then
|
|
echoseq " [I] Generating $mtaRecipientAccessLoc"
|
|
exep "echo \"# unwanted@${MAS_DOMAIN} 550 No mailbox. Nothing to see here.\" > \"$mtaRecipientAccessLoc\""
|
|
echo " [I] Don't forget to add the following"
|
|
echo " [$mtaConfLoc/main.cf]"
|
|
echo " smtpd_recipient_restrictions ="
|
|
echo " check_recipient_access hash:$mtaRecipientAccessLoc"
|
|
fi
|
|
echoseq " [I] Updating $mtaRecipientAccessLoc"
|
|
exe postmap "$mtaRecipientAccessLoc"
|
|
}
|
|
mtaRecipientAccessLoc="$mtaConfLoc/recipient_access"
|
|
|
|
step_56_info() { echo "Add sender dependant relay with authentication"; }
|
|
step_56_alias() { ALIAS="sender_relay"; }
|
|
step_56() {
|
|
if [ ! -f "$mtaSenderRelayLoc" ] ; then
|
|
echoseq " [I] Generating $mtaSenderRelayLoc"
|
|
exep "echo \"# user@extern.com smtp:[mail.extern.com]:587\" > \"$mtaSenderRelayLoc\""
|
|
exe postconf -e "smtp_sender_dependent_authentication = yes"
|
|
exe postconf -e "sender_dependent_relayhost_maps = hash:$mtaSenderRelayLoc"
|
|
exe postconf -e "smtp_sasl_security_options = noanonymous"
|
|
exe postconf -e "smtp_sasl_mechanism_filter = plain"
|
|
exe postconf -e "smtp_tls_security_level = encrypt"
|
|
exe postconf -e "smtp_tls_mandatory_ciphers = high"
|
|
echo " [I] Don't forget to add credentials for the new relay"
|
|
echo " [$saslPassFile]"
|
|
echo " user@extern.com username:passwort"
|
|
echo " postmap $saslPassFile"
|
|
fi
|
|
echoseq " [I] Updating $mtaSenderRelayLoc"
|
|
exe postmap "$mtaSenderRelayLoc"
|
|
exe postmap "$saslPassFile"
|
|
}
|
|
mtaSenderRelayLoc="$mtaConfLoc/sender_relay"
|
|
|
|
step_100_info() {
|
|
echo "Send testmail [-u SYSTEMUSER | -f FROM] [TO]"
|
|
echoinfo "Send as current user to postmaster@\$MAS_DOMAIN by default"
|
|
}
|
|
step_100_alias() { ALIAS="test"; }
|
|
step_100() {
|
|
shift
|
|
local arg
|
|
local fromAdr
|
|
local toAdr="postmaster@$MAS_DOMAIN"
|
|
local asUser=
|
|
for arg in "$@" ; do
|
|
case "$1" in
|
|
-f)
|
|
shift
|
|
fromAdr="-f $1 "
|
|
shift
|
|
;;
|
|
-u)
|
|
shift
|
|
asUser="sudo -u $1 "
|
|
shift
|
|
;;
|
|
*)
|
|
break
|
|
;;
|
|
esac
|
|
done
|
|
if [ ! -z $1 ] ; then
|
|
toAdr="$1"
|
|
fi
|
|
exe ${asUser}sh -c "echo \"Subject: Test from Postfix\nIt is \$(date)\n\nGreetings \$(whoami)\" | sendmail ${fromAdr}$toAdr"
|
|
}
|
|
|
|
step_102_info() { echo "Show mail queue"; }
|
|
step_102_alias() { ALIAS="showqueue"; }
|
|
step_102() {
|
|
exe sendmail -bp
|
|
}
|
|
|
|
step_104_info() {
|
|
echo "Delete mail queue [ID]"
|
|
echoinfo "Delete all queued mails if [ID] is empty"
|
|
}
|
|
step_104_alias() { ALIAS="delqueue"; }
|
|
step_104() {
|
|
shift
|
|
local msgId="ALL"
|
|
if [ ! -z $1 ] ; then
|
|
msgId="$1"
|
|
fi
|
|
exe postsuper -d "$msgId"
|
|
}
|
|
|
|
VERSION_SEQREV=12
|
|
. /usr/local/bin/sequencer.sh
|