Dovecot is an IMAP and POP3 server: it gives mail clients such as Thunderbird, Outlook and phone mail apps access to the mailboxes that Postfix fills. It also provides the authentication service that Postfix uses to let those clients send mail through the server. In this tutorial you will add Dovecot to an existing Postfix server on Ubuntu 24.04, serve IMAP on port 993 and POP3 on port 995 with a Let's Encrypt certificate, and enable authenticated sending on port 587.

Prerequisites

To follow this tutorial you need:

  • A server running Ubuntu 24.04 LTS with Postfix already receiving mail for your_domain, configured as in the guide "How to Set Up a Postfix Mail Server on Ubuntu 24.04". In particular:
    • Postfix delivers to Maildir/ in each user's home directory (home_mailbox = Maildir/).
    • A Let's Encrypt certificate exists in /etc/letsencrypt/live/mail.your_domain/.
    • UFW is enabled with SSH allowed.
  • A non-root user with sudo privileges.
  • A Linux user whose mailbox you will read, called your_user in this guide. Each mail account in this setup is a regular system user with a password; if you need mail accounts that are not Linux users, follow the Postfix and Dovecot virtual mailbox guide instead.

Step 1 - Installing Dovecot

Install the Dovecot core together with the IMAP and POP3 servers:

sudo apt update
sudo apt install dovecot-core dovecot-imapd dovecot-pop3d

The packages enable the imap and pop3 protocols automatically and start the service. dovecot --version should report a 2.3 release, which is what the configuration in this guide is written for. Check the service state:

sudo systemctl status dovecot --no-pager
● dovecot.service - Dovecot IMAP/POP3 email server
     Loaded: loaded (/usr/lib/systemd/system/dovecot.service; enabled; preset: enabled)
     Active: active (running) since ...

Dovecot's configuration is split into small files under /etc/dovecot/conf.d/, included by /etc/dovecot/dovecot.conf. You only need to change a few of them.

Step 2 - Pointing Dovecot at the Maildir

By default Ubuntu configures Dovecot to read mbox files in /var/mail. Postfix delivers to ~/Maildir, so the two must agree. Open the mail settings:

sudo nano /etc/dovecot/conf.d/10-mail.conf

Find the mail_location line and change it to:

mail_location = maildir:~/Maildir

Next, make sure every account gets the standard folders so mail clients store sent mail and drafts in the same place. Open the mailbox definitions:

sudo nano /etc/dovecot/conf.d/15-mailboxes.conf

Add auto = subscribe to the Drafts, Junk, Trash and Sent mailboxes so they are created and subscribed automatically:

namespace inbox {
  mailbox Drafts {
    auto = subscribe
    special_use = \Drafts
  }
  mailbox Junk {
    auto = subscribe
    special_use = \Junk
  }
  mailbox Trash {
    auto = subscribe
    special_use = \Trash
  }
  mailbox Sent {
    auto = subscribe
    special_use = \Sent
  }
  mailbox "Sent Messages" {
    special_use = \Sent
  }
}

Leave the rest of the file unchanged.

Step 3 - Configuring authentication

Dovecot authenticates system users through PAM by default (!include auth-system.conf.ext in 10-auth.conf), which is what this setup needs. Two changes make it work well with mail clients. Open the authentication settings:

sudo nano /etc/dovecot/conf.d/10-auth.conf

Set these values:

disable_plaintext_auth = yes
auth_username_format = %Ln
auth_mechanisms = plain login
  • disable_plaintext_auth = yes refuses passwords on unencrypted connections. It is the default, but keep it explicit.
  • auth_username_format = %Ln lowercases the login and strips the domain, so a user can log in as your_user@your_domain or as your_user. Many clients fill in the full email address by default.
  • auth_mechanisms = plain login adds the LOGIN mechanism that older Outlook versions use. Both send the password in clear text inside the TLS connection, which is why TLS is required in the next step.

Step 4 - Enabling TLS with the Let's Encrypt certificate

Open the SSL settings:

sudo nano /etc/dovecot/conf.d/10-ssl.conf

Replace the ssl, ssl_cert and ssl_key lines and set the minimum protocol:

ssl = required
ssl_cert = </etc/letsencrypt/live/mail.your_domain/fullchain.pem
ssl_key = </etc/letsencrypt/live/mail.your_domain/privkey.pem
ssl_min_protocol = TLSv1.2

