FreeBSD.software
Home/Guides/How to Send Email from FreeBSD Servers with DMA
tutorial·2026-04-09·11 min read

How to Send Email from FreeBSD Servers with DMA

Configure FreeBSD's built-in DMA (DragonFly Mail Agent) to send system emails via SMTP relay: Gmail, AWS SES, Mailgun setup, cron notification, and troubleshooting delivery.

How to Send Email from FreeBSD Servers with DMA

Every FreeBSD server needs to send email. Cron job failures, security alerts, ZFS scrub reports, and periodic maintenance notifications all generate mail. The question is how to deliver it reliably without running a full mail server.

DMA (DragonFly Mail Agent) is the answer. It ships in the FreeBSD base system since FreeBSD 14.0, replacing Sendmail as the default MTA. DMA is a lightweight, send-only mail transfer agent that relays outgoing email through an upstream SMTP server. It does not receive mail, does not run a listening daemon, and has a configuration file that is 5 lines long.

This guide covers configuring DMA on FreeBSD to send system mail through Gmail, AWS SES, Mailgun, and generic SMTP relays. It also covers cron notification setup, troubleshooting delivery issues, and common pitfalls.

Why DMA Over Sendmail or Postfix

Sendmail is powerful but complex. Its configuration syntax is notoriously difficult, it runs as a listening daemon by default (attack surface), and it is overkill for a server that only needs to send notifications. FreeBSD historically included Sendmail in the base system, but maintaining it for outbound-only use is unnecessary overhead.

Postfix is an excellent MTA for receiving and relaying mail, but it is a package dependency, runs multiple daemons, and requires significant configuration for what is fundamentally a simple task: "send this email through an SMTP relay."

DMA does one thing well: it accepts mail from local processes (cron, periodic, applications) and delivers it through an upstream SMTP server using TLS authentication. No listening ports. No daemon process. No complex configuration. It is invoked on demand by the mail submission path and exits when delivery is complete.

