Based on Debian 10 "Buster" environment.

Postfix and Dovecot LMTP

Postfix is one of the most famous MTA (Mail Transfer Agent). It can receive emails from the internet and deliver them to the user directories, but this time I use Dovecot LMTP for the local delivery.

Here I start with a simple integration of Postfix and Dovecot LMTP, then start adding functionalities and configurations gradually.

Postfix

Install

# apt install postfix

The install will ask 2 questions.

  • General type of mail configuration: Internet Site
  • System mail name: mail.example.jp
    The installer will pick up the FQDN for the server as the default for the system mail name.

Open the ports for Postfix

# ufw allow 'Postfix'
# ufw allow 'Postfix Submission'

There is another port for SMTPS(465), which I don't use this time. Encryption is available both SMTP(25) and Submission(587) with STARTTLS.

Virtual Mailbox

This time, mail user will not have any UNIX account. All mails will be stored under /home/vmail, which is the home directory for the user "vmail". For additional security, disable shell login.

# adduser vmail
# usermod -s /usr/sbin/nologin vmail

Configuration for Virtual Users

The Postfix document has an example of the "Non-Postfix mailbox store: separate domains, non-UNIX accounts", which means using virtual accounts with non-Postfix delivery (this case maildrop) for the virtual domains.
Cf. Non-Postfix mailbox store: separate domains, non-UNIX accounts

Modify /etc/postfix/main.cf to send all mails to virtual mailbox.

myhostname = mail.example.jp
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
mydestination = localhost          # Delete domains on the mydestination line
relayhost = 
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
inet_protocols = all

# Virtual Mailbox
virtual_mailbox_domains = mail.example.jp
virtual_transport = lmtp:unix:private/dovecot-lmtp 
virtual_alias_maps = hash:/etc/postfix/virtual

To catch local system mails (e.g. cron job), edit /etc/postfix/virtual.

admin@mail.example.jp info@mail.example.jp
mailer-daemon@mail.example.jp info@mail.example.jp
postmaster@mail.example.jp info@mail.example.jp
root@mail.example.jp info@mail.example.jp

Make the db file using postmap.

# postmap virtual

Reload Postfix to apply changes on main.cf.

# systemctl reload postfix

Dovecot-LMTP

Install

Deovecot-LMTP will take over the mail from Postfix and deliver them to the final destination directory. Postfix can deliver the mail without any external software, but integration with Dovecot enables the Sieve filtering and incoming mail indexing for the Dovecot IMAP server.

# apt install dovecot-lmtpd

Configure

As explained in the Dovecot Wiki, dovecot-lmtpd will be integrated with Postfix via the unix socket.

Tweak the lmtp section in /etc/dovecot/conf.d/10-master.conf to open the socket where Postfix can access.

service lmtp {
  unix_listener /var/spool/postfix/private/dovecot-lmtp {
    mode = 0600
    user = postfix
    group = postfix
  }
}

Enable passwdfile configuration in the bottom of /etc/dovecot/conf.d/10-auth.conf

!include auth-system.conf.ext
#!include auth-sql.conf.ext
#!include auth-ldap.conf.ext
!include auth-passwdfile.conf.ext     # Uncomment this line
#!include auth-checkpassword.conf.ext
#!include auth-vpopmail.conf.ext
#!include auth-static.conf.ext

Set up passdb and userdb, and set defaults for the userdb information in /etc/dovecot/conf.d/auth-passwdfile.conf.ext

passdb {
  driver = passwd-file
  args = scheme=CRYPT username_format=%u /etc/dovecot/users
}

userdb {
  driver = passwd-file
  args = username_format=%u /etc/dovecot/users

  # Default fields that can be overridden by passwd-file
  default_fields = uid=vmail gid=vmail home=/home/vmail/%d/%n mail=sdbox:~/dbox
}
  • passdb and userdb can be the same file. (And that's convenient. Just adding 1 line is the only task to add new user.)
  • Password scheme is CRYPT, which is the default.
  • Username will be mail address style. e.g. info@example.jp
  • userdb has to have uid, gid, home directory, and additionally mail location. In my case, the server is newly built that everyone will use the common configuration.
    • uid and gid is "vmail" that will store all users mail.
    • Virtual users home directory will be /home/vmail/domain/username.
    • Every virtual user will use Dovecot single-dbox style mail storage.

Reload Dovecot to apply the configuration.

# systemctl reload dovecot

Userdb

The userdb (this case /etc/dovecot/users) will keep the list of usernames and their encrypted passwords. The command doveadm will give you the password for copy and paste.
For example, the word "password"

# doveadm pw
Enter new password:       # Nothing displayed when typing
Retype new password:      # Ditto
{CRYPT}$2y$05$n0wj7cVAz5oVxz5G6PmskOSQ6TQ8/5YfEnZPKAMiX8szGX8yvnbxi

Now copy and paste this encrypted password to the userdb (/etc/dovecot/users) file for the user "info@example.jp"

info@example.jp:{CRYPT}$2y-snip-bxi::::::

The trailing colons (::::::) are spaces for uid/gid/home. In addition to these 3, mail_location is set in the conf file. If everything is written inline, then it should look like below.
See passwd-file explanation here for details.

info@example.jp:{CRYPT}$2y-snip-bxi:vmail:vmail::/home/vmail/%d/%n::userdb_mail=sdbox:~/dbox

If you need to change these parameters per user, you can override the default value by writing explicitly.
If you have a bunch of users, it would be better to use a DB to manage them.

Dovecot will check the userdb every time it gets a mail. No reload required just for the userdb update.


Test

Send a test mail to the valid user on this server. The successful logs should come up.
When the first mail has come to the new user, dovecot will make a new directory to store the mail under the specified home directory.

If you have any troubles, dovecot can provide you the detailed debugging logs. Turn on the debug switches in /etc/dovecot/conf.d/10-logging.conf

auth_verbose = yes
auth_debug = yes
auth_debug_passwords = yes
mail_debug = yes