The < before the path is required: it tells Dovecot to read the value from the file. ssl = required rejects authentication on any connection that has not negotiated TLS.

Dovecot reads the certificate only at startup, so it must be reloaded when Certbot renews it. Certbot runs every executable in /etc/letsencrypt/renewal-hooks/deploy/ after a successful renewal. Create a hook:

sudo nano /etc/letsencrypt/renewal-hooks/deploy/reload-mail.sh
#!/bin/sh
systemctl reload postfix dovecot

Make it executable:

sudo chmod 755 /etc/letsencrypt/renewal-hooks/deploy/reload-mail.sh

Step 5 - Opening the ports and restarting Dovecot

Validate the configuration before restarting. doveconf -n prints only the settings that differ from the defaults, and it exits with an error if a file has a syntax problem:

sudo doveconf -n | grep -E 'mail_location|auth_|ssl'
auth_mechanisms = plain login
auth_username_format = %Ln
mail_location = maildir:~/Maildir
ssl = required
ssl_cert = </etc/letsencrypt/live/mail.your_domain/fullchain.pem
ssl_key = # hidden, use -P to show it

Restart Dovecot:

sudo systemctl restart dovecot

Dovecot listens on 143 and 110 (plain with STARTTLS) and on 993 and 995 (implicit TLS). Open only the implicit TLS ports, which every current client supports:

sudo ufw allow 993/tcp
sudo ufw allow 995/tcp

Confirm the listening ports:

sudo ss -ltnp | grep dovecot
LISTEN 0      100          0.0.0.0:993       0.0.0.0:*    users:(("dovecot",pid=5120,fd=38))
LISTEN 0      100          0.0.0.0:995       0.0.0.0:*    users:(("dovecot",pid=5120,fd=24))
LISTEN 0      100          0.0.0.0:110       0.0.0.0:*    users:(("dovecot",pid=5120,fd=22))
LISTEN 0      100          0.0.0.0:143       0.0.0.0:*    users:(("dovecot",pid=5120,fd=36))
...

Step 6 - Testing IMAP and POP3

First check that Dovecot accepts the user's password. doveadm auth test asks for the password and runs the same lookup a client login would:

sudo doveadm auth test your_user
Password:
passdb: your_user auth succeeded
extra fields:
  user=your_user

Now open an IMAP session over TLS from the server itself:

openssl s_client -connect mail.your_domain:993 -quiet

The certificate details are printed first, then Dovecot's greeting. Type the IMAP commands one at a time; each line starts with a tag (a, b, c) that the server repeats in its answer. Replace your_password with the user's password:

a LOGIN your_user your_password
b LIST "" "*"
c LOGOUT
* OK [CAPABILITY IMAP4rev1 SASL-IR LOGIN-REFERRALS ID ENABLE IDLE LITERAL+ AUTH=PLAIN AUTH=LOGIN] Dovecot (Ubuntu) ready.
a OK [CAPABILITY ...] Logged in
* LIST (\HasNoChildren \Drafts) "." Drafts
* LIST (\HasNoChildren \Junk) "." Junk
* LIST (\HasNoChildren \Trash) "." Trash
* LIST (\HasNoChildren \Sent) "." Sent
* LIST (\HasNoChildren) "." INBOX
b OK List completed.
c OK Logout completed.

Test POP3 on port 995 the same way:

openssl s_client -connect mail.your_domain:995 -quiet
USER your_user
PASS your_password
STAT
QUIT

STAT answers with +OK followed by the number of messages and their total size in bytes.

If a login fails, the reason is in the mail log: sudo grep dovecot /var/log/mail.log | tail.

Step 7 - Enabling authenticated sending in Postfix

Mail clients send through port 587 (submission), and the server must check their password before relaying mail to other domains. Postfix can use Dovecot for this through a Unix socket.

Open Dovecot's service definitions:

sudo nano /etc/dovecot/conf.d/10-master.conf

Inside the service auth { ... } block, uncomment and complete the Postfix listener. The socket lives inside Postfix's chroot at /var/spool/postfix:

service auth {
  unix_listener auth-userdb {
    #mode = 0666
    #user =
    #group =
  }

  # Postfix smtp-auth
  unix_listener /var/spool/postfix/private/auth {
    mode = 0660
    user = postfix
    group = postfix
  }
}

Restart Dovecot and check that the socket exists:

sudo systemctl restart dovecot
sudo ls -l /var/spool/postfix/private/auth
srw-rw---- 1 postfix postfix 0 Sep 25 11:02 /var/spool/postfix/private/auth

