456 lines
15 KiB
Bash
Executable File
456 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)
|
|
|
|
readonly toolName=mailserver
|
|
readonly mtaName=postfix
|
|
readonly mtaUser=postfix
|
|
readonly mtaDeps="$mtaName $mtaName-mysql"
|
|
readonly mtaConfLoc="/etc/$mtaName"
|
|
readonly mtaMysqlConfLoc="$mtaConfLoc/sql"
|
|
readonly mdaName=dovecot
|
|
readonly mdaConfLoc="/etc/$mdaName"
|
|
readonly mdaConfDir="$mdaConfLoc/conf.d"
|
|
readonly mdaDeps="dovecot-imapd dovecot-lmtpd dovecot-mysql dovecot-managesieved dovecot-sieve"
|
|
|
|
sq_aptOpt=
|
|
sq_config=0
|
|
|
|
seq_config() {
|
|
root || endReturn -o 1 "No root"
|
|
|
|
#initSeqConfig "$CONFIG_FILE_NAME" "$CONFIG_FILE_TEMPLATE"
|
|
if initSeqConfig "${seq_configName:?}" "${seq_configTemplate:?}" ; then
|
|
sq_config=1
|
|
info " Domain: ${MAS_DOMAIN:-}"
|
|
else
|
|
dry || return 1
|
|
fi
|
|
|
|
## Apt cmdline option to suppress user interaction
|
|
interactive || sq_aptOpt="-y"
|
|
|
|
return 0
|
|
}
|
|
|
|
step_1_info() { echo "Update apt repositories"; }
|
|
step_1_alias() { echo "install"; }
|
|
step_1() {
|
|
exe apt update
|
|
}
|
|
|
|
step_2_info() { echo "Install $mtaName"; }
|
|
step_2() {
|
|
confirm -n -y "In the following dialog chose \"Internet site\" and enter $MAS_DOMAIN as your domain. Enter to continue..."
|
|
exe apt install $mtaDeps ${sq_aptOpt:-}
|
|
}
|
|
|
|
step_3_info() { echo "Enable $mtaName"; }
|
|
step_3() {
|
|
exe systemctl enable $mtaName
|
|
info "Printing $mtaName status"
|
|
exe service $mtaName status
|
|
info "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() {
|
|
local mtaConfSubmission="${seq_origin:?}/$toolName/submissionService"
|
|
local mtaConfSmtps="${seq_origin:?}/$toolName/smtpsService"
|
|
|
|
info "Copy following lines..."
|
|
exe cat "$mtaConfSubmission"
|
|
confirm -n -y "Press Enter to open the $mtaConfLoc/master.cf"
|
|
editor $mtaConfLoc/master.cf
|
|
info
|
|
exe cat "$mtaConfSmtps"
|
|
confirm -n -y "Press Enter to open the $mtaConfLoc/master.cf"
|
|
editor $mtaConfLoc/master.cf
|
|
}
|
|
|
|
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"
|
|
|
|
info "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 ${sq_aptOpt}
|
|
info "Installed version: $(dovecot --version)"
|
|
}
|
|
|
|
step_9_info() {
|
|
echo "Configure $mdaName"
|
|
}
|
|
step_9() {
|
|
color 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() { echo "virtual"; }
|
|
step_20() {
|
|
exe ${seq_origin:?}/postfixadmin.sh ${sqr_args} install
|
|
}
|
|
|
|
step_21_info() { echo "Create $mtaName mysql query files"; }
|
|
step_21() {
|
|
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
|
|
mtaVar="MAS_${mtaFile}"
|
|
info "creating ${mtaFile}.cf"
|
|
exep echo -e "\"${MAS_VIRTUAL_USER_PART:?}\\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"
|
|
|
|
info "Restarting $mtaName"
|
|
exe service $mtaName restart
|
|
}
|
|
|
|
step_24_info() { echo "$mdaName virtualisation configuration instructions"; }
|
|
step_24() {
|
|
color green
|
|
cat <<END_STEP24
|
|
# Configuring Mailbox Location
|
|
[/etc/dovecot/conf.d/10-mail.conf]
|
|
mail_location = maildir:~/Maildir
|
|
mail_home = ${MAS_VIRTUAL_FOLDER_BASE}/%d/%n
|
|
|
|
# Configure authentication
|
|
[/etc/dovecot/conf.d/10-auth.conf]
|
|
# Username with domain
|
|
auth_username_format = %u
|
|
# Find and uncomment following line
|
|
!include auth-sql.conf.ext
|
|
# Comment following line to prevent local users from sending mail
|
|
# without having registered an email address
|
|
#!include auth-system.conf.ext
|
|
# Debug login issues in /var/log/maillog by adding:
|
|
auth_debug = yes
|
|
auth_debug_passwords = yes
|
|
|
|
# Adding mysql login information
|
|
[/etc/dovecot/dovecot-sql.conf.ext]
|
|
driver = mysql
|
|
connect = host=$MAS_DBHOST dbname=$MAS_DBNAME user=$MAS_DBUSER password='${MAS_DBPASS}'
|
|
default_pass_scheme = MD5
|
|
password_query = SELECT username AS user,password FROM mailbox WHERE username = '%u' AND active='1'
|
|
user_query = SELECT maildir, $MAS_VIRTUAL_USER_ID AS uid, $MAS_VIRTUAL_USER_ID AS gid FROM mailbox WHERE username = '%u' AND active='1'
|
|
iterate_query = SELECT username AS user FROM mailbox
|
|
|
|
END_STEP24
|
|
}
|
|
|
|
step_25_info() {
|
|
echo "Configure sieve for virtual users"
|
|
}
|
|
step_25() {
|
|
color green
|
|
cat << END_STEP25
|
|
# Sieve script configuration
|
|
[$mdaConfDir/90-sieve.conf]
|
|
sieve = file:/var/vmail/%d/%n/sieve;active=/var/vmail/%d/%n/.dovecot.sieve
|
|
sieve_extensions = +notify +imapflags +vnd.dovecot.execute
|
|
sieve_plugins = sieve_extprograms
|
|
sieve_user_log = file:/var/vmail/%d/%n/sieve/sieve.log
|
|
|
|
# Enable sieve for lmtp
|
|
[$mdaConfDir/20-lmtp.conf]
|
|
postmaster_address = postmaster@$MAS_DOMAIN
|
|
mail_plugins = \$mail_plugins sieve
|
|
|
|
# Enable excution of external programs (e.g. to send xmpp messages on certain keywords)
|
|
[$mdaConfDir/90-sieve-extprograms.conf]
|
|
sieve_execute_bin_dir = /usr/lib/dovecot/sieve-execute
|
|
|
|
# Notes on execution of scripts
|
|
* Scripts are executed with the $MAS_VIRTUAL_USER user
|
|
* Scripts must no be writeable by others
|
|
(chown root:$MAS_VIRTUAL_USER script; chmod 750 script)
|
|
* \$HOME is set to the virtual users home
|
|
(e.g. /var/vmail/$MAS_DOMAIN/max)
|
|
|
|
# Notes about sendxmpp
|
|
* .sendxmpprc resides in every virtual users home
|
|
and must be owned by $MAS_VIRTUAL_USER
|
|
(chown $MAS_VIRTUAL_USER: .sendxmpprc; chmod 700 .sendxmpprc)
|
|
|
|
END_STEP25
|
|
}
|
|
|
|
step_50_info() { echo "Adding default relay host for sending mails"; }
|
|
step_50_alias() { echo "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
|
|
info "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() { echo "client_access"; }
|
|
step_52() {
|
|
if [ ! -f "$mtaClientAccessLoc" ] ; then
|
|
info "Generating $mtaClientAccessLoc"
|
|
exep echo "# myhost.lan OK" \> "$mtaClientAccessLoc"
|
|
info "Don't forget to add the following"
|
|
info -a "[$mtaConfLoc/main.cf]"
|
|
info -a " smtpd_relay_restrictions ="
|
|
info -a " check_client_access hash:$mtaClientAccessLoc"
|
|
fi
|
|
info "Updating $mtaClientAccessLoc"
|
|
exe postmap "$mtaClientAccessLoc"
|
|
}
|
|
mtaClientAccessLoc="$mtaConfLoc/client_access"
|
|
|
|
step_54_info() {
|
|
echo "Deny recipient access for listed mail addresses"
|
|
}
|
|
step_54_alias() { echo "recipient_access"; }
|
|
step_54() {
|
|
if [ ! -f "$mtaRecipientAccessLoc" ] ; then
|
|
info "Generating $mtaRecipientAccessLoc"
|
|
exep "echo \"# unwanted@${MAS_DOMAIN} 550 No mailbox. Nothing to see here.\" > \"$mtaRecipientAccessLoc\""
|
|
info "Don't forget to add the following"
|
|
info -a "[$mtaConfLoc/main.cf]"
|
|
info -a " smtpd_recipient_restrictions ="
|
|
info -a " check_recipient_access hash:$mtaRecipientAccessLoc"
|
|
fi
|
|
info "Updating $mtaRecipientAccessLoc"
|
|
exe postmap "$mtaRecipientAccessLoc"
|
|
}
|
|
mtaRecipientAccessLoc="$mtaConfLoc/recipient_access"
|
|
|
|
step_56_info() { echo "Add sender dependant relay with authentication"; }
|
|
step_56_alias() { echo "sender_relay"; }
|
|
step_56() {
|
|
if [ ! -f "$mtaSenderRelayLoc" ] ; then
|
|
info "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"
|
|
info "Don't forget to add credentials for the new relay"
|
|
info -a "[$saslPassFile]"
|
|
info -a " user@extern.com username:passwort"
|
|
info -a "postmap $saslPassFile"
|
|
fi
|
|
info "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() { echo "test"; }
|
|
step_100() {
|
|
shift
|
|
local fromAdr
|
|
local toAdr="postmaster@$MAS_DOMAIN"
|
|
local asUser=
|
|
for _ in "$@" ; do
|
|
case "$1" in
|
|
-f)
|
|
shift
|
|
fromAdr="-f ${1:-} "
|
|
shift ;;
|
|
-u)
|
|
shift
|
|
asUser="sudo -u ${1:-} "
|
|
shift ;;
|
|
*)
|
|
break ;;
|
|
esac
|
|
done
|
|
[ -n "${1:-}" ] && toAdr="$1"
|
|
|
|
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() { echo "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() { echo "delqueue"; }
|
|
step_104() {
|
|
shift
|
|
local msgId="ALL"
|
|
[ -n "${1:-}" ] && msgId="$1"
|
|
exe postsuper -d "$msgId"
|
|
}
|
|
|
|
# shellcheck disable=SC2034 # Appears unused
|
|
readonly sqr_minVersion=16
|
|
# shellcheck disable=SC1091 # Don't follow this source
|
|
. /usr/local/bin/sequencer.sh
|