Table des matières

Requisits

Firsts remarks

  1. By initial choice, user mail directories are composed like this : /data/vmail/domainname/username/
  2. You must have a valid FQDN with the corresponding reverse DNS.
  3. You must have SSL/TLS certificates.
  4. Postfix configuration here is not suited to high traffic servers (ISP), for this target, see : hash_queue_depth and http://www.postfix.org/TUNING_README.html

Variables

RQ : change the 3 usernames and their passwords, the mail domain and the server hostname

# for postfixadmin
export PFADBNAME="db_pfadmin"
export PFADBUSER="pfadmin"
export PFADBPW="PASS1_CHANGEME"
 
export PFARODBNAME="db_pfadmin"
export PFARODBUSER="pfa_ro"
export PFARODBPW="PASS2_CHANGEME"
 
export PFARWDBNAME="db_pfadmin"
export PFARWDBUSER="pfa_rw"
export PFARWDBPW="PASS3_CHANGEME"
 
export DEFAULT_MAIL_DOMAIN="<changeme>"
export MAIL_SERVER_HOSTNAME="<changeme>"
export MAIL_SERVER_FQDN="${MAIL_SERVER_HOSTNAME}.${DEFAULT_MAIL_DOMAIN}"

Begin safely

Server update and resolvconf installation :

apt-get update
apt-get upgrade
apt-get install resolvconf

Network interfaces :

vi /etc/network/interfaces

Verify/add : “dns-nameservers 127.0.0.1 <DNS_R_1> <DNS_R_2>”

vi /etc/hosts
/etc/hosts
127.0.0.1	localhost
<IP publique>	<FQDN>	<HOSTNAME>

DNS cache

apt-get install bind9
cp -a /etc/bind/named.conf.local /etc/bind/named.conf.local_
sed -i "s/\/\/include \"\/etc\/bind\/zones\.rfc1918\"\;/include \"\/etc\/bind\/zones\.rfc1918\"\;/g" /etc/bind/named.conf.local
/etc/init.d/bind9 stop
/etc/init.d/bind9 start

IF NO IPV6 (RQ bug on jessie : https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=767798)

cp -a /etc/default/bind9 /etc/default/bind9_
sed -i "s/RESOLVCONF=no/RESOLVCONF=yes/g" /etc/default/bind9
sed -i "s/OPTIONS=\"-u bind\"/OPTIONS=\"-4 -u bind\"/g" /etc/default/bind9
/etc/init.d/bind9 stop
/etc/init.d/bind9 start
sleep 3
rndc flush

Network restart

/etc/init.d/networking stop ; /etc/init.d/networking start

Rq : if the FQDN was changed, restart the server.

mysql-server installation

apt-get install mysql-server
# New mysql superuser password : enter and keep safely somwhere (ex : keepass)
apt-get install dbconfig-common

postfixadmin / postfix / dovecot installation

DBs configuration

DBs and users creation for postfixadmin

echo "create database $PFADBNAME;" > /opt/create_db_pfa
echo "grant usage on *.* to $PFADBUSER@localhost identified by '$PFADBPW';" >> /opt/create_db_pfa
echo "grant all privileges on $PFADBNAME.* to $PFADBUSER@localhost ;" >> /opt/create_db_pfa
echo "grant usage on *.* to $PFARODBUSER@localhost identified by '$PFARODBPW';" >> /opt/create_db_pfa
echo "GRANT SELECT ON $PFARODBNAME.* TO $PFARODBUSER@localhost;" >> /opt/create_db_pfa
echo "grant usage on *.* to $PFARWDBUSER@localhost identified by '$PFARWDBPW';" >> /opt/create_db_pfa
echo "GRANT SELECT,UPDATE,INSERT ON $PFARWDBNAME.* TO $PFARWDBUSER@localhost;" >> /opt/create_db_pfa
cat /opt/create_db_pfa | mysql --defaults-extra-file=/etc/mysql/debian.cnf
rm /opt/create_db_pfa

dbconfig preconfiguration for postfixadmin :

cat << 'EOF' > /etc/dbconfig-common/postfixadmin.conf
dbc_install='true'
dbc_upgrade='true'
dbc_remove=''
dbc_dbtype='mysql'
dbc_dbuser=''
dbc_dbpass=''
dbc_dbserver=''
dbc_dbport=''
dbc_dbname=''
dbc_dbadmin='root'
dbc_basepath=''
dbc_ssl=''
dbc_authmethod_admin=''
dbc_authmethod_user=''
EOF
 
