I've taken great pains to get my mail server set up both the way I want it and correctly. I'm now sharing that knowledge with the internet as a whole, as well as myself when I need to figure out wtf I did.
NOTE
This article should be considered archived as of 2023-02-09. I have abandoned the maintenance of my own email solution for ProtonMail.
Setting up virtual mail users and authentication through Dovecot
My goal here was to use LDAP for authentication and creation of mailboxes for "virtual users" (ie, they don't exist in /etc/password and have home directory). I set it up this way so that I could set up mailboxes for application accounts and get their mail delivered to a predictable place and be able to access it through IMAP without having to have it clutter my actual mailbox.
The bulk of the 'fun stuff' is in /etc/dovecot/dovecot-ldap.conf.ext - it's well commented, so I'm just going to list the settings I changed. For purposes of cleanliness, I'm going to use 'example.com' and 'not the real password' where appropriate :-) I'm using a fairly standard simple bind.
hosts = localhost dn = cn=admin,dc=example,dc=com dnpass = not the real password auth_bind_userdn = uid=%u,ou=People,dc=example,dc=com
Here's I'm checking the users and passwords against the mail attribute on the LDAP account. I'm then ignoring interesting parts of the results to store all mail under a 'vmail' user with uid and gid of 5000 and a subdirectory named after the real users. Dovecot finds this location both when delivering and serving, so no further setup here needed.
base = dc=example,dc=com user_attrs = 5000=uid,5000=gid,home=/var/vmail/%u user_filter = (&objectClass=posixAccount)(mail=%n@example.com) pass_attrs = uid=user,userPassword=password,homeDirectory=/var/vmail/%u pass_filter = (&objectClass=posixAccount)(mail=%n@example.com)
After this, I just have to wire it up in conf.d/auth-ldap.conf.ext to use ldap for password lookups and semi-hardcoded user lookups---don't validate the user and assume they get mail to /var/vmail/{username}
passdb {
driver = ldap
args = /etc/dovecot/dovecot-ldap.conf.ext
}
userdb {
driver = static
args = uid=vmail gid=vmail home=/var/vmail/%u
}
Setting up Postfix to authenticate through Dovecot
Because I spent so much time getting authentication working for Dovecot, let's just re-use it for postfix because the same users are trying to send mail as are receiving it.
In /etc/dovecot/conf.d/10-master.conf
# Setup the socket for postfix to authentical against
service auth {
unix-listener /var/spool/postfix/private/auth {
mode = 0666
}
}
In /etc/postfix/main.cf for authentication
# SASL authentication smtpd_sasl_type = dovecot smtpd_sasl_auth_enable = yes smtpd_recipient_restrictions = permit_sasl_authenticated,permit_mynetworks,reject_unauth_destination smtpd_sasl_path = private/auth
In /etc/postfix/main.cf for mail delivery
# Postfix MDA mailbox_transport = dovecot mailbox_commant = /usr/lib/dovecot/dovecot-lda -a "$RECIPIENT" virtual_transport = dovecot dovecot_destination_recipient_limit = 1
In /etc/postfix/master.cf before the non-posix services
dovecot unix - n n - - pipe
flags=DRhu user=vmail:vmail argv=/usr/lib/dovecot/dovecot-lda -f ${sender} -d ${user} -a ${recipient}
Amavis: Spamassassin and ClamAV
Install but do not enable spamassassin. Amavis will take care of launching a scanner as it scans emails. When I enabled the spamassassin daemon, I ended up with all cpu cores fully utilized.
Install and do enable clamav-daemon. Amavis can use the daemon for a bit of a computational advantage.
Install Amavis and configure it to use spamassassin and clamav. As I'm using Debian, I updated the 15-content_filter_mode to uncomment the virus_checks and spam_checks lines
use strict; # You can modify this file to re-enable SPAM checking through spamassassin # and to re-enable antivirus checking. # Default antivirus checking mode # Please note, that anti-virus checking is DISABLED by # default. # If you wish to enable it, please uncomment the following line: @bypass_virus_checks_maps = ( %bypass_virus_checks, @bypass_virus_checks_acl, $bypass_virus_checks_re); # Default SPAM checking mode # Please note, that anti-spam checking is DISABLED by # default. # If You wish to enable it, please uncomment the following lines: @bypass_spam_checks_maps = ( %bypass_spam_checks, @bypass_spam_checks_acl, $bypass_spam_checks_re); 1; # ensure a defined return
At the end of the postfix master.cf file, I added the following lines to shunt the email to Amavis.
smtp-amavis unix - - - - 2 smtp
-o smtp_data_done_timeout=1200
-o smtp_send_xforward_command=yes
-o disable_dns_lookups=yes
-o max_use=20
127.0.0.1:10025 inet n - - - - smtpd
-o content_filter=
-o smtpd_delay_reject=no
-o smtpd_client_restrictions=permit_mynetworks,reject
-o smtpd_helo_restrictions=
-o smtpd_sender_restrictions=
-o smtpd_recipient_restrictions=permit_mynetworks,reject
-o smtpd_data_restrictions=reject_unauth_pipelining
-o smtpd_end_of_data_restrictions=
-o smtpd_restriction_classes=
-o mynetworks=127.0.0.0/8
-o smtpd_error_sleep_time=0
-o smtpd_soft_error_limit=1001
-o smtpd_hard_error_limit=1000
-o smtpd_client_connection_count_limit=0
-o smtpd_client_connection_rate_limit=0
-o receive_override_options=no_header_body_checks,no_unknown_recipient_checks,no_milters
-o local_header_rewrite_clients=