User Tools

Site Tools


mail_server

Mail Server: Postfix

1.0 --- DNS Settings

You need to set up the following DNS records for your mail system to work:

  • A record, to point your system’s FQDN (hostname) to your mail server IPv4 address.
rpi.tiger-park.com    3600 IN A    118.179.43.233
  • MX record, to specify which mail server is responsible for accepting email messages on behalf of a recipient’s domain. In our case we want all emails sent to @tiger-park.com email addresses to be accepted by the rpi.tiger-park.com mail server.
tiger-park.com    3600 IN MX  0  rpi.tiger-park.com
  • SPF record, which is used to verify which mail servers are approved to send email on behalf of a given domain. In the example below we are approving the domain mail servers (mx) and if the SPF check fails, the result will be a soft failure (~all):
tiger-park.com    3600 IN TXT    "v=spf1 mx ~all"

Reverse DNS (PTR) is an IP address to domain name mapping, the exact opposite of DNS which maps domain names to IP addresses. Most email servers will perform a reverse DNS lookup on the IP address that is attempting to connect to them and may not accept emails from the server if the PTR record is not set. In most cases PTR entries can be set via your hosting provider web interface or by contacting the support team and ask them to setup a correct PTR record for you. You can use the dig command to find out the reverse DNS of a given IP address:

dig -x 118.179.43.233

Output something like this:

233.43.179.118.in-addr.arpa domain name pointer rpi.tiger-park.com

1.1 --- Create a system user

Since we are configuring a mail server with virtual users we need one system user which will be the owner of all mailboxes and will be used by the virtual users to access their email messages on the server.

The following command will create a new group and user named vmail and set the user’s home directory to /var/mail/vmail:

sudo groupadd -g 5000 vmail
sudo useradd -u 5000 -g vmail -s /usr/sbin/nologin -d /var/mail/vmail -m vmail

All virtual mailboxes will be stored in the /var/mail/vmail directory

1.2 --- Install Apache2 & PHP-FPM

Postfix Admin is a PHP based application. To be able to access the PostfixAdmin web interface we need to install a Web server and PHP. Run the following command to install Apache2, PHP-FPM and all required PHP modules:

sudo apt install apache2 apache2-utils mariadb-server php7.2-fpm php7.2-cli php7.2-imap php7.2-json php7.2-mysql php7.2-opcache php7.2-mbstring php7.2-readline

1.3 --- Install Postfix Admin

Download the Postfix Admin archive using the following wget command:

cd /tmp
wget https://sourceforge.net/projects/postfixadmin/files/postfixadmin/postfixadmin-3.2/postfixadmin-3.2.tar.gz/download
mv download postfixadmin-3.2.tar.gz
tar xzf postfixadmin-*.tar.gz
rm postfixadmin-*.tar.gz

Move the Postfix Admin source files the /var/www directory and create templates_c directory (smarty cache):

sudo mv postfixadmin-*/ /var/www/html/postfixadmin
mkdir /var/www/html/postfixadmin/templates_c

Both Apache2 and PHP-FPM are running under user www-data so we need to change the ownership of the /var/www/html/postfixadmin to that user:

sudo chown -R www-data: /var/www/html/postfixadmin

1.4 --- Setup Database in MariaDB

Postfix Admin will use a MariaDB database to store information about users, domains and the application configuration. Login to the MariaDB shell:

sudo mysql -u root -p

Create a new MariaDB user and database using the following commands:

CREATE DATABASE postfixadmin;
GRANT ALL ON postfixadmin.* TO 'postfixadmin'@'localhost' IDENTIFIED BY 'Password';
FLUSH PRIVILEGES;
exit

1.5 --- Configuring Postfix Admin

Instead of editing the default Postfix Admin configuration we will create a new file named config.local.php which will overwrite the default application settings. Open the file with your text file:

sudo nano /var/www/postfixadmin/config.local.php

Paste the following php code:

<?php
$CONF['configured'] = true;

$CONF['database_type'] = 'mysqli';
$CONF['database_host'] = 'localhost';
$CONF['database_user'] = 'postfixadmin';
$CONF['database_password'] = 'Password';
$CONF['database_name'] = 'postfixadmin';

$CONF['default_aliases'] = array (
  'abuse'      => 'abuse@tiger-park.com',
  'hostmaster' => 'hostmaster@tiger-park.com',
  'postmaster' => 'postmaster@tiger-park.com',
  'webmaster'  => 'webmaster@tiger-park.com'
);

$CONF['fetchmail'] = 'NO';
$CONF['show_footer_text'] = 'NO';

