Skip to content

# LMTP

Todo list for receiving emails

1. 1

   DNS records point to your server

2. 2

   Get a certificate from Let's Encrypt

3. 3

   Postfix fetches information from MariaDB

4. 4

   Dovecot fetches information from MariaDB

5. 5

   Postfix hands over emails to Dovecot

6. 6

   Dovecot saves the email to disk

Glad to see that you are still with me. We are very close to receiving our first email. If you feel lost, please review the slideshow from earlier in this guide.

As explained in the previous section, Postfix speaks SMTP and receives the email from the internet. Postfix could even save the email to a mailbox on disk. But instead we will use Dovecot for the final delivery. Actually Dovecot’s main purpose is to let users fetch their email using the IMAP protocol. But it provides additional features we can use as well.

So we need tell Postfix to hand over the incoming email to Dovecot. The communication between Postfix and Dovecot will happens using LMTP – the local mail transfer protocol. LMTP is a lightweight variant of SMTP. It is meant for email communication between internal services that trust each other.

## Dovecot listens to LMTP

Section titled “Dovecot listens to LMTP”

First we need to add a UNIX socket where Dovecot listens for incoming LMTP connections:

Run this on your server

    # Add an LMTP listening socket in Dovecotcat > /etc/dovecot/conf.d/99-ispmail-lmtp-listener.conf << EOFservice lmtp {  # Used internally by Dovecot  unix_listener lmtp {  }
      # Listen to LMTP connections from Postfix  unix_listener /var/spool/postfix/private/dovecot-lmtp {    mode = 0600    user = postfix    group = postfix  }}EOF
    # Restart Dovecotsystemctl restart dovecot

The first `unix_listener lmtp` is just used internally by Dovecot and does not concern us. The second part is what you will be adding. It makes Dovecot create a socket file at `/var/spool/postfix/private/dovecot-lmtp`. As Postfix has its home in `/var/spool/postfix` it can access that socket to speak LMTP with Dovecot.

A socket is similar to a TCP port but it’s only available for other processes running on same system. That’s why you also set the access mode, user and group so that Postfix can actually use it.

## Postfix talks to Dovecot using LMTP

Section titled “Postfix talks 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. So please run:

Run this on your server

    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` – because `/var/spool/postfix` is the Postfix’s home directory.

## Send a test mail locally

Section titled “Send a test mail locally”
Todo list for receiving emails

1. 1

   DNS records point to your server

2. 2

   Get a certificate from Let's Encrypt

3. 3

   Postfix fetches information from MariaDB

4. 4

   Dovecot fetches information from MariaDB

5. 5

   Postfix hands over emails to Dovecot

6. 6

   Dovecot saves the email to disk

Finally we are ready for our first email. Using the `swaks` command you can create a test email to `john@example.org` and send it to Postfix:

Run this on your server

    swaks --server localhost --to john@example.org

If all goes as planned, you will see an SMTP dialog like this:

    === Trying localhost:25...=== Connected to localhost.<-  220 mail ESMTP Postfix (Debian) -> EHLO mail<-  250-mail<-  250-PIPELINING<-  250-SIZE 10240000<-  250-VRFY<-  250-ETRN<-  250-STARTTLS<-  250-ENHANCEDSTATUSCODES<-  250-8BITMIME<-  250-DSN<-  250-SMTPUTF8<-  250 CHUNKING -> MAIL FROM:<root@mail><-  250 2.1.0 Ok -> RCPT TO:<john@example.org><-  250 2.1.5 Ok -> DATA<-  354 End data with <CR><LF>.<CR><LF> -> Date: Sun, 24 Aug 2025 21:08:59 +0000 -> To: john@example.org -> From: root@mail -> Subject: test Sun, 24 Aug 2025 21:08:59 +0000 -> Message-Id: <20250824210859.021444@mail> -> X-Mailer: swaks v20240103.0 jetmore.org/john/code/swaks/ -> -> This is a test mailing -> -> -> .<-  250 2.0.0 Ok: queued as 2742B221FA -> QUIT<-  221 2.0.0 Bye=== Connection closed with remote host.

If you see a `250 2.0.0 Ok: queued as…” near the end of this dialog, then Postfix has received the email successfully.

Check if Postfix managed to pass the email to Dovecot:

Run this on your server

    journalctl -n 10 -u dovecot

The line you are looking for looks like:

    Aug 24 21:36:22 mail dovecot[23214]: lmtp(john@example.org)<…><…>: msgid=<20250824213622.023221@mail>: saved mail to INBOX

Does it say `saved mail to INBOX`? Awesome. The email should be visible in John’s home directory. Check it:

Run this on your server

    find /var/vmail/example.org/john

Does it look like this?

    /var/vmail//var/vmail/example.org/var/vmail/example.org/john/var/vmail/example.org/john/Maildir/var/vmail/example.org/john/Maildir/maildirfolder/var/vmail/example.org/john/Maildir/new/var/vmail/example.org/john/Maildir/new/1756071382.M198387P23222.mail,S=635,W=655/var/vmail/example.org/john/Maildir/cur/var/vmail/example.org/john/Maildir/tmp/var/vmail/example.org/john/Maildir/dovecot-uidvalidity.68ab85d6/var/vmail/example.org/john/Maildir/dovecot.index.log/var/vmail/example.org/john/Maildir/dovecot-uidvalidity/var/vmail/example.org/john/Maildir/dovecot.index.cache/var/vmail/example.org/john/Maildir/dovecot-uidlist/var/vmail/example.org/john/Maildir/dovecot.list.index.log

The important file here is `…/Maildir/new/1756071382.M198387P23222.mail,S=635,W=655`. The numbers will look differently on your system. But this is the actual mail that got delivered. You can view it with `cat` and will find the test email you just sent using `swaks`.

Don’t worry about the other files like `maildirfolder` or the files that sound like `dovecot…`. Those help Dovecot keep track of the mailbox. You can safely ignore them.

## Your actual domain

Section titled “Your actual domain”

Obviously the previous examples dealt with the `example.org` domain which is not your actual domain. Feel free to add your own domain to the database and create a test user. The later section on managing users will explain that in detail.