#!/bin/sh
#
# This file is part of OpenMediaVault.
#
# @license   http://www.gnu.org/licenses/gpl.html GPL Version 3
# @author    Volker Theile <volker.theile@openmediavault.org>
# @copyright Copyright (c) 2009-2012 Volker Theile
#
# OpenMediaVault is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# any later version.
#
# OpenMediaVault is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with OpenMediaVault. If not, see <http://www.gnu.org/licenses/>.

# Documentation/Howto:
# http://www.postfix.org/postconf.5.html
# http://www.gtkdb.de/index_7_727.html
# http://irbs.net/internet/postfix/0503/2148.html
# http://gate.io/blogpost34
# http://www.cyberciti.biz/tips/howto-postfix-flush-mail-queue.html
# http://www.tuxfutter.de/wiki/Einrichten_eines_Mailservers_mit_Postfix

# Testing:
# echo "Test" | mail -s "Test subject" -a "From: xxx@yyy.zzz" root
# hostname | mailx -s "root `hostname` `date`" root

# Working with CA certificates:
# - Add new CA certificate to /etc/ssl/certs
# - Modify /etc/ca-certificates.conf
# - Execute update-ca-certificates

set -e

. /etc/default/openmediavault
. /usr/share/openmediavault/scripts/helper-functions

OMV_POSTFIX_CONFIG=${OMV_POSTFIX_CONFIG:-"/etc/postfix/main.cf"}
OMV_POSTFIX_MYDESTINATION=${OMV_POSTFIX_MYDESTINATION:-""}
OMV_POSTFIX_INET_INTERFACES=${OMV_POSTFIX_INET_INTERFACES:-"loopback-only"}
OMV_POSTFIX_SMTP_GENERIC_MAPS=${OMV_POSTFIX_SMTP_GENERIC_MAPS:-"/etc/postfix/generic"}
OMV_POSTFIX_SENDER_CANONICAL_MAPS=${OMV_POSTFIX_SENDER_CANONICAL_MAPS:-"/etc/postfix/sender_canonical"}
OMV_POSTFIX_RECIPIENT_BCC_MAPS=${OMV_POSTFIX_RECIPIENT_BCC_MAPS:-"/etc/postfix/recipient_bcc"}
OMV_POSTFIX_SMTP_SASL_AUTH_ENABLE=${OMV_POSTFIX_SMTP_SASL_AUTH_ENABLE:-"yes"}
OMV_POSTFIX_SMTP_SASL_PASSWORD_MAPS=${OMV_POSTFIX_SMTP_SASL_PASSWORD_MAPS:-"/etc/postfix/sasl_passwd"}
OMV_POSTFIX_SMTP_SASL_SECURITY_OPTIONS=${OMV_POSTFIX_INETINTERFACES:-"noanonymous"}
OMV_POSTFIX_SMTP_SASL_MECHANISM_FILTER=${OMV_POSTFIX_SMTP_SASL_MECHANISM_FILTER:-""}
OMV_POSTFIX_SMTP_HEADER_CHECKS=${OMV_POSTFIX_SMTP_HEADER_CHECKS:-"/etc/postfix/smtp_header_checks"}
OMV_POSTFIX_SMTP_TLS_CAFILE=${OMV_POSTFIX_SMTP_TLS_CAFILE:-"/etc/ssl/certs/ca-certificates.crt"}
OMV_POSTFIX_SMTP_TLS_CAPATH=${OMV_POSTFIX_SMTP_TLS_CAPATH:-"/etc/ssl/certs"}
OMV_POSTFIX_CRON_CONFIG=${OMV_POSTFIX_CRON_CONFIG:-"/etc/cron.hourly/openmediavault-flushmailq"}

# Create '/etc/postfix/main.cf' configuration file
xmlstarlet sel -t -m "//system/email" \
  -o "mydestination = ${OMV_POSTFIX_MYDESTINATION}" -n \
  -o "inet_interfaces = ${OMV_POSTFIX_INET_INTERFACES}" -n \
  -v "concat('relayhost = ',server,':',port)" -n \
  -o "sender_canonical_maps = hash:${OMV_POSTFIX_SENDER_CANONICAL_MAPS}" -n \
  -o "recipient_bcc_maps = hash:${OMV_POSTFIX_RECIPIENT_BCC_MAPS}" -n \
  -o "smtp_generic_maps = hash:${OMV_POSTFIX_SMTP_GENERIC_MAPS}" -n \
  -i "authentication[enable = '1']" \
    -o "smtp_sasl_auth_enable = ${OMV_POSTFIX_SMTP_SASL_AUTH_ENABLE}" -n \
    -o "smtp_sasl_security_options = ${OMV_POSTFIX_SMTP_SASL_SECURITY_OPTIONS}" -n \
    -o "smtp_sasl_password_maps = hash:${OMV_POSTFIX_SMTP_SASL_PASSWORD_MAPS}" -n \
	-o "smtp_sasl_mechanism_filter = ${OMV_POSTFIX_SMTP_SASL_MECHANISM_FILTER}" -n \
  -b \
  -i "tls[. = '1']" \
    -o "smtp_use_tls = yes" -n \
	-o "smtp_tls_CAfile = ${OMV_POSTFIX_SMTP_TLS_CAFILE}" -n \
    -o "smtp_tls_CApath = ${OMV_POSTFIX_SMTP_TLS_CAPATH}" -n \
  -b \
  -o "smtp_header_checks = regexp:${OMV_POSTFIX_SMTP_HEADER_CHECKS}" -n \
  ${OMV_CONFIG_FILE} | xmlstarlet unesc > ${OMV_POSTFIX_CONFIG}