Prerequisites

  • FreeBSD 14.0 or later (DMA is in the base system)
  • An SMTP relay account (Gmail, AWS SES, Mailgun, or your organization's mail server)
  • Root access

Step 1: Verify DMA Is the Active Mailer

On FreeBSD 14.0+, DMA is the default. Verify:

sh
ls -la /usr/sbin/sendmail

This should be a symlink to /usr/libexec/dma or DMA should be configured in /etc/mail/mailer.conf:

sh
cat /etc/mail/mailer.conf

Expected output:

shell
sendmail /usr/libexec/dma mailq /usr/libexec/dma newaliases /usr/libexec/dma

If your system still uses Sendmail, switch to DMA:

sh
cat > /etc/mail/mailer.conf << 'EOF' sendmail /usr/libexec/dma mailq /usr/libexec/dma newaliases /usr/libexec/dma EOF # Disable Sendmail sysrc sendmail_enable="NO" sysrc sendmail_submit_enable="NO" sysrc sendmail_outbound_enable="NO" sysrc sendmail_msp_queue_enable="NO" service sendmail stop 2>/dev/null

Step 2: Configure DMA

DMA uses two configuration files:

  • /etc/dma/dma.conf -- Main configuration
  • /etc/dma/auth.conf -- SMTP authentication credentials

Generic SMTP Relay Configuration

sh
cat > /etc/dma/dma.conf << 'EOF' # SMTP relay server SMARTHOST smtp.example.com PORT 587 # Authentication AUTHPATH /etc/dma/auth.conf # TLS encryption SECURETRANSFER STARTTLS # Masquerade sender address MASQUERADE admin@example.com # Queue management DEFER FULLBOUNCE EOF

Set SMTP credentials:

sh
cat > /etc/dma/auth.conf << 'EOF' admin@example.com|smtp.example.com:YourSMTPPassword EOF chmod 640 /etc/dma/auth.conf chown root:mail /etc/dma/auth.conf

The format is user|server:password. The user must match the SMTP login username.

Test the Configuration

sh
echo "Test email from FreeBSD server $(hostname)" | mail -s "DMA Test" recipient@example.com

Check the DMA queue for stuck messages:

sh
ls -la /var/spool/dma/

An empty spool directory means all messages were delivered. If files remain, check /var/log/maillog for errors:

sh
tail -20 /var/log/maillog

Step 3: Gmail SMTP Configuration

Gmail requires an App Password if two-factor authentication is enabled (and it should be).

Generate a Gmail App Password

  1. Go to https://myaccount.google.com/apppasswords
  2. Select "Mail" and "Other (FreeBSD Server)"
  3. Copy the generated 16-character password

Configure DMA for Gmail

sh
cat > /etc/dma/dma.conf << 'EOF' SMARTHOST smtp.gmail.com PORT 587 AUTHPATH /etc/dma/auth.conf SECURETRANSFER STARTTLS MASQUERADE yourname@gmail.com EOF cat > /etc/dma/auth.conf << 'EOF' yourname@gmail.com|smtp.gmail.com:abcd efgh ijkl mnop EOF chmod 640 /etc/dma/auth.conf chown root:mail /etc/dma/auth.conf

Replace abcd efgh ijkl mnop with the App Password from Google (spaces included).

Test

sh
echo "Gmail test from $(hostname) at $(date)" | mail -s "FreeBSD DMA Test" recipient@example.com

Gmail Sending Limits

Gmail limits outgoing mail to 500 messages per day for regular accounts and 2,000 for Google Workspace. For a server sending cron notifications and alerts, this is more than enough. For bulk sending, use AWS SES or Mailgun.

Step 4: AWS SES Configuration

Amazon Simple Email Service is the most cost-effective option for high-volume transactional email.

Prerequisites

  1. An AWS account with SES configured
  2. A verified domain or email address in SES
  3. SMTP credentials generated in the SES console (these are different from IAM credentials)

Configure DMA for AWS SES

sh
cat > /etc/dma/dma.conf << 'EOF' SMARTHOST email-smtp.us-east-1.amazonaws.com PORT 587 AUTHPATH /etc/dma/auth.conf SECURETRANSFER STARTTLS MASQUERADE noreply@yourdomain.com EOF

Replace us-east-1 with your SES region.

sh
cat > /etc/dma/auth.conf << 'EOF' AKIAIOSFODNN7EXAMPLE|email-smtp.us-east-1.amazonaws.com:wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY EOF chmod 640 /etc/dma/auth.conf chown root:mail /etc/dma/auth.conf

The username is your SES SMTP username (starts with AKIA...), and the password is the SES SMTP password.

Verify Sender Domain

AWS SES requires verified sender addresses. The MASQUERADE address must match a verified identity in SES. In sandbox mode, recipient addresses must also be verified.

Move Out of SES Sandbox

New SES accounts start in sandbox mode (can only send to verified addresses). Request production access through the AWS console to send to any recipient.

Step 5: Mailgun Configuration

Mailgun provides a generous free tier and excellent deliverability.

sh
cat > /etc/dma/dma.conf << 'EOF' SMARTHOST smtp.mailgun.org PORT 587 AUTHPATH /etc/dma/auth.conf SECURETRANSFER STARTTLS MASQUERADE noreply@mg.yourdomain.com EOF cat > /etc/dma/auth.conf << 'EOF' postmaster@mg.yourdomain.com|smtp.mailgun.org:your-mailgun-smtp-password EOF chmod 640 /etc/dma/auth.conf chown root:mail /etc/dma/auth.conf

The username and password come from Mailgun's domain settings under SMTP credentials.

Step 6: Cron Job Notifications

FreeBSD's cron sends the output of failed jobs (or all jobs, depending on configuration) via email.

Configure Cron Email Recipient

Set the MAILTO variable in the crontab:

sh
crontab -e

Add at the top:

shell
MAILTO=admin@example.com MAILFROM=cron@yourdomain.com

All cron job output will now be emailed to admin@example.com.

Per-Job Email

Override the recipient for specific jobs:

shell
# Send disk alerts to the ops team MAILTO=ops@example.com 0 * * * * /usr/local/bin/disk-check.sh # Send backup reports to the admin MAILTO=admin@example.com 0 3 * * * /usr/local/bin/backup.sh

Suppress Successful Job Output

To only receive emails when jobs fail, redirect stdout and keep stderr:

shell
0 3 * * * /usr/local/bin/backup.sh > /dev/null

This suppresses normal output. Errors (stderr) still generate an email.

Step 7: FreeBSD periodic(8) Notifications

FreeBSD's periodic system (daily, weekly, monthly maintenance) generates reports that are emailed to root by default.

Configure periodic Email

Edit /etc/periodic.conf:

sh
cat >> /etc/periodic.conf << 'EOF' # Send periodic reports to admin daily_output="admin@example.com" weekly_output="admin@example.com" monthly_output="admin@example.com" # Security reports to a separate address daily_status_security_output="security@example.com" EOF

Mail Aliases

Configure /etc/aliases to redirect root's mail:

sh
cat > /etc/aliases << 'EOF' # Root email forwarding root: admin@example.com manager: admin@example.com postmaster: admin@example.com EOF # Rebuild the alias database (DMA uses this file directly) newaliases

Step 8: Sending Email from Scripts

Using mail(1)

sh
# Simple message echo "Backup completed successfully" | mail -s "Backup Report: $(hostname)" admin@example.com # Multi-line message mail -s "ZFS Scrub Report" admin@example.com << 'REPORT' ZFS scrub completed on $(hostname) Date: $(date) Pool status: $(zpool status) ARC statistics: $(sysctl kstat.zfs.misc.arcstats.hits kstat.zfs.misc.arcstats.misses) REPORT

Using mailx with Attachments

DMA works with mailx for sending attachments:

sh
# Send a log file as an attachment pkg install mailx echo "See attached log" | mailx -s "Server Log" -a /var/log/messages admin@example.com

From Shell Scripts

sh
#!/bin/sh # alert.sh -- send an alert email RECIPIENT="admin@example.com" SUBJECT="ALERT: $(hostname) - $1" BODY="$2" echo "$BODY" | mail -s "$SUBJECT" "$RECIPIENT"

Usage:

sh
/usr/local/bin/alert.sh "Disk Space Low" "Filesystem /var is 95% full on $(hostname)"

Integrating with ZFS Events

Create a ZFS Event Daemon (ZED) email script:

sh
# Ensure /etc/zfs/zed.d/zed.rc has: ZED_EMAIL_ADDR="admin@example.com" ZED_EMAIL_PROG="mail" ZED_NOTIFY_VERBOSE=1

ZED will email you when ZFS detects errors, scrubs complete, or resilvers finish.

Step 9: Sender Authentication (SPF, DKIM)

Even with a relay service, email deliverability depends on proper sender authentication.

SPF Record

Add an SPF record to your domain's DNS:

shell
yourdomain.com. IN TXT "v=spf1 include:_spf.google.com ~all"

For AWS SES:

shell
yourdomain.com. IN TXT "v=spf1 include:amazonses.com ~all"

For Mailgun:

shell
yourdomain.com. IN TXT "v=spf1 include:mailgun.org ~all"

DKIM

DKIM signing is handled by the relay service (Gmail, SES, Mailgun). Configure it in the relay provider's dashboard, not on the FreeBSD server. Add the DKIM DNS record they provide.

DMARC

Add a DMARC record for monitoring:

shell
_dmarc.yourdomain.com. IN TXT "v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com"

Start with p=none (monitor only), review reports, then tighten to p=quarantine or p=reject.

Troubleshooting

Email Stuck in the Queue

sh
# Check the DMA spool ls -la /var/spool/dma/ # View queued message details cat /var/spool/dma/M* # Check the mail log tail -50 /var/log/maillog

Common causes: wrong SMTP credentials, firewall blocking port 587, DNS resolution failure, or TLS certificate verification failure.

Authentication Failures

sh
# Verify credentials format in auth.conf cat /etc/dma/auth.conf # Format must be: user|server:password # Test SMTP connectivity manually openssl s_client -connect smtp.gmail.com:587 -starttls smtp

Type EHLO localhost after the connection establishes. A 250 response confirms SMTP connectivity.

TLS Certificate Errors

If DMA reports TLS errors:

sh
# Verify the CA certificate bundle exists ls -la /etc/ssl/cert.pem # Test TLS to the relay openssl s_client -connect smtp.gmail.com:587 -starttls smtp -CAfile /etc/ssl/cert.pem

If the certificate bundle is missing or outdated:

sh
pkg install ca_root_nss

Emails Arriving in Spam

Check sender authentication:

sh
# Verify SPF dig TXT yourdomain.com | grep spf # Verify DKIM (check with your relay provider) # Verify DMARC dig TXT _dmarc.yourdomain.com

Also verify that the MASQUERADE address in dma.conf matches a verified sender in your relay service.

Port 587 Blocked

Some hosting providers block outbound SMTP ports. Test connectivity:

sh
nc -zv smtp.gmail.com 587

If blocked, try port 465 (SMTPS) instead:

sh
# dma.conf SMARTHOST smtp.gmail.com PORT 465 AUTHPATH /etc/dma/auth.conf SECURETRANSFER # Remove STARTTLS -- port 465 uses implicit TLS

No /var/log/maillog

Ensure syslog is configured to log mail:

sh
grep mail /etc/syslog.conf

Expected line:

shell
mail.* /var/log/maillog

If missing, add it and restart syslog:

sh
echo 'mail.* /var/log/maillog' >> /etc/syslog.conf service syslogd restart

DMA Configuration Reference

| Directive | Purpose | Example |

|-----------|---------|---------|

| SMARTHOST | SMTP relay server | smtp.gmail.com |

| PORT | SMTP port | 587 |

| AUTHPATH | Path to credentials file | /etc/dma/auth.conf |

| SECURETRANSFER | Enable TLS | (no value) |

| STARTTLS | Use STARTTLS (port 587) | (no value) |

| MASQUERADE | Sender address | noreply@example.com |

| DEFER | Queue messages on failure | (no value) |

| FULLBOUNCE | Include original message in bounces | (no value) |

| MAILNAME | HELO hostname | server.example.com |

FAQ

Is DMA available on FreeBSD 13?

DMA is available as a package (pkg install dma) on FreeBSD 13, but it is not the default MTA. On FreeBSD 14.0+, DMA is in the base system and replaces Sendmail as the default. On FreeBSD 13, install it and update /etc/mail/mailer.conf manually.

Can DMA receive incoming email?

No. DMA is a send-only MTA. It does not listen on any ports and cannot accept incoming mail. For receiving email, use Postfix, OpenSMTPD, or a hosted email service.

How many emails can DMA queue?

DMA stores queued messages as individual files in /var/spool/dma/. There is no hard limit, but each message is a separate file. On a healthy system with a working relay, the queue should be empty. A growing queue indicates delivery problems.

Should I use port 587 (STARTTLS) or port 465 (SMTPS)?

Port 587 with STARTTLS is the current standard (RFC 6409). Port 465 with implicit TLS was deprecated but re-standardized (RFC 8314). Both work. Use 587 as the default; fall back to 465 if 587 is blocked.

Can I use DMA with Microsoft 365 / Outlook?

Yes. Use smtp.office365.com as the SMARTHOST, port 587, and authenticate with a valid Microsoft 365 account. Ensure the account has an Exchange Online license. Modern authentication (OAuth2) is not supported by DMA; use an app password or a service account with basic auth enabled.

How do I send email from a FreeBSD jail?

DMA works inside jails. Install DMA (or symlink it from the host's base if using thin jails), configure /etc/dma/dma.conf inside the jail, and ensure the jail has outbound network access on port 587.

What happens if the SMTP relay is down?

With the DEFER directive, DMA queues the message in /var/spool/dma/ and retries on the next invocation. DMA does not run a background queue runner; retries happen when the next email is sent or when you manually flush the queue with dma -q. For reliable delivery, add a cron job to flush the queue periodically:

sh
# Flush DMA queue every 5 minutes */5 * * * * root /usr/libexec/dma -q

Get more FreeBSD guides

Weekly tutorials, security advisories, and package updates. No spam.