Email Server ConfigurationSetting 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.
A complete email server typically consists of several components working together:
mail.localTypical mail flow: Incoming mail → MTA → Spam/Virus Filter → LDA → Mailbox ← MRA ← Email Client
MidnightBSD includes several mail-related utilities in the base system, inherited from FreeBSD and DragonFly BSD:
/usr/sbin/sendmail - The traditional Sendmail binary (often a wrapper)/usr/libexec/mail.local - Local mail delivery agent/usr/libexec/mailwrapper - Wrapper for switching between MTAs/usr/bin/mail - Command-line mail client/usr/bin/mailq - View the mail queueThe 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:
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.
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.
Sendmail is the traditional Unix MTA and is available in mports. It is feature-rich but has a reputation for complex 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
/usr/local/etc/mail/sendmail.mc - Main configuration macro file/usr/local/etc/mail/sendmail.cf - Compiled configuration (do not edit directly)/usr/local/etc/mail/access - Access control database (relay permissions)/usr/local/etc/mail/aliases - Aliases file (may override /etc/mail/aliases)/usr/local/etc/mail/virtusertable - Virtual user table/usr/local/etc/mail/local-host-names - Accepted hostnamesEnable 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 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.
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.
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.
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
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
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.
Install Procmail from mports:
# mport install procmail
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:
/etc/mail/mailer.conf or Sendmail configuration to use Procmail as the local delivery agentmailbox_command in main.cf:
mailbox_command = /usr/local/bin/procmail -a "$EXTENSION"
Basic user .procmailrc:
# Set default mailbox location MAILDIR=$HOME/Maildir DEFAULT=$MAILDIR/ # Log file location LOGFILE=$HOME/.procmail.log # Verbose logging (optional) VERBOSE=off
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/
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.
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
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
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
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 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 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
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.
# mport install postfix dovecot rspamd clamav spamassassin
Ensure your server has proper DNS records:
v=spf1 mx ~allEdit /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
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
}
}
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;
}
# 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
# 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
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
Mail is not being delivered:
mailq or postqueue -ptail -f /var/log/maillogservice postfix statusdig MX yourdomain.comtelnet localhost 25Authentication failures with Dovecot:
service dovecot statustail -f /var/log/dovecot.logtelnet localhost 143Spam filtering not working:
service rspamd statustail -f /var/log/rspamd.logrspamc check < test-message.emlVirus scanning not working:
service clamav_clamd statusfreshclamclamdscan /tmp/testfileConnection refused errors:
ipfw list or pfctl -srsockstat -l | grep portCommon 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:
top, vmstatmaster.cfDebugging tools:
telnet - Test SMTP/IMAP connections manuallyopenssl s_client - Test SSL/TLS connectionsdig, nslookup - Test DNS recordstraceroute, mtr - Test network connectivitytruss, ktrace - Trace system calls using base-system toolsLog 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)"