1. Home
  2. Linux
  3. General
  4. Install and configure Dovecot and Postfix

Install and configure Dovecot and Postfix

Install and configure Postfix and Dovecot
Install and configure Postfix and Dovecot

We are going to show you how to install Dovecot and Postfix which are the two main components of our mail system. Postfix is a mail transfer agent (MTA), a service used to send and receive emails. Dovecot is an IMAP/POP3 server, and in our setup, it will also handle local delivery and user authentication.
I have talked about the Postfix and  Dovecot earlier, the details of which you can read in these articles:

  1. How to Install Sentora on Debian 8
  2. Setting up and Installing Postfix on Ubuntu 14.04

Install Dovecot and Postfix

Dovecot packages in the Ubuntu default repositories are outdated, so in order to take advantage of the imap_sieve module, we will install Dovecot from the Dovecot community repository:

wget -O- https://repo.dovecot.org/DOVECOT-REPO-GPG | sudo apt-key add -
echo "deb https://repo.dovecot.org/ce-2.3-latest/ubuntu/$(lsb_release -cs) $(lsb_release -cs) main" | sudo tee -a /etc/apt/sources.list.d/dovecot.list
sudo apt update
debconf-set-selections <<< "postfix postfix/mailname string $(hostname -f)"
debconf-set-selections <<< "postfix postfix/main_mailer_type string 'Internet Site'"
sudo apt install postfix postfix-mysql dovecot-imapd dovecot-lmtpd dovecot-pop3d dovecot-mysql

Postfix Configuration

We will setup Postfix with virtual mailboxes and multiple domains, so first we’ll create the configuration files, which will allow postfix to access the database that we created in the first part of this series:

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

 

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

 

/etc/postfix/sql/mysql_virtual_alias_domain_maps.cf
user = postfixadmin
password = P4ssvv0rD
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'

 

/etc/postfix/sql/mysql_virtual_alias_domain_catchall_maps.cf
user = postfixadmin
password = P4ssvv0rD
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'

 

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

 

/etc/postfix/sql/mysql_virtual_alias_domain_mailbox_maps.cf
user = postfixadmin
password = P4ssvv0rD
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'

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 SQLite 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 postconf command displays the actual values of configuration parameters, changes configuration parameter values, or displays other configuration information about the Postfix mail system.
The local delivery will be handled by the Dovecot’s LMTP. The local delivery agent will take mail from our MTA (Postfix) and deliver it to a user’s mailbox.

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/mail.linuxize.com/fullchain.pem'
sudo postconf -e 'smtpd_tls_key_file = /etc/letsencrypt/live/mail.linuxize.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 also need to edit the Postfix master process configuration file master.cf and enable the submission port (587) and smtps port (465), then uncomment and edit the following lines:

/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

Restart the postfix service for changes to take effect.

sudo systemctl postfix restart

By now, you should have successfully configured the Postfix service.

Configure Dovecot

Open the following files and edit the lines highlighted in yellow:

/etc/dovecot/dovecot-sql.conf.ext
driver = mysql
connect = host=127.0.0.1 dbname=postfixadmin user=postfixadmin password=P4ssvv0rD
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'

Make sure you use the correct MySQL credentials (dbname, user, and password).

/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 = mail
...
mail_plugins = quota
...
Copy
/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
...
Copy
/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
  }
}
...
/etc/dovecot/conf.d/10-ssl.conf
...
ssl = yes
...
ssl_cert = </etc/letsencrypt/live/mail.linuxize.com/fullchain.pem
ssl_key = </etc/letsencrypt/live/mail.linuxize.com/privkey.pem
ssl_dh = </etc/ssl/certs/dhparam.pem
...
ssl_cipher_list = EECDH+AES:EDH+AES+aRSA
...
ssl_prefer_server_ciphers = yes
...

Make sure you use the correct path to the SSL certificate files.
If you have followed this series from the beginning, you should already have the fullchain.pem, privkey.pem, and dhparam.pem files created on your server. For more information about how to create a free Let’s encrypt SSL certificate and Diffie–Hellman key, check this tutorial.
Thanks to Nevyn for noticing the problem and providing a solution.

/etc/dovecot/conf.d/20-imap.conf
...
protocol imap {
  ...
  mail_plugins = $mail_plugins imap_quota
  ...
}
...
/etc/dovecot/conf.d/20-lmtp.conf
...
protocol imap {
  postmaster_address = [email protected]
  mail_plugins = $mail_plugins
}
...
Copy
/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 already enabled quota support in PostfixAdmin, which means the quota information will be stored in the PostfixAdmin database. We also need to configure Dovecot to connect to the database to handle quota limits and to run a script that sends mail to the user when the user’s quota exceeds a specified limit.

/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
}
Copy
/etc/dovecot/dovecot-dict-sql.conf.ext
...
connect = host=127.0.0.1 dbname=postfixadmin user=postfixadmin password=P4ssvv0rD
...
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
#   }
# }
...

Make sure you use the correct MySQL credentials (dbname, user, and password).
Create the following shell script:

/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: [email protected]
Subject: Quota warning
Your mailbox is now $PERCENT% full.
EOF

and make it executable:

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

Finally, restart the dovecot service for the changes to take effect.

systemctl dovecot restart

By now, you should have a fully functional mail system. In the next part of this series, we will show you how to install and integrate Rspamd.
Check out Our Best VPS Hosting and WordPress hosting for scaling your cloud-based applications and processes.
One more thing..
Share this tutorial with your hosting administrators
Thanks

Updated on December 23, 2018

Was this article helpful?

Related Articles

Leave a Comment

[apsl-login-lite login_text='Please login with a social account']