# Create '/etc/postfix/sasl_passwd' configuration file
xmlstarlet sel -t -m "//system/email" \
  -i "authentication[enable = '1']" \
    -v "concat(server,':',port,' ',authentication/username,':',authentication/password)" -n \
  -b \
  ${OMV_CONFIG_FILE} | xmlstarlet unesc > ${OMV_POSTFIX_SMTP_SASL_PASSWORD_MAPS}
chown root:root ${OMV_POSTFIX_SMTP_SASL_PASSWORD_MAPS}
chmod 0600 ${OMV_POSTFIX_SMTP_SASL_PASSWORD_MAPS}
postmap ${OMV_POSTFIX_SMTP_SASL_PASSWORD_MAPS}

# Create '/etc/postfix/generic' configuration file. Add a catch-all recipient,
# thus all emails send to an user/address not existing will be redirected to
# the configured primary recipient address.
myhostname=$(postconf -h myhostname)
xmlstarlet sel -t \
  -i "//system/email/enable[. = '1']" \
	-v "concat('root ',//system/email/sender)" -n \
	-v "concat('openmediavault ',//system/email/sender)" -n \
	-m "//system/usermanagement/users/user[email != '']" \
	  -v "concat(name,' ',email)" -n \
	-b \
	-v "concat('@${myhostname} ',//system/email/primaryemail)" \
  -b \
  ${OMV_CONFIG_FILE} | xmlstarlet unesc > ${OMV_POSTFIX_SMTP_GENERIC_MAPS}
chown root:root ${OMV_POSTFIX_SMTP_GENERIC_MAPS}
chmod 0600 ${OMV_POSTFIX_SMTP_GENERIC_MAPS}
postmap ${OMV_POSTFIX_SMTP_GENERIC_MAPS}

# Create '/etc/postfix/sender_canonical' configuration file. Rewrite all
# outgoing emails with the configured sender address, otherwise the SMTP relay
# will bounce them, e.g.
# postfix/smtp[xxxxx]: XXXXXXXXXX: to=<abc@xyz.localdomain>,
#   orig_to=<test>, relay=mail.gmx.net[x.x.x.x]:25, delay=1,
#   delays=0.02/0.02/0.93/0.06, dsn=5.7.0, status=bounced (host
#   mail.gmx.net[x.x.x.x] said: 550 5.7.0 Sender address does not belong to
#   logged in user {mp030} (in reply to MAIL FROM command))
xmlstarlet sel -t \
  -i "//system/email/enable[. = '1']" \
	-v "concat('@${myhostname} ',//system/email/sender)" -n \
	-v "concat('&quot;&quot; ',//system/email/sender)" \
  -b \
  ${OMV_CONFIG_FILE} | xmlstarlet unesc > ${OMV_POSTFIX_SENDER_CANONICAL_MAPS}
chown root:root ${OMV_POSTFIX_SENDER_CANONICAL_MAPS}
chmod 0600 ${OMV_POSTFIX_SENDER_CANONICAL_MAPS}
postmap ${OMV_POSTFIX_SENDER_CANONICAL_MAPS}

# Create '/etc/postfix/recipient_bcc' configuration file
xmlstarlet sel -t -m "//system/email" \
  -i "enable[. = '1'] and string-length(secondaryemail) > 0" \
	  -v "concat(primaryemail,' ',secondaryemail)" \
  -b \
  ${OMV_CONFIG_FILE} | xmlstarlet unesc > ${OMV_POSTFIX_RECIPIENT_BCC_MAPS}
chown root:root ${OMV_POSTFIX_RECIPIENT_BCC_MAPS}
chmod 0600 ${OMV_POSTFIX_RECIPIENT_BCC_MAPS}
postmap ${OMV_POSTFIX_RECIPIENT_BCC_MAPS}

# Create '/etc/postfix/smtp_header_checks' configuration file
cat <<EOF > ${OMV_POSTFIX_SMTP_HEADER_CHECKS}
# Append the hostname to the email subject
/^Subject: (.*)/ REPLACE Subject: \${1} [$(hostname)]
EOF
chown root:root ${OMV_POSTFIX_SMTP_HEADER_CHECKS}
chmod 0600 ${OMV_POSTFIX_SMTP_HEADER_CHECKS}

# Create a hourly cron job that flushes the postfix mail queue if email
# notification is disabled.
if [ "$(omv_config_get "//system/email/enable")" = "0" ]; then
	cat <<EOF > ${OMV_POSTFIX_CRON_CONFIG}
#!/bin/sh
# Flush the mail queue every hour if email notification is disabled.
postsuper -d ALL
EOF
	chmod 755 ${OMV_POSTFIX_CRON_CONFIG}
else
	rm -f ${OMV_POSTFIX_CRON_CONFIG}
fi
