Mail Server Setup

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=

Thanks

These fine projects have been used as my tools of choice in serving mail.

Dovecot logo Postfix logo clamav logo spamassassin logo