Email Server Configuration

Email Server Configuration

Introduction

Setting up an email server on MidnightBSD provides full control over your email infrastructure. MidnightBSD includes mail delivery utilities derived from FreeBSD and DragonFly BSD, and supports popular mail server software through mports including Sendmail, Postfix, Dovecot, rspamd, ClamAV, and SpamAssassin.

This guide covers the complete email stack: Mail Transfer Agents (MTA) for sending and receiving mail, Local Delivery Agents (LDA) for delivering mail to local mailboxes, Mail Retrieval Agents (MRA) for IMAP/POP3 access, and security/filtering components to protect your server from spam and malware.

Email Architecture Overview

A complete email server typically consists of several components working together:

Typical mail flow: Incoming mail → MTA → Spam/Virus Filter → LDA → Mailbox ← MRA ← Email Client

Base System Mail Delivery

Local Mail Delivery

MidnightBSD includes several mail-related utilities in the base system, inherited from FreeBSD and DragonFly BSD:

The base system mail.local is a simple local mail delivery agent that delivers mail to /var/mail mailboxes in mbox format. It supports basic features like forwarding via .forward files.

Viewing mail queues:

# mailq

Sending a test email from command line:

$ echo "Test message body" | mail -s "Test Subject" user@localhost

Reading mail with the mail command:

$ mail

mailwrapper

mailwrapper is a lightweight MTA wrapper that allows switching between different MTAs without modifying system configurations. It examines the /etc/mail/mailer.conf file to determine which MTA to use for various mail operations.

Default mailer.conf:

# $MidnightBSD$
sendmail       /usr/libexec/sendmail/sendmail
mailq          /usr/libexec/sendmail/sendmail
newaliases     /usr/libexec/sendmail/sendmail
hoststat       /usr/libexec/sendmail/sendmail
purgestat      /usr/libexec/sendmail/sendmail

When you install Postfix or Sendmail from mports, they will typically update this file to point to their respective binaries.

Aliases and Forwarding

Email aliases allow you to forward mail for one user to another, or to multiple recipients. The base system uses /etc/mail/aliases for this purpose.

Editing aliases:

# vi /etc/mail/aliases

Example aliases file:

# Basic format: alias: recipient1, recipient2, ...
# System aliases
root: laffer1
postmaster: root
webmaster: root

# Forward user john's mail to external address
john: john@example.com

# Forward to multiple recipients
admin: root, laffer1, backup@example.com

# Mailing list
staff: alice, bob, charlie

After modifying aliases, run:

# newaliases

User-level forwarding: Individual users can create a .forward file in their home directory to forward their mail:

$ echo "user@example.com" > ~/.forward

Note: Be careful with .forward files as they can create mail loops if not configured properly.

Mail Transfer Agents (MTA)

Sendmail

Sendmail is the traditional Unix MTA and is available in mports. It is feature-rich but has a reputation for complex configuration.

Installation and Configuration

Install Sendmail from mports:

# mport install sendmail

Sendmail configuration is primarily done through the sendmail.mc file which is compiled into sendmail.cf.

Basic sendmail.mc configuration:

# vi /usr/local/etc/mail/sendmail.mc

Common configuration directives:

