Dovecot Basics

Page 13 — IMAP/POP3 server. Mailbox access and authentication.

What Dovecot is

Dovecot handles:

Postfix moves mail between servers. Dovecot lets users access their mailboxes. They work alongside each other — Postfix delivers incoming mail into the mailbox; Dovecot serves it to clients.

Listener ports

# Default listener ports:
143   IMAP (STARTTLS upgrades from plaintext)
993   IMAPS (TLS from the start — older but still widely used)
110   POP3 (STARTTLS)
995   POP3S (TLS from the start)

# Check which ports Dovecot is actually listening on
ss -tlnp | grep dovecot
lsof -i -P -n | grep dovecot

LMTP — receiving mail from Postfix

In a typical setup, Postfix delivers locally-addressed mail to Dovecot via LMTP rather than writing mailbox files directly. This lets Dovecot handle delivery, indexing, and sieve filters.

# In Postfix main.cf — deliver via Dovecot LMTP socket
virtual_transport = lmtp:unix:private/dovecot-lmtp
# or over TCP:
virtual_transport = lmtp:inet:localhost:24

# In Dovecot /etc/dovecot/conf.d/20-lmtp.conf:
protocols = imap pop3 lmtp
# The LMTP socket is created by Dovecot at: /var/spool/postfix/private/dovecot-lmtp

TLS check

# Verify Dovecot TLS certificate and connection
openssl s_client -connect mail.example.com:993 -quiet
# Look for: subject, issuer, verify return code = 0 (ok)

# Test IMAP over STARTTLS (port 143)
openssl s_client -connect mail.example.com:143 -starttls imap

Common files

/etc/dovecot/dovecot.conf
/etc/dovecot/conf.d/

Main config is dovecot.conf. The conf.d/ directory contains split configuration files loaded in order. Key files:

Useful commands

doveconf

doveconf
doveconf -n

Shows the effective Dovecot configuration. -n shows non-default values only — like postconf -n for Postfix.

doveadm who

doveadm who

Shows currently connected users and sessions.

doveadm user

doveadm user '*'

Shows mailbox and user info for all users (depending on auth backend setup).

Service checks

systemctl status dovecot
journalctl -u dovecot -n 50

Troubleshooting

Sieve filtering (pigeonhole)

Dovecot's pigeonhole plugin implements RFC 5228 Sieve — server-side filters that run at LMTP delivery time, before the message reaches the user's INBOX. Users can edit their own rules (via ManageSieve on 4190/tcp) and the admin keeps a default rule set.

# /etc/dovecot/conf.d/90-sieve.conf
plugin {
  sieve = file:~/sieve;active=~/.dovecot.sieve
  sieve_default = /var/lib/dovecot/sieve/default.sieve
  sieve_extensions = +imap4flags +fileinto +envelope
}

# Enable the sieve plugin on LMTP and LDA
protocol lmtp {
  mail_plugins = $mail_plugins sieve
}
protocol lda {
  mail_plugins = $mail_plugins sieve
}

Per-user ~/.dovecot.sieve — route spam into a Junk folder based on the header set by Rspamd/SpamAssassin:

require ["fileinto", "imap4flags"];

if header :contains "X-Spam-Flag" "YES" {
    fileinto "Junk";
    stop;
}

if header :contains "List-Id" "announce.example.com" {
    fileinto "Lists/Announce";
}

After editing a script, compile it so the binary (.svbin) is cached: sievec ~/.dovecot.sieve. See Dovecot Sieve & Quotas for ManageSieve on 4190, quota-warning hooks, and shared-folder ACLs.

Debugging with doveadm

doveadm is the Swiss-army knife for mailbox inspection — it talks directly to the backend so it works even when IMAP clients are misbehaving. Three commands cover 90% of incident work:

doveadm fetch — read message content without a client

# First 20 messages in alice's INBOX with headers and flags
doveadm fetch -u alice 'hdr flags' mailbox INBOX 1:20

# Full raw RFC822 for a specific UID (useful for rebuilding a message)
doveadm fetch -u alice 'text' mailbox INBOX uid 42

# List every folder across every user
doveadm mailbox list -A

doveadm search — find a missing message

# Find a message by subject, across all folders, for one user
doveadm search -u alice mailbox-guid all subject "invoice #4711"

# Find messages older than 30 days, system-wide (all users with -A)
doveadm search -A mailbox INBOX savedbefore 30d

# Was anything delivered in the last 5 minutes?
doveadm search -A mailbox INBOX savedsince 5mins

doveadm who / kick — live sessions

# Who is connected right now, from where, and how many connections
doveadm who
doveadm who -1        # one line per session (useful for grep)

# Force-disconnect an abusive client
doveadm kick 203.0.113.42
doveadm kick alice    # kick all sessions for a user

If doveadm fetch succeeds but the IMAP client cannot see the same message, the fault is almost always a stale client-side index — doveadm index -u alice INBOX rebuilds it.

passdb options

passdb (password database) tells Dovecot how to verify credentials; userdb tells it where that user's mail lives. Several drivers are available and can be stacked — the first passdb that returns "user found" wins.

Common passdb drivers:
  • passdb { driver = pam } — delegate to Linux PAM (the default on new installs). Easy to integrate with SSSD/FreeIPA but forks a dovecot-auth-worker per request.
  • passdb { driver = sql } — query a MySQL/Postgres/SQLite table via /etc/dovecot/dovecot-sql.conf.ext. Best for virtual-domain hosting where users are not Linux accounts.
  • passdb { driver = ldap } — bind or compare against LDAP/389DS/AD using /etc/dovecot/dovecot-ldap.conf.ext. Supports auth_bind = yes for bind-as-user verification.
  • passdb { driver = passwd-file } — a plain file (user:{SCHEME}hash:uid:gid::home::). Handy for a small fixed user list or test environments.
Set auth_cache_size = 10M in 10-auth.conf to cache successful lookups in memory — critical for sql/ldap backends so every IMAP NOOP doesn't hit the database. Pair with auth_cache_ttl = 1 hour and auth_cache_negative_ttl = 1 hour to bound the staleness. Pre-auth failures are covered by SSSD in most FreeIPA setups; see SSSD & Auth Flow.