I hope you haven’t lost your mind yet. If you are unsure how Postfix and Dovecot work together take a moment and go back to the big picture page.
In a previous chapter we made sure that Postfix knows which emails it is allowed to receive. Now what to do with the email? It has to be saved to disk into the mailbox of the mail user who is eagerly waiting for it. You could let Postfix handle that using its built-in mail delivery agent (MDA) called “virtual“. However compared to the capabilities that Dovecot provides like server-based sieve rules or quotas the Postfix delivery agent is pretty basic. We are using Dovecot anyway to provide the IMAP (and optionally POP3) service. So let’s use its delivery agent.
How can we make Postfix hand over the email to Dovecot? There are generally two ways to establish that link.
- Using the dovecot-lda (local delivery agent) process. It can process one email at a time. And it starts up a new process for every email. This was for long the default way. But as you can imagine that it does not scale well.
- The better option is to use LMTP (local mail transport protocol) that was conceived for this purpose. It can handle multiple recipients at the same time and has a permanently running process which provides a better performance than using the LDA. In short, LMTP is a variant of SMTP with fewer features. It is meant for email communication between internal services that trust each other.
You guessed it already – we will go for the second option. You installed the dovecot-lmtpd package earlier. So let’s configure it.
Tell Dovecot where to listen for LMTP connections from Postfix
Edit Dovecot’s configuration file that deals with the LMTP daemon – you can find it at /etc/dovecot/conf.d/10-master.conf
. Look for the “service lmtp” section and edit it so that it looks like:
service lmtp { unix_listener /var/spool/postfix/private/dovecot-lmtp { group = postfix mode = 0600 user = postfix } }
This makes Dovecot’s lmtp daemon create a UNIX socket at /var/spool/postfix/private/dovecot-lmtp. Just like in the section dealing with setting up Dovecot we make it put a socket into the /var/spool/postfix chroot directory because Postfix is restricted to that directory and cannot access anything outside of it. So from Postfix’s point of view the socket is located at “/private/dovecot-lmtp”.
Restart Dovecot…
systemctl restart dovecot
Check if dovecot accepted that change:
systemctl status dovecot
The output should contain “Active: active (running)”.
Tell Postfix to deliver emails to Dovecot using LMTP
This is even easier. The “virtual_transport” in Postfix defines the service to use for delivering emails to the local system. Dovecot has created a socket file and is ready to listen to incoming LMTP connections. We just need to tell Postfix to send emails there:
postconf virtual_transport=lmtp:unix:private/dovecot-lmtp
The syntax looks crazy, but it’s actually simple. You just told Postfix to use the LMTP protocol. And that we want to use a UNIX socket on the same system (instead of a TCP connection). And the socket file is located at /var/spool/postfix/private/dovecot-lmtp
.
(You will find further information on these steps in the Dovecot configuration on Postfix integration.)
Enable server-side mail rules
One of my favorite features of Dovecot are automatic rules for incoming email that are processed on the server. You can sort away your mailing list emails into special folders. You can reject certain senders. Or you can set up vacation auto-responders. No need to have a mail client running – it all happens automatically on the server even when your mail users are not connected.
The open-source standard (RFC 5228) for such rules is called Sieve. Basically, Sieve is a way to manage server-side email rules. A rule consists of conditions and actions. For example if the sender address matches “steve@example.org” you could tell Dovecot to move such emails to your “steve” folder automatically. These rules are stored on the Dovecot server and executed automatically. Whether you connect from your smartphone your laptop or use the webmail access – the rules always work and require no configuration on the client side.
As we use LMTP that’s where we need to tell the lmtp service that we want to use Dovecot’s “sieve” plugin. Edit the file /etc/dovecot/conf.d/20-lmtp.conf
and within the “protocol lmtp” section change the “mail_plugins” line to:
mail_plugins = $mail_plugins sieve
Restart Dovecot and you are done:
systemctl restart dovecot
Not sure which page to comment on about this, but I had a heck of a time setting up for multiple domain names. As a church server, we host several domains. This is what I had to do to make it work.
First, create a separate certificate for all your mail domains. One for all doesn’t seem to work right for me.
certbot certonly –standalone -d mail.example1.com –pre-hook “service
apache2 stop” –post-hook “service apache2 start”
certbot certonly –standalone -d mail.example2.net –pre-hook “service
apache2 stop” –post-hook “service apache2 start”
This keeps it from messing with the Apache config files.
Then you need to create a file called ssl_mail:
nano /etc/postfix/ssl_map
In that file, you need it look like this:
mail.example1.com /etc/letsencrypt/live/mail.example1.com/privkey.pem
/etc/letsencrypt/live/mail.example1.com/fullchain.pem
mail.example2.net /etc/letsencrypt/live/mail.example2.net/privkey.pem
/etc/letsencrypt/live/mail.example2.net/fullchain.pem
Save the file, then run the following command:
postmap -F hash:/etc/postfix/ssl_map
This file needs to be hashed for Postfix to read it.
Then you need to add the following to your main.cf file:
nano /etc/postfix/main.cf
This file needs the following changes:
Take out:
#smtpd_tls_cert_file=/etc/letsencrypt/live/webmail.example.com/fullchain.pem
#smtpd_tls_key_file=/etc/letsencrypt/live/webmail.example.com/privkey.pem
Add the following:
smtpd_tls_chain_files =
/etc/letsencrypt/live/webmail.example.com/privkey.pem
/etc/letsencrypt/live/webmail.example.com/fullchain.pem
This line makes it so the server uses the user to determine the domain.
smtp_sender_dependent_authentication = yes
This line tells Postfix to look for the domain certificates you created in the file you created:
tls_server_sni_maps = hash:/etc/postfix/ssl_map
In /etc/dovecot/conf.d/10-ssl.conf you need to change it to include:
local_name mail.example1.com {
ssl_cert = </etc/letsencrypt/live/mail.example1.com/fullchain.pem
ssl_key = </etc/letsencrypt/live/mail.example1.com/privkey.pem
}
local_name mail.example2.net {
ssl_cert = </etc/letsencrypt/live/mail.example2.net/fullchain.pem
ssl_key = </etc/letsencrypt/live/mail.example2.net/privkey.pem
}
Save the file. Remember to leave the original domain certs in the file as created by this guide.
Then run the following commands:
systemctl restart postfix
systemctl restart dovecot
If everything is correct, you should be able to send and receive without certificate errors from the various domains on your mailserver.
Thanks!
Do not use any of the above. It does not work like it looked like it did.
Sorry. Back to the drawing board.