sed -i "s/dbc_dbname='.*$/dbc_dbname='$PFADBNAME'/g" /etc/dbconfig-common/postfixadmin.conf
sed -i "s/dbc_dbuser='.*$/dbc_dbuser='$PFADBUSER'/g" /etc/dbconfig-common/postfixadmin.conf
sed -i "s/dbc_dbpass='.*$/dbc_dbpass='$PFADBPW'/g" /etc/dbconfig-common/postfixadmin.conf

postfixadmin installation

apt-get install postfixadmin
# auto reconfigure : apache2
# reconfigure postfixadmin with dbconfig-common ? yes
# DB server to use with postfixadmin : mysql
# DB admin password : enter mysql superadmin password
# choose to install the package maintainer configuration file 

postfix installation

if [ -e /var/log/exim4/paniclog ]; then rm /var/log/exim4/paniclog; fi
apt-get install postfix postfix-mysql dovecot-common
# mail server conf type : internet site
# mailserver name : entrer the public FQDN of the mailserver
apt-get remove --purge exim4 exim4-base exim4-config exim4-daemon-heavy exim4-daemon-light exim4-config-2 exim4-localscanapi-1.0 exim4-localscanapi-1.1
rm -rf /etc/exim4

dovecot installation

apt-get install dovecot-mysql dovecot-sieve dovecot-imapd dovecot-lmtpd dovecot-managesieved 

Apache initial configuration

see corresponding howto

postfixadmin configuration

cp -a /etc/apache2/conf-available/postfixadmin.conf /etc/apache2/conf-available/postfixadmin.conf_
sed -i "s/Alias \/postfixadmin .*$/Alias \/admin_pfa \/usr\/share\/postfixadmin/g" /etc/apache2/conf-available/postfixadmin.conf
cp -a /etc/postfixadmin/dbconfig.inc.php /etc/postfixadmin/dbconfig.inc.php_
sed -i "s|\$dbtype=.*|\$dbtype='mysqli';|g" /etc/postfixadmin/dbconfig.inc.php
 
/etc/init.d/apache2 stop
/etc/init.d/apache2 start
# verify that the webserver is responding : http://fqdn/admin_pfa
 
vi /etc/postfixadmin/config.inc.php
# change these fields :
XXX
#$CONF['postfix_admin_url'] = '/postfixadmin';
$CONF['postfix_admin_url'] = '/admin_pfa';
$CONF['default_language'] = 'fr';
$CONF['admin_email'] = 'postmaster@<domain_changeme>';
$CONF['default_aliases'] = array (
    'abuse' => 'admin@<domain_changeme>',
    'hostmaster' => 'admin@<domain_changeme>',
    'postmaster' => 'admin@<domain_changeme>',
    'webmaster' => 'admin@<domain_changeme>',
    'admin' => 'admin@<domain_changeme>'
);
 
$CONF['aliases'] = '0';
$CONF['mailboxes'] = '0';
$CONF['maxquota'] = '1000';
$CONF['domain_path'] = 'YES';
$CONF['domain_in_mailbox'] = 'NO';

Todo by hand :

postfix configuration

service postfix stop

virtual mappings with mysql