$CONF['quota'] = 'YES';
$CONF['domain_quota'] = 'YES';
$CONF['quota_multiplier'] = '1024000';
$CONF['used_quotas'] = 'YES';
$CONF['new_quota_table'] = 'YES';

$CONF['aliases'] = '0';
$CONF['mailboxes'] = '0';
$CONF['maxquota'] = '0';
$CONF['domain_quota_default'] = '0';
?>

Next point your web browser towards https://rpi.tiger-park.com/postfixadmin/public/setup.php and follow the instructions.

2.0 --- Install Postfix & Dovecot

sudo apt install postfix postfix-mysql dovecot-imapd dovecot-lmtpd dovecot-pop3d dovecot-mysql sasl2-bin

Make sure that sasl run at the startup by editing its configuration file:

sudo nano /etc/default/saslauthd
# Should saslauthd run automatically on startup? (default: no)
START=yes
[...]
sudo systemctl restart saslauthd
sudo systemctl enable saslauthd

We will setup Postfix to use virtual mailboxes and domains. Start by creating the sql configuration files which will instruct postfix how to access the MariaDB database:

sudo mkdir -p /etc/postfix/sql

Open your text editor and create the following files:

sudo nano /etc/postfix/sql/mysql_virtual_domains_maps.cf
user = postfixadmin
password = Password
hosts = 127.0.0.1
dbname = postfixadmin
query = SELECT domain FROM domain WHERE domain='%s' AND active = '1'

Then:

sudo nano /etc/postfix/sql/mysql_virtual_alias_maps.cf
user = postfixadmin
password = Password
hosts = 127.0.0.1
dbname = postfixadmin
query = SELECT goto FROM alias WHERE address='%s' AND active = '1'

Then:

sudo nano /etc/postfix/sql/mysql_virtual_alias_domain_maps.cf
user = postfixadmin
password = Password
hosts = 127.0.0.1
dbname = postfixadmin
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'

Then:

sudo nano /etc/postfix/sql/mysql_virtual_alias_domain_catchall_maps.cf
user = postfixadmin
password = Password
hosts = 127.0.0.1
dbname = postfixadmin
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'

Then:

sudo nano /etc/postfix/sql/mysql_virtual_mailbox_maps.cf
user = postfixadmin
password = Password
hosts = 127.0.0.1
dbname = postfixadmin
query = SELECT maildir FROM mailbox WHERE username='%s' AND active = '1'

Then:

sudo nano /etc/postfix/sql/mysql_virtual_alias_domain_mailbox_maps.cf
user = postfixadmin
password = Password
hosts = 127.0.0.1
dbname = postfixadmin
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'

2.1 --- Configuring Postfix

Once the SQL configuration files are created, update the main postfix configuration file to include information about the virtual domains, users, and aliases which are stored in the MariaDB database:

sudo postconf -e "virtual_mailbox_domains = mysql:/etc/postfix/sql/mysql_virtual_domains_maps.cf"
sudo postconf -e "virtual_alias_maps = mysql:/etc/postfix/sql/mysql_virtual_alias_maps.cf, mysql:/etc/postfix/sql/mysql_virtual_alias_domain_maps.cf, mysql:/etc/postfix/sql/mysql_virtual_alias_domain_catchall_maps.cf"
sudo postconf -e "virtual_mailbox_maps = mysql:/etc/postfix/sql/mysql_virtual_mailbox_maps.cf, mysql:/etc/postfix/sql/mysql_virtual_alias_domain_mailbox_maps.cf"

The local delivery agent will deliver the incoming emails to the users’ mailboxes. Run the following command to set Dovecot’s LMTP service as a default mail delivery transport:

sudo postconf -e "virtual_transport = lmtp:unix:private/dovecot-lmtp"

Set the TL parameters using the previously generated Let’s encrypt SSL certificate:

sudo postconf -e 'smtp_tls_security_level = may'
sudo postconf -e 'smtpd_tls_security_level = may'
sudo postconf -e 'smtp_tls_note_starttls_offer = yes'
sudo postconf -e 'smtpd_tls_loglevel = 1'
sudo postconf -e 'smtpd_tls_received_header = yes'
sudo postconf -e 'smtpd_tls_cert_file = /etc/letsencrypt/live/rpi.tiger-park.com/fullchain.pem'
sudo postconf -e 'smtpd_tls_key_file = /etc/letsencrypt/live/rpi.tiger-park.com/privkey.pem'

Configure the authenticated SMTP settings and hand off authentication to Dovecot:

sudo postconf -e 'smtpd_sasl_type = dovecot'
sudo postconf -e 'smtpd_sasl_path = private/auth'
sudo postconf -e 'smtpd_sasl_local_domain ='
sudo postconf -e 'smtpd_sasl_security_options = noanonymous'
sudo postconf -e 'broken_sasl_auth_clients = yes'
sudo postconf -e 'smtpd_sasl_auth_enable = yes'
sudo postconf -e 'smtpd_recipient_restrictions = permit_sasl_authenticated,permit_mynetworks,reject_unauth_destination'

We’ll also need to edit the Postfix master configuration file master.cf and enable the submission port (587) and smtps port (465):

sudo nano /etc/postfix/master.cf
[...]
submission inet n       -       y       -       -       smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
#  -o smtpd_reject_unlisted_recipient=no
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
#  -o smtpd_helo_restrictions=$mua_helo_restrictions
#  -o smtpd_sender_restrictions=$mua_sender_restrictions
#  -o smtpd_recipient_restrictions=
#  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING
smtps     inet  n       -       y       -       -       smtpd
  -o syslog_name=postfix/smtps
  -o smtpd_tls_wrappermode=yes
  -o smtpd_sasl_auth_enable=yes
#  -o smtpd_reject_unlisted_recipient=no
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
#  -o smtpd_helo_restrictions=$mua_helo_restrictions
#  -o smtpd_sender_restrictions=$mua_sender_restrictions
#  -o smtpd_recipient_restrictions=
#  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING
[...]

Now you can run the postconf -n command to check some errors:

postconf -n

If there are no errors you can restart the postfix service for changes to take effect:

sudo systemctl restart postfix

2.2 --- Configuring Dovecot

Start by configuring the dovecot-sql.conf.ext file that instructs Dovecot how to access the database and how to find the information about email accounts:

sudo nano /etc/dovecot/dovecot-sql.conf.ext
driver = mysql
connect = host=127.0.0.1 dbname=postfixadmin user=postfixadmin password=Password
default_pass_scheme = MD5-CRYPT
iterate_query = SELECT username AS user FROM mailbox
user_query = SELECT CONCAT('/var/mail/vmail/',maildir) AS home, \
  CONCAT('maildir:/var/mail/vmail/',maildir) AS mail, \
  5000 AS uid, 5000 AS gid, CONCAT('*:bytes=',quota) AS quota_rule \
  FROM mailbox WHERE username = '%u' AND active = 1
password_query = SELECT username AS user,password FROM mailbox \
  WHERE username = '%u' AND active='1'

Next, edit the conf.d/10-mail.conf file and edit the following variables:

sudo nano /etc/dovecot/conf.d/10-mail.conf
[...]
mail_location = maildir:/var/mail/vmail/%d/%n
[...]
mail_uid = vmail
mail_gid = vmail
[...]
first_valid_uid = 5000
last_valid_uid = 5000
[...]
mail_privileged_group = vmail
[...]
mail_plugins = quota
[...]

To make the authentication work, open the conf.d/10-auth.conf, edit the following lines and include the auth-sql.conf.ext file:

sudo nano /etc/dovecot/conf.d/10-auth.conf
[...]
disable_plaintext_auth = yes
[...]
auth_mechanisms = plain login
[...]
#!include auth-system.conf.ext
!include auth-sql.conf.ext
[...]

Open the conf.d/10-master.conf file, and modify it as follows:

sudo nano /etc/dovecot/conf.d/10-master.conf
[...]
service lmtp {
  unix_listener /var/spool/postfix/private/dovecot-lmtp {
    mode = 0600
    user = postfix
    group = postfix
  }
[...]
}
[...]
service auth {
  [...]
  unix_listener auth-userdb {
    mode = 0600
    user = vmail
    group = vmail
  }
  [...]
  unix_listener /var/spool/postfix/private/auth {
    mode = 0666
    user = postfix
    group = postfix
  }
  [...]
}
[...]
service auth-worker {
  user = vmail
}
[...]
service dict {
  unix_listener dict {
    mode = 0660
    user = vmail
    group = vmail
  }
}
[...]

Open the conf.d/10-ssl.conf and enable SSL/TLS:

sudo nano /etc/dovecot/conf.d/10-ssl.conf
[...]
ssl = yes
[...]
ssl_cert = </etc/letsencrypt/live/rpi.tiger-park.com/fullchain.pem
ssl_key = </etc/letsencrypt/live/rpi.tiger-park.com/privkey.pem
ssl_dh = </etc/ssl/certs/dhparam.pem
[...]
ssl_cipher_list = EECDH+AES:EDH+AES+aRSA
[...]
ssl_prefer_server_ciphers = yes
[...]

Open the conf.d/20-imap.conf file and activate the imap_quota plugin:

sudo nano /etc/dovecot/conf.d/20-imap.conf
[...]
protocol imap {
  [...]
  mail_plugins = $mail_plugins imap_quota
  [...]
}
[...]

Open the conf.d/20-lmtp.conf file and edit it as follows:

sudo nano /etc/dovecot/conf.d/20-lmtp.conf
[...]
protocol lmtp {
  postmaster_address = postmaster@tiger-park.com
  mail_plugins = $mail_plugins
}
[...]

Define the default Mailboxes in the conf.d/20-lmtp.conf file:

sudo nano /etc/dovecot/conf.d/15-mailboxes.conf
[...]
mailbox Drafts {
  special_use = \Drafts
}
mailbox Spam {
  special_use = \Junk
  auto = subscribe
}
mailbox Junk {
  special_use = \Junk
}
[...]

There are two different types of quota sizes, one is set for the entire domain and the other per user mailbox. In the previous part of this series we have already enabled the quota support in PostfixAdmin which means the quota information will be stored in the PostfixAdmin database.

Now we need to configure Dovecot to connect to the database, to handle quota limits and to run a script that sends a mail to the user when user’s quota exceeds a specified limit. To do so open the conf.d/90-quota.conf file and modify it as follows:

sudo nano /etc/dovecot/conf.d/90-quota.conf
plugin {
  quota = dict:User quota::proxy::sqlquota
  quota_rule = *:storage=5GB
  quota_rule2 = Trash:storage=+100M
  quota_grace = 10%%
  quota_exceeded_message = Quota exceeded, please contact your system administrator.
  quota_warning = storage=100%% quota-warning 100 %u
  quota_warning2 = storage=95%% quota-warning 95 %u
  quota_warning3 = storage=90%% quota-warning 90 %u
  quota_warning4 = storage=85%% quota-warning 85 %u
}

service quota-warning {
  executable = script /usr/local/bin/quota-warning.sh
  user = vmail

  unix_listener quota-warning {
    group = vmail
  	mode = 0660
  	user = vmail
  }
}

dict {
  sqlquota = mysql:/etc/dovecot/dovecot-dict-sql.conf.ext
}

We also need to tell dovecot how to access the quota SQL dictionary. Open the dovecot-dict-sql.conf.ext file and edit the following lines:

sudo nano /etc/dovecot/dovecot-dict-sql.conf.ext
[...]
connect = host=127.0.0.1 dbname=postfixadmin user=postfixadmin password=Password
[...]
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
}
[...]
# map {
#   pattern = shared/expire/$user/$mailbox
#   table = expires
#   value_field = expire_stamp
#
#   fields {
#     username = $user
#     mailbox = $mailbox
#   }
# }
[...]

Create the following shell script which will send an email to the user if its quota exceeds a specified limit:

sudo nano /usr/local/bin/quota-warning.sh
#!/bin/sh
PERCENT=$1
USER=$2
cat << EOF | /usr/lib/dovecot/dovecot-lda -d $USER -o "plugin/quota=dict:User quota::noenforcing:proxy::sqlquota"
From: postmaster@tiger-park.com
Subject: Quota warning

Your mailbox is now $PERCENT% full.
EOF

Make the script executable by running the following command:

sudo chmod +x /usr/local/bin/quota-warning.sh

Finally restart the dovecot service for changes to take effect:

sudo systemctl restart dovecot

By now you should have a fully functional mail system.

3.0 Prerequisites Roundcube Webmail

sudo apt install php-auth php-intl php-mail-mime php-mail-mimedecode php-mcrypt php-net-smtp php-net-idna2 php-net-socket php-pear php-xml php7.2-intl php7.2-mcrypt php7.2-xml php7.2-gd php7.2-gd php-imagick

Create a new MariaDB database and user and grant privileges to that user over the newly created database:

sudo mysql -u root -p
CREATE DATABASE roundcubemail;
GRANT ALL ON roundcubemail.* TO 'roundcubemail'@'localhost' IDENTIFIED BY 'Password';
FLUSH PRIVILEGES;
exit

3.1 --- Download, install Roundcube Webmail

cd /tmp
wget https://github.com/roundcube/roundcubemail/releases/download/1.3.8/roundcubemail-1.3.8.tar.gz
tar xzf roundcubemail-*.tar.gz
rm -rf roundcubemail-*.tar.gz
sudo mv roundcubemail-*/ /var/www/html/roundcubemail
sudo chown -R www-data: /var/www/html/roundcubemail

3.2 --- Configure Roundcube Webmail

Open your browser and navigate to https://rpi.tiger-park.com/roundcubemail/installer. Follow the instructions.

x.x --- References

mail_server.txt · Last modified: 2019/01/27 14:13 by pi