Module 5 · Lesson 1
MX Records and Mail Routing
⏱ 12 min read
MX Records and Mail Routing
Before any email gets delivered, a sending server has to answer one question: where do I connect to? That answer comes from the MX record — Mail Exchanger. Get it wrong and mail bounces. Point it at a CNAME and you've violated RFC 5321 and introduced a failure mode that will show up at the worst possible time.
The Structure of an MX Record
An MX record has two fields: a priority (also called preference) and a hostname.
example.com. 3600 IN MX 10 mail1.example.com.
example.com. 3600 IN MX 20 mail2.example.com.
The priority is a number. Lower is preferred. A sending MTA will try the lowest-priority record first, fall back to the next if the connection fails, and so on.
Query it with dig:
dig MX example.com
Or with short output:
dig MX example.com +short
Output:
10 mail1.example.com.
20 mail2.example.com.
Priority and Failover
Priorities don't need to be 10 and 20 — you can use any integers. Spacing them out by 10 gives you room to insert additional records later without renumbering everything. Common conventions: 10/20, 5/10/15, 1/5/10.
When two records share the same priority, the sending MTA picks one at random. This is load balancing, not failover. If you want failover (try A first, only use B if A is down), give them different priorities.
Failover matters more than most people realize. Suppose your primary mail server is at priority 10, and you have a backup at priority 20. If the primary goes offline, well-configured sending servers will try the backup. "Well-configured" is doing a lot of work in that sentence — some sending servers won't try lower priority hosts, or will only retry after long delays. Don't rely on MX failover as a substitute for a reliable primary.
The CNAME Rule: Never Point MX to a CNAME
This comes up constantly. RFC 5321 is clear: the hostname in an MX record must resolve to an A or AAAA record directly. It must not be a CNAME.
If you do this:
; Wrong. Don't do this.
example.com. IN MX 10 mail.example.com.
mail.example.com. IN CNAME hosting-provider.example.net.
Some MTAs will follow the CNAME chain anyway. Others will fail. Either way, you've introduced undefined behavior into your mail routing. The spec says no CNAMEs. Follow the spec.
The fix is simple: point the MX record to a hostname that has its own A or AAAA record.
example.com. IN MX 10 mail.example.com.
mail.example.com. IN A 203.0.113.42
What Happens When MX Is Misconfigured
No MX record at all: Some sending servers will fall back to the A record of the domain itself (per RFC 5321, section 5). Some won't. Depending on A-record fallback is not a configuration strategy.
MX pointing to a nonexistent hostname: The sending server gets NXDOMAIN when it tries to look up the A record. The delivery attempt fails. Depending on the sender's retry policy, they may try again later or bounce immediately.
MX pointing to the domain itself: example.com. IN MX 10 example.com. — This creates a mail loop if your web server isn't running an MTA, or delivers to the web server's mail queue if it is. Either way, not what you intended.
Wrong priority causing unexpected routing: If you set up a honeypot or test server at a low priority number, it becomes the primary. Priority 1 beats priority 10.
Temporary propagation issues after TTL change: You updated the MX record, but the old TTL was 86400. Senders cached the old value. Mail is still going to the old server for up to 24 hours. This is why you lower the TTL before making changes.
Null MX: For Domains That Don't Accept Email
If you own a domain that exists only for a website, or as a brand protection registration, it should have a Null MX record. This tells sending servers explicitly: this domain does not accept email. Don't try.
RFC 7505 defines the Null MX:
noemail.example.com. IN MX 0 .
Priority 0, hostname . (the DNS root). A sending MTA that receives this will immediately bounce rather than wasting time attempting connections to nonexistent mail servers.
Without a Null MX, senders trying to deliver to your domain will either fall back to the A record (and get a connection refused) or spend time on DNS lookups before bouncing. Neither is good behavior. The Null MX is a clean signal.
Set a Null MX on every domain that doesn't accept email. It takes 30 seconds.
Looking Up Real MX Records
Some real-world examples to run yourself:
# Gmail
dig MX gmail.com +short
# Likely output:
# 5 gmail-smtp-in.l.google.com.
# 10 alt1.gmail-smtp-in.l.google.com.
# 20 alt2.gmail-smtp-in.l.google.com.
# 30 alt3.gmail-smtp-in.l.google.com.
# 40 alt4.gmail-smtp-in.l.google.com.
# Microsoft 365
dig MX yourdomain-com.mail.protection.outlook.com +short
# Returns a single MX record pointing to Microsoft's inbound servers
# Check what your domain currently has
dig MX yourdomain.com +short
The +short flag strips the DNSSEC and TTL noise, leaving just what you need.
Key Takeaways
- MX records have two fields: priority (lower = preferred) and hostname.
- Multiple MX records at different priorities provide failover.
- MX records must point to hostnames with A/AAAA records. Never a CNAME.
- Misconfigured MX means mail bounces, silently routes to the wrong place, or relies on undocumented fallback behavior.
- Set a Null MX (
0 .) on every domain that doesn't accept email. - Lower your TTL before making MX changes. High TTLs mean long propagation windows.
Further Reading
- RFC 5321 — Simple Mail Transfer Protocol (section 5 covers MX lookup behavior)
- RFC 7505 — A "Null MX" No Delivery Resource Record for Domains That Accept No Mail
- RFC 974 — Mail Routing and the Domain System (the original 1986 spec, worth reading for historical context)
Up Next
Lesson 02 covers DANE and MTA-STS: two ways to make sure the connection to your mail server uses a verified TLS certificate, not just opportunistic encryption that anyone can intercept.