# initial backup
cd /etc/postfix
mkdir origin
cp -ar ./* origin 

# postfixadmin compatible mysql queries for postfix
# RQ : we need exported variables we created before for mysql configuration
mkdir /etc/postfix/sql
export PFXSQLCONFDIR=/etc/postfix/sql

echo "# mysql_virtual_alias_maps
user = $PFARODBUSER
password = $PFARODBPW
hosts = localhost
dbname = $PFARODBNAME
query = SELECT goto FROM alias WHERE address='%s' AND active = '1'
#expansion_limit = 100
" > $PFXSQLCONFDIR/mysql_virtual_alias_maps.cf

echo "# mysql_virtual_alias_domain_maps
user = $PFARODBUSER
password = $PFARODBPW
hosts = localhost
dbname = $PFARODBNAME
query = SELECT goto FROM alias,alias_domain WHERE alias_domain.alias_domain = '%d' and alias.address = CONCAT('%u', '@', alias_domain.target_domain) AND alias.active = 1 AND alias_domain.active='1'
" > $PFXSQLCONFDIR/mysql_virtual_alias_domain_maps.cf

echo "# mysql_virtual_alias_domain_catchall_maps
# handles catch-all settings of target-domain
user = $PFARODBUSER
password = $PFARODBPW
hosts = localhost
dbname = $PFARODBNAME
query  = SELECT goto FROM alias,alias_domain WHERE alias_domain.alias_domain = '%d' and alias.address = CONCAT('@', alias_domain.target_domain) AND alias.active = 1 AND alias_domain.active='1'
" > $PFXSQLCONFDIR/mysql_virtual_alias_domain_catchall_maps.cf

echo "# mysql_virtual_domains_maps
user = $PFARODBUSER
password = $PFARODBPW
hosts = localhost
dbname = $PFARODBNAME
query          = SELECT domain FROM domain WHERE domain='%s' AND active = '1'
#query          = SELECT domain FROM domain WHERE domain='%s'
#optional query to use when relaying for backup MX
#query           = SELECT domain FROM domain WHERE domain='%s' AND backupmx = '0' AND active = '1'
#expansion_limit = 100
" > $PFXSQLCONFDIR/mysql_virtual_domains_maps.cf

echo "# mysql_virtual_mailbox_maps
user = $PFARODBUSER
password = $PFARODBPW
hosts = localhost
dbname = $PFARODBNAME
query           = SELECT maildir FROM mailbox WHERE username='%s' AND active = '1'
#expansion_limit = 100
" > $PFXSQLCONFDIR/mysql_virtual_mailbox_maps.cf

echo "# mysql_virtual_alias_domain_mailbox_maps
user = $PFARODBUSER
password = $PFARODBPW
hosts = localhost
dbname = $PFARODBNAME
query = SELECT maildir FROM mailbox,alias_domain WHERE alias_domain.alias_domain = '%d' and mailbox.username = CONCAT('%u', '@', alias_domain.target_domain) AND mailbox.active = 1 AND alias_domain.active='1'
" > $PFXSQLCONFDIR/mysql_virtual_alias_domain_mailbox_maps.cf

echo "# mysql_virtual_mailbox_limit_maps
user = $PFARODBUSER
password = $PFARODBPW
hosts = localhost
dbname = $PFARODBNAME
query = SELECT quota FROM mailbox WHERE username='%s' AND active = '1'
" > $PFXSQLCONFDIR/mysql_virtual_mailbox_limit_maps.cf

echo "# mysql_virtual_sasl-sender-check
user = $PFARODBUSER
password = $PFARODBPW
hosts = localhost
dbname = $PFARODBNAME
query = SELECT goto FROM alias WHERE address='%s' AND active="1"
" > $PFXSQLCONFDIR/mysql_virtual_sasl-sender-check.cf

chown -R root:postfix /etc/postfix/sql
chmod -R 640 /etc/postfix/sql
chmod 750 /etc/postfix/sql

Remove mail sender IP

cat << '__EOF__' >> /etc/postfix/postfix_header-checks.cf
/^received: /     IGNORE
/^X-Sender: /     IGNORE
__EOF__
chown root:postfix /etc/postfix/sql
chmod 640 /etc/postfix/postfix_header-checks.cf

Custom error messages - french

cat << '__EOF__' >> /etc/postfix/bounce.cf.fr
# The failure template is used when mail is returned to the sender;
# either the destination rejected the message, or the destination
# could not be reached before the message expired in the queue.
 
failure_template = <<EOF
Charset: utf-8
From: MAILER-DAEMON (Messagerie auf.org)
Subject: Erreur lors de l'acheminement d'un message
Postmaster-Subject: Postmaster Copy: Undelivered Mail
 
  -- Version française :
Information envoyée par le serveur $myhostname :
Le message électronique attaché ci-dessous n'a pu être acheminé à l'ensemble
de ses destinataires. Vous trouverez plus bas un rapport d'erreur. 
 
  -- English version :
This is the mail system at host $myhostname. Your message could not be
delivered to one or more recipients. It's attached below.
 
  -- Rapport d'erreur / Problem report :
EOF
 
# The delay template is used when mail is delayed. Note a neat trick:
# the default template displays the delay_warning_time value as hours
# by appending the _hours suffix to the parameter name; it displays
# the maximal_queue_lifetime value as days by appending the _days
# suffix.
#
# Other suffixes are: _seconds, _minutes, _weeks. There are no other
# main.cf parameters that have this special behavior.
#
# You need to adjust these suffixes (and the surrounding text) if
# you have very different settings for these time parameters.
 
delay_template = <<EOF
Charset: utf-8
From: MAILER-DAEMON (Messagerie auf.org)
Subject: Retard lors de l'acheminement d'un message
Postmaster-Subject: Postmaster Warning: Delayed Mail
 
  -- Version française :
Information envoyée par le serveur $myhostname :
Le système n'est pas parvenu à acheminer le message ci-dessous depuis plus de
$delay_warning_time_hours heures. L'envoi va être tenté à nouveau pendant $maximal_queue_lifetime_days jours.
** NB : ceci est seulement un message d'information, vous n'avez pas besoin
** de renvoyer votre message.
 
  -- English version :
This is the mail system at host $myhostname.
Your message could not be delivered for more than $delay_warning_time_hours hour(s).
It will be retried until it is $maximal_queue_lifetime_days day(s) old.
** This is a warning only, you do not need to resend your message.
 
  -- Rapport d'erreur / Problem report :
EOF
 
 
#
# The success template is used when mail is delivered to mailbox,
# when an alias or list is expanded, or when mail is delivered to a
# system that does not announce DSN support. It is an error to specify
# a Postmaster-Subject: here.
#
 
success_template = <<EOF
Charset: utf-8
From: MAILER-DAEMON (Messagerie auf.org)
Subject: Message delivre avec succes
 
  -- Version française :
Information envoyée par le serveur $myhostname :
Votre message a été acheminé avec succès aux destinations indiquées ci-dessous.
Si le message est arrivé dans la boîte aux lettres finale vous ne recevrez pas
d'autres informations, sinon d'autres d'erreurs peuvent survenir et vous serons
éventuellement signalées par d'autres systèmes.
 
  -- English version :
This is the mail system at host $myhostname.
Your message was successfully delivered to the destination(s) listed below. If
the message was delivered to mailbox you will receive no further notifications.
Otherwise you may still receive notifications of mail delivery errors from
other systems.
 
EOF
 
# The verify template is used for address verification (sendmail -bv
# address...). or for verbose mail delivery (sendmail -v address...).
# It is an error to specify a Postmaster-Subject: here.
 
verify_template = <<EOF
Charset: utf-8
From: MAILER-DAEMON (Messagerie auf.org)
Subject: Mail Delivery Status Report
 
  -- Version française :
Information envoyée par le serveur $myhostname :
Ci-dessous le rapport d'acheminement que vous avez demandé.
 
  -- English version :
This is the mail system at host $myhostname.
Enclosed is the mail delivery report that you requested.
 
EOF
__EOF__
chown root:root /etc/postfix/bounce.cf.fr
chmod 644 /etc/postfix/bounce.cf.fr

Cleanup the safe run postfix environment :

rm /var/lib/postfix/*

main.cf file

vi /etc/postfix/main.cf
/etc/postfix/main.cf
# See /usr/share/postfix/main.cf.dist for a commented, more complete version
 
#################################################
# Main domain & conf
#
myhostname = _MAIL_SERVER_FQDN_
mydomain = _DEFAULT_MAIL_DOMAIN_
myorigin = /etc/mailname
mydestination = _MAIL_SERVER_FQDN_, localhost._DEFAULT_MAIL_DOMAIN_, localhost
relayhost =
inet_interfaces = all
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
 
# Recipient delimiter : + is often refused, _ is more accepted
recipient_delimiter = _
 
# Strict address format in addresses
strict_rfc821_envelopes = yes
 
# Maximum postmaster notifications
notify_classes = bounce, 2bounce, delay, policy, protocol, resource, software
 
# Mail maximum size in Bytes
message_size_limit = 67108864
mailbox_size_limit = 0
 
 
################################################################################
# SSL/TLS
 
# TLS parameters
smtpd_tls_cert_file=/etc/ssl/certs/<changeme>
smtpd_tls_key_file=/etc/ssl/private/<changeme>
smtpd_use_tls=yes
smtpd_tls_auth_only = yes
 
 
################################################################################
# Sender restrictions
 
# Only registered users can send emails
smtpd_sender_login_maps = proxy:mysql:/etc/postfix/sql/mysql_virtual_sasl-sender-check.cf
smtpd_reject_unlisted_sender = yes
 
# Have a look : http://www.postfix.org/SMTPD_ACCESS_README.html
smtpd_client_restrictions =
smtpd_sender_restrictions = permit_sasl_authenticated
smtpd_recipient_restrictions =  permit_mynetworks
                                permit_sasl_authenticated
                                reject_unverified_recipient
                                reject_non_fqdn_recipient
##                                reject_non_fqdn_sender
                                reject_non_fqdn_helo_hostname
                                reject_invalid_helo_hostname
##                                reject_unknown_sender_domain
                                reject_unknown_recipient_domain
                                reject_unlisted_recipient
                                reject_unlisted_sender
                                reject_unauth_destination
                                reject_unlisted_sender
                                reject_unauth_destination
                                reject_rbl_client bl.spamcop.net
                                reject_rbl_client zen.spamhaus.org
                                permit
smtpd_data_restrictions = reject_unauth_pipelining
                          reject_multi_recipient_bounce
                          permit
 
# hide the sender IP
header_checks = regexp:/etc/postfix/postfix_header-checks.cf
 
################################################################################
# SASL Auth
smtpd_sasl_auth_enable = yes
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_security_options = noanonymous
smtpd_sasl_local_domain =
smtpd_sasl_authenticated_header = yes
broken_sasl_auth_clients = yes
 
 
################################################################################
# mail delivery
#mailbox_transport = dovecot
#mailbox_command = procmail -a "$EXTENSION"
#mailbox_command = /usr/lib/dovecot/deliver -n -m "$EXTENSION"
#mailbox_size_limit = 0
#dovecot_destination_recipient_limit = 1
virtual_transport = lmtp:unix:private/dovecot-lmtp
 
################################################
# Virtual mailboxes
 
virtual_mailbox_domains = proxy:mysql:/etc/postfix/sql/mysql_virtual_domains_maps.cf
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
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
 
 
################################################################################
# misc config
 
# No local user, no need to notify them.
biff = no
 
# Appending .domain is the MUA's job.
append_dot_mydomain = no
 
# messages d'erreur (bounces) en français :
bounce_template_file = /etc/postfix/bounce.cf.fr
 
# warn the user of non distributed mail after 24h of tries (but keep trying during 5 days)
delay_warning_time = 24h
 
# No need for documentation
readme_directory = no
 
# HELO Stuff
smtpd_banner = $myhostname ESMTP $mail_name
smtpd_helo_required = yes
 
 
################################################
# Proxy
 
# Proxy service feeding (important because of the chrooted environment in Debian)
proxy_read_maps = $local_recipient_maps
                  $mydestination
                  $mynetworks
                  $virtual_alias_maps
                  $virtual_alias_domains
                  $virtual_mailbox_maps
                  $virtual_mailbox_domains
                  $relay_recipient_maps
                  $relay_domains
                  $canonical_maps
                  $sender_canonical_maps
                  $recipient_canonical_maps
                  $relocated_maps
                  $transport_maps
                  $smtpd_sender_login_maps
 
proxy_write_maps = $smtp_sasl_auth_cache_name
                   $smtp_tls_session_cache_database
                   $smtpd_tls_session_cache_database
                   $lmtp_sasl_auth_cache_name
                   $address_verify_map
                   $postscreen_cache_map
 
smtp_sasl_auth_cache_name = proxy:btree:${data_directory}/smtp_sasl_auth_cache_name
smtp_tls_session_cache_database = proxy:btree:${data_directory}/smtp_tls_session_cache_database
smtpd_tls_session_cache_database = proxy:btree:${data_directory}/smtpd_tls_session_cache_database
lmtp_sasl_auth_cache_name = proxy:btree:${data_directory}/lmtp_sasl_auth_cache_name
address_verify_map = proxy:btree:${data_directory}/address_verify_map
postscreen_cache_map = proxy:btree:${data_directory}/postscreen_cache_map
sed -i "s/_DEFAULT_MAIL_DOMAIN_/${DEFAULT_MAIL_DOMAIN}/g" /etc/postfix/main.cf
sed -i "s/_MAIL_SERVER_HOSTNAME_/${MAIL_SERVER_HOSTNAME}/g" /etc/postfix/main.cf
sed -i "s/_MAIL_SERVER_FQDN_/${MAIL_SERVER_FQDN}/g" /etc/postfix/main.cf

master.cf file

vi /etc/postfix/master.cf

add :

submission inet n - n - - smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_sasl_type=dovecot
  -o smtpd_sasl_path=private/auth
  -o smtpd_sasl_security_options=noanonymous
  -o smtpd_sasl_local_domain=$myhostname
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
  -o smtpd_sender_restrictions=reject_sender_login_mismatch
  -o smtpd_recipient_restrictions=reject_non_fqdn_recipient,reject_unknown_recipient_domain,permit_sasl_authenticated,reject

dovecot configuration

mysql / postfixadmin

cd /etc/dovecot
mkdir origin
cp -aR ./* origin
 
echo "
# postfixadmin database queries
driver = mysql
connect = host=localhost dbname=$PFARODBNAME user=$PFARODBUSER password=$PFARODBPW
default_pass_scheme = MD5-CRYPT
user_query = SELECT concat('/data/vmail/', maildir) AS home, 500 AS uid, 500 AS gid FROM mailbox WHERE username = '%u'
password_query = SELECT username as user, password, concat('/data/vmail/', maildir) as userdb_home, 500 as userdb_uid, 500 as userdb_gid, CONCAT('dirsize:storage=', ROUND(quota / 1024) ) AS quota FROM mailbox WHERE username = '%u' AND active=1
" >> /etc/dovecot/dovecot-sql.conf.ext
 
sed -i "s/#disable_plaintext_auth = yes/disable_plaintext_auth = yes/g" /etc/dovecot/conf.d/10-auth.conf
sed -i "s/\!include auth-system.conf.ext/#\!include auth-system.conf.ext/g" /etc/dovecot/conf.d/10-auth.conf
sed -i "s/#\!include auth-sql.conf.ext/\!include auth-sql.conf.ext/g" /etc/dovecot/conf.d/10-auth.conf
sed -i "s/mail_location =.*$/mail_location = maildir:%h/g" /etc/dovecot/conf.d/10-mail.conf
sed -i "s/#mail_privileged_group =/mail_privileged_group = mail/g" /etc/dovecot/conf.d/10-mail.conf
#sed -i "s/#port = 993/port = 993/g" /etc/dovecot/conf.d/10-master.conf
sed -i "s/unix_listener lmtp {/unix_listener \/var\/spool\/postfix\/private\/dovecot-lmtp {\n    user = postfix\n    group = postfix\n    mode = 0600/g" /etc/dovecot/conf.d/10-master.conf
sed -i "s/unix_listener auth-userdb {/unix_listener auth-userdb {\n    user = vmail/g" /etc/dovecot/conf.d/10-master.conf
sed -i "s/# Postfix smtp-auth/# Postfix smtp-auth\n  unix_listener \/var\/spool\/postfix\/private\/auth {\n    mode = 0666\n  }/g" /etc/dovecot/conf.d/10-master.conf
sed -i "s/service auth-worker {/service auth-worker {\n  user = \$default_internal_user/g" /etc/dovecot/conf.d/10-master.conf
sed -i "s/ssl = no/ssl=required/g" /etc/dovecot/conf.d/10-ssl.conf
sed -i 's/#ssl_protocols = !SSLv2/ssl_protocols = !SSLv2/g' /etc/dovecot/conf.d/10-ssl.conf
sed -i 's/#ssl_cipher_list = ALL:!LOW:!SSLv2:!EXP:!aNULL/ssl_cipher_list = ALL:!LOW:!SSLv2:!EXP:!aNULL/g' /etc/dovecot/conf.d/10-ssl.conf
#sed -i "s/#postmaster_address =/postmaster_address = postmaster@<changeme>/g" /etc/dovecot/conf.d/15-lda.conf
#sed -i "s/#recipient_delimiter = +/#recipient_delimiter = +\nrecipient_delimiter = _/g" /etc/dovecot/conf.d/15-lda.conf
sed -i "s/protocol lmtp {/protocol lmtp {\n  postmaster_address = postmaster@<changeme>\n  mail_plugins = \$mail_plugins quota sieve /g" /etc/dovecot/conf.d/20-lmtp.conf
sed -i "s/#recipient_delimiter = +/#recipient_delimiter = +\n  recipient_delimiter = _/g" /etc/dovecot/conf.d/90-sieve.conf
 
mkdir -p /data/vmail
chmod 770 /data/vmail
groupadd --gid 500 vmail
useradd --system --uid 500 --gid 500 --home-dir /data/vmail --shell /sbin/nologin --comment "Virtual mailbox" vmail
chown vmail:vmail /data/vmail

At the end...

Do by hand :

# (re)start services

tail -f /var/log/syslog &
service dovecot stop
service dovecot start
service postfix start
fg

Add www-data alias

echo "www-data: root" >> /etc/aliases
echo "root: admin_<MAIL_SERVER_FQDN>@<DEFAULT_MAIL_DOMAIN>" >> /etc/aliases
newaliases

Final verification (all the chain)

# stop mail services
for SERVICE_ in postfix dovecot ; do service $SERVICE_ stop; done
# start mail services
for SERVICE_ in dovecot postfix; do service $SERVICE_ start; done

Not included for the moment :