# Set the hostname
MASQUERADE_AS(`yourdomain.com')

# Allow relay for local networks
ACCESS_DB(`hash -o /etc/mail/access.db')

# Set trusted networks
LOCAL_NET_CONFIG
R$* < @ $=w . >            $: $1         user@trusted.net

Compile the configuration:

# cd /usr/local/etc/mail
# make
# make install
# make restart
Configuration Files
Starting Sendmail

Enable Sendmail at boot:

# sysrc sendmail_enable=YES
# sysrc sendmail_submit_enable=YES
# sysrc sendmail_outbound_enable=YES
# sysrc sendmail_msp_queue_enable=YES

Start Sendmail services:

# service sendmail start

Check Sendmail status:

# service sendmail status
# ps aux | grep sendmail

View mail queue:

# mailq
# sendmail -bp

Flush the mail queue:

# sendmail -q
# sendmail -q10m  # Process queue every 10 minutes

Postfix

Postfix is a modern, secure, and easy-to-configure MTA that is widely used as an alternative to Sendmail. It has a modular design with a focus on security and performance.

Installation

Install Postfix from mports:

# mport install postfix

If installing Postfix alongside Sendmail: You may need to disable Sendmail first:

# sysrc sendmail_enable=NO
# service sendmail stop

Postfix installation will prompt you to configure the default mailer.conf. Typically, you want Postfix to be the default MTA.

Basic Configuration

Postfix uses two main configuration files: main.cf and master.cf.

Main configuration file:

# vi /usr/local/etc/postfix/main.cf

Essential main.cf settings:

# Basic settings
myhostname = mail.yourdomain.com
mydomain = yourdomain.com
myorigin = $mydomain
inet_interfaces = all
mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain

# Trusted networks (allow relay)
mynetworks = 127.0.0.0/8, [::1]/128, 192.168.1.0/24

# Reject unknown users
local_recipient_maps = proxy:unix:passwd.byname $alias_maps

# Use canonical maps for address rewriting
canonical_maps = hash:/usr/local/etc/postfix/canonical

# Bounce configuration
bounce_queue_lifetime = 5d
maximal_queue_lifetime = 7d

Master process configuration:

# vi /usr/local/etc/postfix/master.cf

The master.cf file controls how Postfix processes different types of connections. By default, it includes configuration for SMTP (port 25), submission (port 587), and pickup services.

Virtual Domains

Postfix supports hosting multiple domains on a single server using virtual domains.

Set up virtual mailbox domains:

# Add to main.cf
virtual_mailbox_base = /var/vmail
virtual_mailbox_domains = hash:/usr/local/etc/postfix/virtual_domains
virtual_mailbox_maps = hash:/usr/local/etc/postfix/virtual_mailbox
virtual_alias_maps = hash:/usr/local/etc/postfix/virtual_alias
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000
virtual_minimum_uid = 5000

Create virtual domains file:

# vi /usr/local/etc/postfix/virtual_domains
example.com    OK
example.org    OK

Create virtual mailbox file:

# vi /usr/local/etc/postfix/virtual_mailbox
user@example.com    example.com/user/
admin@example.com   example.com/admin/

Create virtual alias file:

# vi /usr/local/etc/postfix/virtual_alias
webmaster@example.com    admin@example.com
postmaster@example.com   admin@example.com

Compile the hash databases:

# postmap /usr/local/etc/postfix/virtual_domains
# postmap /usr/local/etc/postfix/virtual_mailbox
# postmap /usr/local/etc/postfix/virtual_alias

Create the dedicated virtual-mail account and directory:

# pw groupadd vmail -g 5000
# pw useradd vmail -u 5000 -g vmail -d /var/vmail -s /usr/sbin/nologin
# install -d -o vmail -g vmail -m 0750 /var/vmail/example.com/user
Starting Postfix

Enable Postfix at boot:

# sysrc postfix_enable=YES

Start Postfix:

# service postfix start

Check Postfix status:

# service postfix status
# postfix status

View mail queue:

# postqueue -p
# mailq

Flush the mail queue:

# postqueue -f

Reload configuration after changes:

# postfix reload

Local Delivery Agents

Procmail

Procmail is a versatile local delivery agent (LDA) that can filter, sort, and process incoming mail based on flexible rules. It is commonly used with Sendmail or Postfix for mail filtering.

Installation

Install Procmail from mports:

# mport install procmail
Configuration

Procmail uses .procmailrc files in users' home directories to define filtering rules.

Global procmail configuration:

# vi /usr/local/etc/procmailrc

Configure MTA to use Procmail for local delivery:

Basic user .procmailrc:

# Set default mailbox location
MAILDIR=$HOME/Maildir
DEFAULT=$MAILDIR/

# Log file location
LOGFILE=$HOME/.procmail.log

# Verbose logging (optional)
VERBOSE=off
Recipe Examples

Simple filtering by subject:

:0
* ^Subject:.*spam
/dev/null

Forward specific emails:

:0
* ^From:.*important@client.com
! backup@example.com

Deliver to different folders based on sender:

:0
* ^From:.*family-member@
$MAILDIR/family/

:0
* ^From:.*work@
$MAILDIR/work/

:0
* ^List-Id:.*midnightbsd-users
$MAILDIR/lists/midnightbsd/

Pipe mail to a script:

:0
* ^Subject:.*backup report
| /usr/local/bin/process-backup-report.sh

Automatic vacation reply:

:0 Wh
* !^FROM_DAEMON
* !^X-Loop: myaddress@myhost
* !^FROM: myaddress@myhost
| (formail -r -A "X-Loop: myaddress@myhost"; \
   echo "I am on vacation until January 1. I will read your mail when I return.") | \
  /usr/sbin/sendmail -t

Spam filtering with SpamAssassin:

:0fw
| /usr/local/bin/spamc

:0
* ^X-Spam-Level: \*\*\*\*
$MAILDIR/spam/

Mail Retrieval

Dovecot

Dovecot is a modern, secure IMAP and POP3 server that works well with both Sendmail and Postfix. It supports various mailbox formats and provides excellent performance.

Installation

Install Dovecot from mports:

# mport install dovecot

Install Dovecot with MySQL support (for virtual users):

# cd /usr/mports/mail/dovecot
# make config       # Select the MYSQL database option
# make install clean
Configuration

Main configuration:

# vi /usr/local/etc/dovecot/dovecot.conf

Basic dovecot.conf:

# OS specific configuration
!include conf.d/*.conf

# Protocols to enable
protocols = imap pop3

# Listen on all interfaces
listen = *

# CA-issued SSL certificate and key
ssl_cert = </usr/local/etc/letsencrypt/live/mail.yourdomain.com/fullchain.pem
ssl_key = </usr/local/etc/letsencrypt/live/mail.yourdomain.com/privkey.pem
ssl_min_protocol = TLSv1.2

# Mail location
mail_location = maildir:~/Maildir

# User and group
mail_uid = vmail
mail_gid = vmail

# First valid UID and GID
first_valid_uid = 1000
first_valid_gid = 1000

# Authentication
!include auth-system.conf.ext
!include auth-passwdfile.conf.ext

Authentication configuration for system users:

# vi /usr/local/etc/dovecot/conf.d/10-auth.conf

auth_mechanisms = plain login

# System users authentication
!include auth-system.conf.ext

For virtual users with passwd-file:

# vi /usr/local/etc/dovecot/conf.d/auth-passwdfile.conf.ext

passdb {
  driver = passwd-file
  args = scheme=BLF-CRYPT username_format=%u /usr/local/etc/dovecot/users
}

userdb {
  driver = passwd-file
  args = username_format=%u /usr/local/etc/dovecot/users
}

Create users file:

# vi /usr/local/etc/dovecot/users
user1:{BLF-CRYPT}hashedpassword:5000:5000::/var/vmail/example.com/user1::
user2:{BLF-CRYPT}hashedpassword:5000:5000::/var/vmail/example.com/user2::

Generate password hash:

# doveadm pw -s BLF-CRYPT
Enter new password:
Retype new password:
{BLF-CRYPT}hashedstring

Configure mail location for virtual users:

# vi /usr/local/etc/dovecot/conf.d/10-mail.conf

mail_location = maildir:/var/vmail/%d/%n
mail_uid = vmail
mail_gid = vmail
SSL/TLS Setup

Install a publicly trusted certificate:

Use a CA-issued certificate whose subject covers the public mail hostname. Self-signed certificates are appropriate only for isolated test systems where the issuing certificate is explicitly trusted by every client.

# chmod 600 /usr/local/etc/letsencrypt/live/mail.yourdomain.com/privkey.pem
# openssl x509 -in /usr/local/etc/letsencrypt/live/mail.yourdomain.com/fullchain.pem \
    -noout -dates -issuer -subject

Configure SSL in dovecot.conf:

ssl = required
ssl_cert = </usr/local/etc/letsencrypt/live/mail.yourdomain.com/fullchain.pem
ssl_key = </usr/local/etc/letsencrypt/live/mail.yourdomain.com/privkey.pem
ssl_min_protocol = TLSv1.2

Enable SSL ports (IMAPS on 993, POP3S on 995):

# vi /usr/local/etc/dovecot/conf.d/10-master.conf

service imaps {
  inet_listener imaps {
    port = 993
    ssl = yes
  }
}

service pop3s {
  inet_listener pop3s {
    port = 995
    ssl = yes
  }
}

Enable Dovecot:

# sysrc dovecot_enable=YES
# service dovecot start

Verify Dovecot is running:

# service dovecot status
# dovecot --version

Security and Filtering

rspamd

rspamd (Real-time Spam Protection And Mail Delivery) is a modern spam filtering system that uses a variety of techniques including statistical analysis, DNS blacklists, and custom rules. It is designed to be fast, efficient, and easy to integrate with your mail server.

Install rspamd from mports:

# mport install rspamd

Set local action thresholds:

# vi /usr/local/etc/rspamd/local.d/actions.conf

reject = 15;
add_header = 6;
greylist = 4;

Rspamd's packaged module defaults remain active unless they are overridden in /usr/local/etc/rspamd/local.d/. Validate changes with rspamadm configtest.

Configure rspamd to work with ClamAV for virus scanning:

# vi /usr/local/etc/rspamd/local.d/antivirus.conf

clamav {
    type = "clamav";
    servers = "127.0.0.1:3310";
    action = "reject";
    symbol = "CLAM_VIRUS";
}

Start rspamd:

# sysrc rspamd_enable=YES
# service rspamd start

Enable rspamd's milter proxy on loopback:

# /usr/local/etc/rspamd/local.d/worker-proxy.inc
bind_socket = "127.0.0.1:11332";
milter = yes;
timeout = 120s;

upstream "local" {
    default = yes;
    self_scan = yes;
}

Connect Postfix to the local milter:

# Add to /usr/local/etc/postfix/main.cf
smtpd_milters = inet:127.0.0.1:11332
non_smtpd_milters = inet:127.0.0.1:11332
milter_protocol = 6
milter_default_action = tempfail

ClamAV

ClamAV is an open-source antivirus engine designed for detecting trojans, viruses, malware, and other malicious threats. It can be integrated with your mail server to scan incoming and outgoing email.

Install ClamAV from mports:

# mport install clamav

Update virus definitions:

# freshclam

Configure freshclam to run periodically:

# vi /usr/local/etc/freshclam.conf

# Enable automatic updates
DatabaseMirror database.clamav.net

# Run as clamav user
DatabaseOwner clamav

# Number of database updates per day
Checks 24

# Log freshclam activity
LogSyslog yes
LogFacility LOG_LOCAL6

Configure clamd:

# vi /usr/local/etc/clamd.conf

# Comment out Example line
#Example

# Log file
LogSyslog yes
LogFacility LOG_LOCAL6

# Pid file
PidFile /var/run/clamav/clamd.pid

# Database directory
DatabaseDirectory /var/db/clamav

# Listen only on loopback so rspamd can submit scans
TCPSocket 3310
TCPAddr 127.0.0.1

# User and group
User clamav

Start ClamAV:

# sysrc clamav_clamd_enable=YES
# sysrc clamav_freshclam_enable=YES
# service clamav_clamd start
# service clamav_freshclam start

Test ClamAV:

# clamscan --version
# clamscan -r /usr/local/etc/postfix

With the rspamd antivirus module configured above, Postfix mail is scanned through the rspamd milter; a separate Postfix content-filter transport or reinjection script is not required.

SpamAssassin

SpamAssassin is a powerful spam filtering system that uses a variety of mechanisms including header and text analysis, Bayesian filtering, DNS blocklists, and collaborative filtering databases.

Install SpamAssassin from mports:

# mport install spamassassin

Enable SpamAssassin:

# sysrc sa-spamd_enable=YES
# service sa-spamd start

Configure SpamAssassin:

# vi /usr/local/etc/mail/spamassassin/local.cf

# Required score to flag as spam
required_score 5.0

# Required score to reject
required_hits 6.0

# Rewrite subject for spam
rewrite_header Subject **** SPAM _SCORE_ ***

# Add report to message
report_safe 1

# Enable Bayesian filtering
use_bayes 1
bayes_auto_learn 1
bayes_path /var/db/spamassassin/bayes

# Enable network tests
skip_rbl_checks 0

# Custom rules
header MY_CUSTOM_RULE  Subject =~ /Free Viagra/i
score MY_CUSTOM_RULE 5.0

Integrate SpamAssassin with Postfix:

# Add to /usr/local/etc/postfix/main.cf
smtp_milter_connect_macros = i j {daemon_name} v {if_name} _
smtp_milter_macros = i j {tls_version} {cipher} {cipher_bits} {cert_issuer} {cert_subject}
milter_default_action = accept
milter_protocol = 2
smtp_milter_command_timeout = 30

# Add to /usr/local/etc/postfix/master.cf
smtp       inet  n       -       n       -       -       smtpd
  -o milter_macro_daemon_name=ORIGINATING

# Add spamassassin milter
127.0.0.1:783 inet    n       -       n       -       -       smtpd
  -o milter_macro_daemon_name=ORIGINATING

Integrate SpamAssassin with Procmail:

# Add to user's .procmailrc
:0fw
| /usr/local/bin/spamc

:0
* ^X-Spam-Level: \*\*\*\*
$MAILDIR/spam/

:0
* ^X-Spam-Status: Yes
$MAILDIR/spam/

Update SpamAssassin rules:

# sa-update

Run SpamAssassin in test mode:

# spamassassin -t < /path/to/test-message.eml

Check SpamAssassin logs:

# tail -f /var/log/maillog | grep spam

Complete Server Example

This section provides a baseline example using Postfix, Dovecot, rspamd, ClamAV, and SpamAssassin. Test and adapt it for your DNS, certificates, users, firewall, and delivery policy before production use.

Step 1: Install all required packages

# mport install postfix dovecot rspamd clamav spamassassin

Step 2: Configure networking

Ensure your server has proper DNS records:

Step 3: Configure Postfix

Edit /usr/local/etc/postfix/main.cf:

myhostname = mail.yourdomain.com
mydomain = yourdomain.com
myorigin = $mydomain
inet_interfaces = all
mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain
mynetworks = 127.0.0.0/8, [::1]/128, 192.168.1.0/24

# Relay restrictions
smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination

# TLS configuration
smtpd_use_tls = yes
smtpd_tls_cert_file = /etc/ssl/certs/postfix.pem
smtpd_tls_key_file = /etc/ssl/private/postfix.key
smtpd_tls_security_level = may

# SASL authentication
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
smtpd_sasl_security_options = noanonymous

# Virtual mailbox domains
virtual_mailbox_base = /var/vmail
virtual_mailbox_domains = hash:/usr/local/etc/postfix/virtual_domains
virtual_mailbox_maps = hash:/usr/local/etc/postfix/virtual_mailbox
virtual_alias_maps = hash:/usr/local/etc/postfix/virtual_alias
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000
virtual_minimum_uid = 5000

# Milter for spam/virus filtering (rspamd listens only on loopback)
smtpd_milters = inet:127.0.0.1:11332
non_smtpd_milters = inet:127.0.0.1:11332
milter_default_action = tempfail
milter_protocol = 6

Step 4: Configure Dovecot

Edit /usr/local/etc/dovecot/dovecot.conf:

protocols = imap pop3
listen = *

# SSL
ssl = required
ssl_cert = </usr/local/etc/letsencrypt/live/mail.yourdomain.com/fullchain.pem
ssl_key = </usr/local/etc/letsencrypt/live/mail.yourdomain.com/privkey.pem
ssl_min_protocol = TLSv1.2

# Mail location for virtual users
mail_location = maildir:/var/vmail/%d/%n
mail_uid = vmail
mail_gid = vmail

# SASL for Postfix
service auth {
  unix_listener /var/spool/postfix/private/auth {
    mode = 0660
    user = postfix
    group = postfix
  }
}

Step 5: Configure rspamd

Configure /usr/local/etc/rspamd/local.d/worker-proxy.inc:

bind_socket = "127.0.0.1:11332";
milter = yes;
timeout = 120s;
upstream "local" {
    default = yes;
    self_scan = yes;
}

Step 6: Start all services

# sysrc postfix_enable=YES
# sysrc dovecot_enable=YES
# sysrc rspamd_enable=YES
# sysrc clamav_clamd_enable=YES
# sysrc clamav_freshclam_enable=YES
# sysrc sa-spamd_enable=YES

# service postfix start
# service dovecot start
# service rspamd start
# service clamav_clamd start
# service clamav_freshclam start
# service sa-spamd start

Step 7: Test the setup

# telnet localhost 25
# EHLO test
# MAIL FROM:<test@yourdomain.com>
# RCPT TO:<user@yourdomain.com>
# DATA
# Subject: Test
# 
# Test message
# .
# QUIT

# Test IMAP
# telnet localhost 143

# Check logs
# tail -f /var/log/maillog

Step 8: Enable submission port (587) for authenticated sending

Edit /usr/local/etc/postfix/master.cf:

submission inet n       -       n       -       -       smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING

Then reload Postfix:

# postfix reload

Troubleshooting

Mail is not being delivered:

Authentication failures with Dovecot:

Spam filtering not working:

Virus scanning not working:

Connection refused errors:

Common error messages:

# 451 Temporary local problem - please try later
#   → Usually a permissions issue or service not ready

# 550 Relay not permitted
#   → Check mynetworks or authentication configuration

# 550 No such user
#   → Check virtual user maps or system user existence

# Connection timed out
#   → Check firewall, network connectivity, or service status

Performance issues:

Debugging tools:

Log analysis:

# Show recent mail log entries
# tail -100 /var/log/maillog

# Filter for errors
# grep -i error /var/log/maillog

# Filter for specific service
# grep postfix /var/log/maillog
# grep dovecot /var/log/maillog
# grep rspamd /var/log/maillog

# Real-time log monitoring
# tail -f /var/log/maillog | grep -E "(postfix|dovecot|rspamd|clamav)"