Mail Server Series — Part 5
In Part 4, we built a production-grade Postfix SMTP system with:
- MySQL-based virtual domains
- SNI TLS
- LMTP delivery
- Amavis filtering
- Piler archiving
- Submission (587) and SMTPS (465) user authentication
In this article, we implement the other half of the mail delivery system — Dovecot, the component responsible for:
- IMAP / POP3 services
- Final mailbox storage
- SQL authentication
- LMTP delivery (from Postfix)
- SIEVE filtering, including spam learning
- Quota enforcement
- TLS SNI per domain
- Docker-based deployment
Dovecot is the heart of your mail system — every email is ultimately stored and accessed through it.
🧩 1. What You Will Have After This Part
After completing this chapter, you will have:
✔ Fully working IMAP (143/993) and POP3 (110/995)
✔ LMTP delivery (Postfix → Dovecot)
✔ SQL authentication (integrated with PostfixAdmin)
✔ SNI TLS for multi-domain deployments
✔ User mailbox quota with real-time warning emails
✔ Sieve rules and ManageSieve service (Roundcube filters)
✔ Automatic spam learning (spam/ham) through IMAPSieve
✔ Docker-based, reproducible and maintainable deployment
📦 2. Building the Dovecot Docker Image
We base our build on Alpine Linux 3.22.1, including:
- dovecot + lmtpd
- dovecot-mysql
- dovecot-pigeonhole (Sieve)
- spamassassin-client (spamc)
Dockerfile
FROM alpine:3.22.1
RUN apk update && \
apk add --no-cache \
dovecot dovecot-lmtpd dovecot-mysql dovecot-pigeonhole-plugin \
bash vim tzdata ca-certificates \
spamassassin-client \
shadow su-exec
RUN addgroup -g 5000 -S vmail && \
adduser -D -S -H -s /sbin/nologin -u 5000 -G vmail vmail
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
EXPOSE 110 995 143 993 24 4190
CMD ["/entrypoint.sh"]
🔖 3. Directory Structure
/opt/docker/mail/dovecot/
├─ config/ → mounted to /etc/dovecot
├─ sieve/ → global Sieve rules
├─ shell/ → custom scripts (quota warnings, spam learning)
├─ log/ → /var/log/dovecot
└─ usermail/ → /var/vmail (actual maildir)
Ensure mailbox permissions:
chown -Rf 5000:5000 usermail/
chown -Rf 5000:5000 config/sieve/
🧩 4. SQL Authentication (MySQL + PostfixAdmin)
The authentication source is the same database PostfixAdmin uses.
/etc/dovecot/dovecot-sql.conf.ext:
driver = mysql
connect = host=maildb dbname=postfix user=postfix password=postfix1230
password_query = SELECT username AS user, password FROM mailbox WHERE username='%u' AND active='1'
user_query = SELECT 5000 AS uid, 5000 AS gid, '/var/vmail/%d/%n' AS home, 'maildir:/var/vmail/%d/%n' AS mail
This ensures consistent user management across Postfix, Roundcube, and Dovecot.
🔐 5. TLS SNI for Multiple Domains
Dovecot supports per-domain certificates.
10-ssl.conf:
ssl = required
ssl_cert = </etc/letsencrypt/live/it.demo.tw/fullchain.pem
ssl_key = </etc/letsencrypt/live/it.demo.tw/privkey.pem
local_name it.demo.tw {
ssl_cert = </etc/letsencrypt/live/it.demo.tw/fullchain.pem
ssl_key = </etc/letsencrypt/live/it.demo.tw/privkey.pem
}
local_name nuface.tw {
ssl_cert = </etc/letsencrypt/live/nuface.tw/fullchain.pem
ssl_key = </etc/letsencrypt/live/nuface.tw/privkey.pem
}
📥 6. LMTP Delivery from Postfix
As configured in Part 4:
virtual_transport = lmtp:inet:dovecot:24
Dovecot:
10-master.conf:
service lmtp {
inet_listener lmtp {
address = *
port = 24
}
}
LMTP provides:
- per-user delivery status
- correct bounces
- quota support
- efficient local delivery
📦 7. Quota + Automatic Warning Emails
Enable quota plugin:
plugin {
quota = maildir:User quota
quota_rule = *:storage=2G
quota_rule2 = Trash:storage=+100M
}
Enable notifications:
quota_warning = storage=80%% quota-warning 80 %u
quota_warning2 = storage=95%% quota-warning 95 %u
quota_warning3 = -storage=100%% quota-warning below %u
Your quota-warning.sh generates multilingual notification emails.
🧠 8. SpamAssassin Remote Learning (IMAPSieve)
This system supports:
- Move to Junk folder → mark as spam
- Move out of Junk → mark as ham
Rules:
global/learn-spam.sieve
global/learn-ham.sieve
Scripts:
sa-remote-learn-spam.sh
sa-remote-learn-ham.sh
Learning is executed through spamc:
spamc -d spamassassin -p 783 -u <user> -L spam
This ensures:
- accurate Bayes scoring
- per-user training
- SQL-based storage
📐 9. Sieve + ManageSieve (Roundcube Integration)
Enable ManageSieve:
protocol sieve {
listen = *:4190
}
Roundcube connects using:
tls://dovecot:4190
Users can create:
- Forwarding rules
- Auto-move filters
- Auto-delete
- Vacation replies
🐳 10. Running the Dovecot Container
docker run -dit --name dovecot \
--restart=always \
--network intranet-net \
-p 110:110 -p 995:995 \
-p 143:143 -p 993:993 \
-p 24:24 -p 4190:4190 \
-e TZ=Asia/Taipei \
-v $PWD/config:/etc/dovecot \
-v $PWD/log:/var/log \
-v $PWD/usermail:/var/vmail \
-v /opt/docker/wwwapp/data/etc-letsencrypt:/etc/letsencrypt \
nuface/dovecot-2.4.1-4:1.0
🧪 11. Testing the Setup
1. Check version
dovecot --version
2. Test IMAPS
openssl s_client -connect it.demo.tw:993
3. Test SQL authentication
doveadm auth test [email protected] password
4. Test LMTP
telnet dovecot 24
5. Test Sieve
doveadm sieve list -u [email protected]
6. Test spam learning
cat spam.eml | spamc -L spam -u [email protected]
🏁 12. Summary: Your Receiving System Is Now Enterprise-Ready
By completing this article, you now have:
✔ Full IMAP/POP3/LMTP support
✔ SQL-based user authentication
✔ Multi-domain TLS SNI
✔ Quota management with warnings
✔ Sieve + ManageSieve
✔ Automatic spam learning
✔ Containerized deployment
Dovecot is now fully integrated into your complete mail stack and ready for production.