Making Postfix send emails to Dovecot

(Hint: The ISPmail guide now uses LMTP to exchange emails between Postfix and Dovecot. It is a much simpler and also better performing way.)

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 stored to disk for your users. 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 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 it.

There are generally two ways to establish that link between Postfix and Dovecot.

  1. One is 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.
  2. The other 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 that is meant for email communication in a trusted environment.

You guessed it already – we will go for the second option. The software package dovecot-lmtpd should already be installed on your system. So first…

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…

service dovecot restart

(By the way this configuration snippet has been taken from the Dovecot wiki.)

So we can now…

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? 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 for example a TCP connection). And that 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 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 even when your mail users are not connected.

The open-source standard (RFC 5228) for such rules is called Sieve. Simply put 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:

service dovecot restart

34 thoughts on “Making Postfix send emails to Dovecot”

  1. Are you sure it is ‘postconf virtual_transport=lmtp:unix:private/dovecot-lmtp’?

    I have a standard Debian Jessie installation and the /etc/postfix/main.cf contains a ‘mailbox_command = procmail -a “$EXTENSION”‘ line. This overrides the virtual_transport command i thought. So i removed the ‘mailbox_command’ line. But it still won`t work.
    Then i tried to change the ‘virtual_transport’ into ‘mailbox_transport’ and all is working now. Is this how it should be? or am i missing something?

    1. Christoph Haas

      Yes, I’m pretty sure. The settings you are playing with deal with local domains – not virtual domains. Could you share a few lines of /var/log/mail.log to verify that?

      1. Mail delivery was not working. I have had to change the mailbox_command in postfix/main.cf .
        The right command which works for me:
        mailbox_command = /usr/lib/dovecot/dovecot-lda -f “$SENDER” -a “$RECIPIENT”

    2. tomabrafix

      Are you sure, that your domain isn’t listed in mydestination? If your domain is listed in mydestination, then virtual_transport will not react.

  2. I think i found it, i tested with the local command ‘echo test | mail john@example.org‘ then it won’t work. When i tested it from my email client it worked. (where is the ‘duh’ smiley when you need one…)

    I set an extra command in the /etc/postfix/main.cf file ‘local_transport = lmtp:unix:private/dovecot-lmtp’ this way it will also work when you locally test with the ‘echto test | mail john@example.org‘ command 😉

    (All other mailbox_commands can be deleted)

    1. Christoph Haas

      local_transport is definitely wrong. It’s not meant for virtual domains. Two wrongs don’t make a right.

      1. Hello,
        I have the same problem here, test | mail alex@mydomain.com echo the following
        Feb 6 16:47:40 myserver postfix/lmtp[18132]: D144DC0316: to=, relay=none, delay=0.03, delays=0.03/0/0/0, dsn=4.4.1, status=deferred (connect to ns301040.ovh.net[private/dovecot-lmtp]: No such file or directory)

        1. I have changed virtual_transport=lmtp:unix:private/dovecot-lmtp to virtual_transport=lmtp:unix:private/dovecot.
          It works now as it should but there must be an explanation. I am just doing trials and errors here.
          Thanks.

          1. Christoph Haas

            I’d say you have defined the “unix_listener /var/spool/postfix/private/dovecot-lmtp” incorrectly. If you point to private/dovecot but use private/dovecot-lmtp as a listener that wouldn’t work.

  3. Hey Christoph!

    Wonderful work with your ISPMail-Tutorial. Thank you very much!

    I just wanted to let you know that `/etc/dovecot/conf.d/20-lmtp.conf` does NOT exist in a default Debian/jessie installation. (At least not in my one).

    I took the one from Dovecot-Wiki: http://wiki2.dovecot.org/LMTP

    Hope thats ok. Maybe you could add “your” complete file. Or tell us where you did get the 20-lmtp.conf file from. Regards!

    1. Hmm.. Actually the file only consists of these three lines:

      protocol lmtp {
      mail_plugins = $mail_plugins sieve
      }

      Right?

      Does the line “protocols” line needs to be changed somewhere too?

      # add lmtp to protocols, otherwise its listeners are ignored
      protocols = imap pop3 lmtp

      (as stated in the dovecot wiki)

  4. Ahh.. easier!

    Please add “apt-get install dovecot-lmtpd” at the beginning…

    With that you will get `/etc/dovecot/conf.d/20-lmtp.conf`.. 😉

    1. Christoph Haas

      That’s right. I’m listing “dovecot-lmtpd” in the list of packages to be installed. But to be fair I changed that yesterday per request of a reader to simplify things. So if you were half through the guide then this was a bit unfair towards you because you didn’t know back then that the package has to be installed. Sorry.

    1. Christoph Haas

      Hi Osvaldo – thanks. Actually all you need to do is set the “mail_plugins” as described at the end of this page.

  5. Hi Christoff,
    all is going well I think – mine is a new install, no mail import or anything. I notice that there is no /var/log/mail as yet – is that to be expected at this stage?

  6. Hi Christoph,
    great tutorial as usual. Enjoying it for years now.
    Got an issue in my logs with the missing postmaster_address.
    Fatal: Error reading configuration: Invalid settings: postmaster_address setting not given
    As told in the dovecot wiki it seems to be required:
    http://wiki.dovecot.org/HowTo/PostfixDovecotLMTP

    Regards Nico

  7. a decision that helped me (Postfix main.cf):
    mailbox_transport = lmtp:unix:private/dovecot-lmtp

  8. Little problem here:
    I can login with Roundcube via Dovecot-imap, I can send e-Mails to external mail accounts.

    But on the receiving end:
    Postfix gets the mail, tries to deliver it to dovecot-lmtp, but dovecot-lmtp replies with: “User not found”. Same result when I try to send a mail to the same mail account via Roundcube.

    Any help would be appreciated.

    1. Shane Grey

      You might be running into the problem described by Nico https://workaround.org/ispmail/jessie/postfix-dovecot/#comment-12991

      I was, and his solution of adding this and restarting dovecot worked.

      `#/etc/dovecot//dovecot.conf`
      `postmaster_address={{ ispmail_postmaster_address }}`

      Then:
      `service dovecot restart`

      There was a delay to see the result however. I was testing for about 5 minutes after that change, and then emails that I had sent started coming in all at once. Likely this was due to a retry delay on the sending server.

  9. Chris, I’ve some generic questions about your ISPmail scenario, maybe you’ve some ideas or hints where to look for.

    I have aside to my private email accounts now “ISPmail”-based on my OpenSUSE vserver some ISP accounts. German Telekom “t-online”, etc. As I dont’t want my email staying on a “public” server, I’m using finally only POP for these accounts, storing every mail in my local Thunderbird. But as I’m also receive these email on my mobile, IMAP in this case, and answers a lot of them, I always have e.g. to move the IMAP “Sent Items” to my local (POP) Thunderbird sent items folder.

    Q: Would it easily (!! :-)) possible to create an IMAP account on my “ISPmail” box and collect all (sent and received) emails. Would “fetchmail” or something similar do this job, or even dovecot itself?

    Second is that I’ve also installed GNU Mailman, for a few small mailing lists (no spam :-)) Currently Mailman is still “fighting” or in fact still loosing against postfix and/or dovecot, because I’ve defined virtual alias catch-all addresses as described in your tutorial (“@domain.tld”). So all mails which should be received and processed by Mailman are “catched” and leads to a “mailbox does not exist” message.

    Q: Did you have the same requirement for mailing lists, any ideas how to solve this?

    Thanks and regards,
    Michael

  10. Hello Christoph,

    In my Dovecot config I set /var/vmail as a symlink to /mnt/hdd1/vmail

    Now when after executing command ‘echo test | mail john@example.org‘ I get the following error in the Dovecot log:

    dovecot[2386]: lmtp(2460, john@example.org): Error: User initialization failed: Namespace ”: mkdir(/var/vmail/example.org/john/Maildir) failed: Permission denied (euid
    =5000(vmail) egid=5000(vmail) UNIX perms appear ok (ACL/MAC wrong?))

    Are symlinks not allowed in the Dovecot config?

    BTW, in the Postfix’s main.cf there is a parameter

    mail_spool_directory = /var/mail

    that is a symlink to /var/spool/mail (I’ve changed it to /mnt/hdd1/mail), and it works fine. I get warning mail for the logged user in that directory flawlessly.

    Do I need to change the symlink /var/vmail to the absolute link or there is another solution?

  11. I’ve solved the problem. As I’m installing the software on openSUSE, it requires to make some settings for AppArmor. Namely, I had to edit /etc/apparmor.d/tunables/dovecot and specify there a space-separated list of all directories where Dovecot is allowed to store and read mails. In my case it is:

    @{DOVECOT_MAILSTORE}=/var/vmail/ /mnt/hdd1/vmail/

  12. for CentOS 7 this won’t work
    postconf virtual_transport=lmtp:unix:private/dovecot-lmtp
    default for built in dovecot rpm path for LMTP socket is
    /var/run/dovecot/lmtp
    so working config for postfix on CentOS 7
    postconf virtual_transport=lmtp:unix:/var/run/dovecot/lmtp
    the rest is on dovecot proper config

  13. Could you please help me.

    I have installed postfix, dovecot and roundcube on centos linex 8.

    An outgoing email are working from roundcube and via command line.

    But not working from sending from gmail or even sending to self in roundcube.

    Any help is highly appeciate.

    Thanks,
    Sam

  14. Hello, is there a way the postfix does not look at mx records if the domain is local ?
    I have two domains, both local and they seding messages to each other and receiving with lmpt and dovecot, is there any settings to tweak so the do not look at MX records of one another ?

    1. Christoph Haas

      By “local” you really mean a local domain – as in “listed in $mydestination”?

      Be aware that your comment is under the “Jessie” tutorial which is dealing with a very old Debian release. Please use the current “Bookworm” guide.

Leave a Reply

Your email address will not be published. Required fields are marked *

Scroll to Top