Tell Postfix to use Dovecot for SASL authentication. The path is relative to the Postfix chroot:

sudo postconf -e "smtpd_sasl_type = dovecot"
sudo postconf -e "smtpd_sasl_path = private/auth"

Authentication is enabled only on the submission port, not on port 25, so it is defined in master.cf. Open it:

sudo nano /etc/postfix/master.cf

Ubuntu's file contains a commented-out submission block. Replace it with this one (the lines starting with -o must be indented with at least one space):

submission inet n       -       y       -       -       smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_tls_auth_only=yes
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING
  • smtpd_tls_security_level=encrypt refuses any command before STARTTLS.
  • The two restrictions let only authenticated users use this port, and let them send to any domain.

Check the configuration, restart Postfix and open the port:

sudo postfix check
sudo systemctl restart postfix
sudo ufw allow 587/tcp

Verify that the server offers authentication after STARTTLS:

openssl s_client -starttls smtp -connect mail.your_domain:587 -quiet

Type EHLO test and press Enter:

250-mail.your_domain
250-PIPELINING
250-SIZE 10240000
250-ETRN
250-AUTH PLAIN LOGIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250-DSN
250-SMTPUTF8
250 CHUNKING

The AUTH PLAIN LOGIN line confirms that Dovecot SASL is active. Type QUIT to close the session.

Finally, send a real message through the submission port with swaks, a command-line SMTP test tool. It asks for the password:

sudo apt install swaks
swaks --to [email protected] --from your_user@your_domain --server mail.your_domain --port 587 --tls --auth LOGIN --auth-user your_user

The last lines of the output show the message was accepted:

<-  250 2.0.0 Ok: queued as 4XbR1c3Vbwz9sWf
 -> QUIT
<-  221 2.0.0 Bye

Step 8 - Protecting logins with Fail2ban

A public IMAP and SMTP server receives password-guessing attempts within hours. Fail2ban reads the mail log and temporarily bans addresses with repeated failures. Install it:

sudo apt install fail2ban

Enable the built-in jails for Dovecot and Postfix authentication in a local file, which package updates do not overwrite:

sudo nano /etc/fail2ban/jail.d/mail.local
[dovecot]
enabled = true

[postfix-sasl]
enabled = true

Restart Fail2ban and check the jails:

sudo systemctl restart fail2ban
sudo fail2ban-client status
Status
|- Number of jail:      3
`- Jail list:   dovecot, postfix-sasl, sshd

sudo fail2ban-client status dovecot shows the currently banned addresses.

Step 9 - Configuring a mail client

Use these settings in Thunderbird, Outlook or a phone mail app:

SettingValue
Usernameyour_user@your_domain (or your_user)
Incoming server (IMAP)mail.your_domain, port 993, SSL/TLS, normal password
Incoming server (POP3)mail.your_domain, port 995, SSL/TLS, normal password
Outgoing server (SMTP)mail.your_domain, port 587, STARTTLS, normal password

Choose IMAP unless you specifically want messages downloaded and removed from the server. IMAP keeps mail and folders on the server, so every device sees the same state.

Troubleshooting

  • auth failed for a correct password: check sudo grep 'auth' /var/log/mail.log | tail. A pam_authenticate() failed message means the password is wrong or the account is locked. Test directly with sudo doveadm auth test your_user.
  • Plaintext authentication disallowed on non-secure connection: the client connected to 143 or 110 without STARTTLS. Switch it to port 993 or 995 with SSL/TLS.
  • Login works but the mailbox is empty: Dovecot and Postfix disagree on the location. postconf home_mailbox must say Maildir/ and doveconf mail_location must say maildir:~/Maildir.
  • SASL authentication failure: cannot connect to Dovecot auth server: the socket is missing or has the wrong owner. Check /var/spool/postfix/private/auth as in Step 7 and restart Dovecot.
  • Clients warn about the certificate: the client must use mail.your_domain, the name on the certificate, not the IP address or another hostname.

Conclusion

Your server now serves IMAP and POP3 over TLS, lets users send authenticated mail on port 587, and bans addresses that guess passwords. Every mail account is a Linux user, which works well for a few people. To host several domains or mailboxes that are not system accounts, move to virtual mailboxes delivered by Dovecot LMTP, and consider adding quotas and server-side filtering with Sieve (dovecot-sieve).