Postfix and Dovecot Communication

 Published on 16 Feb 2025 .  Filed in Projects .  641 words

In a previous chapters 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 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.

  1. 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.
  2. 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.

We are going for the second option. You installed the dovecot-lmtpd package earlier. So let’s configure it.

Configure Dovecot to Listen for LMTP Connections from Postfix

Edit Dovecot’s configuration file /etc/dovecot/conf.d/10-master.conf that deals with the LMTP daemon. 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:

  sudo systemctl restart dovecot

Configure Postfix to Deliver Mails to Dovecot using LMTP

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:

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

We just told Postfix to use the LMTP protocol. And 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.

Enable server-side mail rules   ARCHIVE

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 user2@example1.com you could tell Dovecot to move such emails to your user2 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