DNS for Mail

Running a mail server requires a proper DNS records.

Before you begin

This guide assumes that you have already set up a properly functioning name server using nsd. If you have not already, you will want to read up on basic DNS concepts and set up your name server.

Adding to the zone file

For mail, you will need to add DNS records. Let's take a look at a sample zone file containing only what is needed to handle mail:

$ORIGIN and Start of Authority (SOA) record:

$ORIGIN example.com.
example.com.     3600   SOA   ns1.example.com. admin.example.com. (
                            2021050302   ; serial YYYYMMDDnn
                            1800        ; refresh
                            3600         ; retry
                            86400       ; expire
                            3600 )      ; minimum TTL

Here we define the $ORIGIN to be example.com. The $ORIGIN will be appended to every record to produce a fully qualified domain name. Make sure to read up on FQDN if you do not understand what that means.

The Start of Authority record? says that the serial number was last updated on May 3rd, 2021; that the refresh interval is 1800 seconds, the retry interval is 3600 seconds, the record expires after 1 day, and the minimum time to live is 3600 seconds.

        3600    IN      MX      10 mail
        3600    IN      A
        3600    IN      AAAA    2602:fccf:1:143::
        3600    IN      NS      ns1
        3600    IN      NS      ns2
mail    3600    IN      A
        3600    IN      AAAA    2602:fccf:1:143::
pop     3600    IN      A
        3600    IN      AAAA    2602:fccf:1:143::
imap    3600    IN      A
        3600    IN      AAAA    2602:fccf:1:143::
smtp    3600    IN      A
        3600    IN      AAAA    2602:fccf:1:143::

When there is no name for the record, it just takes on the value of $ORIGIN: example.com.

Line 1 defines the mail exchange (MX) record for example.com. When another mail server sends your server mail, it will perform two DNS queries. First, it asks what your MX record is for example.com:

$ dig +short -t mx example.com
10 mail.example.com.

Here, the MX record for example.com is mail.example.com with a value of 10. This means that mail.example.com is the actual mail server that will handle mail.

Once an MX record is returned, the mail server will find the A/AAAA record for that mail server:

$ dig +short -t a mail.example.com

Normally, a domain will have multiple MX records so that if one mail server goes offline, another can continue serving mail. Most mail servers will choose the MX record with the lowest value to deliver to first.

SPF record

You'll want to add a TXT record in your domain's DNS zone for SPF:

        3600    IN      TXT     "v=spf1 mx -all"

This simple SPF record allows any mail exchange (MX) server for the domain to send mail, but no others.

DMARC records

_dmarc  3600   IN      TXT     "v=DMARC1;p=none;pct=0;fo=1;rua=mailto:postmaster@example.com;ruf=mailto:postmaster@example.com"

This record will provide you with reports for DKIM/SPF but will not filter any mail. It's useful for diagnosing problems with your configuration.

DKIM records

You will need to follow the instructions for creating a proper DKIM record:

First, you will need to create a public and private DKIM key:

$ openssl genrsa -out private.key 1024
$ openssl rsa -in private.key -pubout -out public.key
$ chmod og-rwx private.key
$ chmod og-wx public.key
$ chmod u-w public.key private.key
$ doas mkdir -m 770 /etc/mail/dkim
$ doas mv private.key public.key /etc/mail/dkim/
$ doas chown -R _dkimsign:_dkimsign /etc/mail/dkim/

We then create a DKIM record by taking the public key, removing the first and last line, then joining all the lines together:

$ doas cat /etc/mail/dkim/public.key | awk '/-----/{if (NR!=1)print "";next}{printf $0}' -

Running this command on public.key should produce text like the following:


This key should go into the DKIM DNS records to replace <public key>:

_adsp._domainkey   86400   IN      TXT     "dkim=discardable;"
mail._domainkey   86400   IN      TXT     "k=rsa; t=s; p=<public key>"

The final result should look like this:

_adsp._domainkey   86400   IN      TXT     "dkim=discardable;"
mail._domainkey    86400   IN      TXT     "k=rsa; t=s; p=8AMIIBCgKCAQEAyBhtr90v64hQTfw1sUtFPg5bYXF/SxUTNMziGJMql81av47DG+cDEPmQW0XN8+Tb8yIwenh01hZ5Xh1gjWg1v8OIrnErf3482B8XRZykHJQUdjcALnZ9gGZ9CnzAhIC3TsAnTDSHdgk3c0oqJeilriW0EIAkV2+x1jWlPunGJgJT/bSc2rzZsZv2gZmrrR+2f4aK7xTamAyFUl+cSP/kcoHbEmvXEOtqTQZTTDhxM6BKELUO0xBBhlrsq8C3q92OqZtwflK+IbJDyQPndORMR7R4itIj6O+LMFlYziPitM4egw3KADLZSlycJuTLkhCG5b/3VHFy+uUn3kQc+/s17QIDAQAB"

Note: the _adsp records come from RFC5617 which was marked as historic in 2013. More testing is necessary to determine if these records are really needed.


dnswl is a DNS whitelist that is free of charge, so you should sign up for it.