Internet Protocols · Email Protocols

MX Resolution, Preference Ordering, and Null MX

How a sending server turns a domain into a list of hosts, why the preference values are ordered the way they are, and what an empty MX list asserts.

Before a message can be sent, the sending MTA has to turn a domain name into a host to connect to. The mechanism is a DNS record type designed for exactly that, and its details (the preference value, the absence of address records in the answer, the fallback when the record is missing) determine behaviour that is easy to get wrong and hard to diagnose from the outside.

What an MX record contains

An MX record maps a domain to a mail exchanger host and a 16-bit preference value. The record type was defined alongside the original DNS specification and carries no other semantics: RFC 1035 gives the RDATA as a two-octet preference followed by a domain name.

A lookup for example.com of type MX returns records like:

example.com.    3600  IN  MX  10  mx1.example.com.
example.com.    3600  IN  MX  20  mx2.example.com.
example.com.    3600  IN  MX  10  mx3.example.net.

Three properties of that answer matter.

The exchange host is a name, not an address. A sender that gets this answer must perform a second lookup, A or AAAA, for each exchanger before it can connect. This indirection is deliberate: it lets a domain delegate its mail service to a provider, and it lets the provider change addresses without the domain changing its records. It also means the answer to an MX query is never sufficient to connect, and a resolver that returns the MX list without resolving the exchanges has done only half the work.

The preference values are relative, not absolute. Lower is preferred. There is no reserved range and no meaning to the specific numbers beyond their ordering; a domain can use 0, 10, 20 or 1, 2, 3 or 100, 200, 300 with identical effect. The convention of spacing values by ten leaves room to insert a new exchanger between existing ones without renumbering, which is the only reason the spacing exists.

Equal preference values mean the senders may choose among them. The specification does not require a specific selection rule, and the practical effect is that a sender can use randomization or a hash of the message to spread load. Two exchangers with preference 10 are a load-sharing pair; preference 10 and 20 are a primary and a fallback. The distinction is entirely in the numbers, and a domain that intends a primary and a backup but gives both the same preference gets load sharing instead.

The fallback when there is no MX

A domain with no MX record is still expected to receive mail. RFC 5321 specifies that if the MX lookup returns no records, the sender treats the domain name itself as the mail exchanger, with an implicit preference of zero, and looks up its address records.

That rule exists because it was true before MX records were widely deployed: a host that accepted mail for itself published an A record and nothing else. The fallback preserves compatibility with that arrangement. It also creates a security-relevant ambiguity, because a domain that has an A record for a web server and no MX record will receive mail at the web server’s address. If the host is not running an MTA, the connection is refused, and the sender retries until the message expires.

The interaction with wildcard DNS is the failure mode. A domain with a wildcard A record and no MX records has an implicit mail exchanger for every name under it, including names that were never meant to accept mail. A sender looking up anything.example.com gets an address, connects, and either finds no SMTP service or finds one that accepts the connection and rejects the recipient. The first is a connection failure that looks like a network problem; the second is a policy rejection that looks like a nonexistent mailbox. Neither is what the domain operator intended.

The null MX and what it asserts

RFC 7505 adds a way to say explicitly that a domain accepts no mail: a single MX record whose exchange is the root name, conventionally written as a single dot, with preference zero.

example.com.    3600  IN  MX  0  .

The semantics are an assertion, not a configuration. A sender that sees this record must treat the domain as not accepting mail and fail the delivery permanently, without falling back to the A record. That is the whole point: the record removes the ambiguity of the fallback rule, so a domain that has address records for other purposes can state that mail is not one of them.

The null MX is most useful for domains that exist only to be reserved. A domain registered defensively so nobody else can use the name can publish a null MX and be done; senders get a clean permanent failure instead of connecting to a web server. It is also useful for subdomains that appear in addresses by accident, and for parked domains.

The record is single and exclusive. A zone that publishes a null MX alongside a real MX is malformed, and senders differ in how they resolve it. A zone with more than one record and one of them null is not a valid null MX configuration; the correct form is exactly one record with preference zero and a null exchange.

Ordering, retrying, and the cost of the list

The sender’s algorithm after a successful lookup is a loop over exchangers in preference order, with a per-host retry policy inside the per-message retry policy.

For each distinct preference value, in ascending order, the sender attempts the hosts at that preference. If all hosts at one preference fail with a transient error, the sender may move to the next preference value within the same delivery attempt, or it may wait for the next retry. RFC 5321 does not mandate one behaviour; the practical difference is whether a message is delayed by a primary that is down when a secondary is up.

Two costs shape the choice. Trying every exchanger in one attempt means a message to a domain with five unreachable hosts waits for five connection timeouts before the attempt is recorded as failed, and each timeout may be tens of seconds. Trying only the first and waiting means the message sits in the queue for the full retry interval even though a working exchanger was available immediately. Deployed senders usually try each preference level in turn within an attempt, with a short per-host timeout, and stop at the first host that accepts the message.

The address lookup for each exchanger adds another failure mode. An exchanger name that resolves to both A and AAAA records gives the sender a choice of address families; a host that is reachable over IPv4 and not over IPv6 produces a connection failure that the sender must interpret as a per-host failure rather than a per-domain failure. Happy-eyeballs-style parallel connection attempts reduce the delay but complicate the accounting, because a failure on one family must not be attributed to the domain.

Caching interacts with all of this. MX records have a TTL, and the address records for the exchangers have their own. A domain that changes its MX target during a TTL window has mail in flight to the old target, which may still accept it or may reject it. A domain that removes an exchanger from its list cannot retract messages already queued against it. The queue entry, described in Queue Management and Retry Scheduling in MTAs, holds the destination name and re-resolves it on each attempt, which is the only reason a changed record eventually takes effect.

Loop detection and the implicit-host trap

MX records can point at each other. A domain whose MX is another domain that has no MX record falls back to that domain’s A record, which is legal and common. A domain whose MX points at itself is also legal, and is how a host that is its own mail exchanger is configured.

The loop that matters is not in the records but in the delivery path. If a.example has MX mx.a.example and mx.a.example has no MX record, the fallback makes mx.a.example its own exchanger, which is consistent. If a.example has MX b.example and b.example has MX a.example, both lookups succeed and both hosts may be running an MTA that accepts mail for the other, producing a forwarding loop that the protocol cannot detect. The Received header count is the only signal, and it is unauthenticated.

A second trap is the implicit host applied to a name that also has an MX record pointing elsewhere. The fallback applies only when there is no MX record at all; a domain with an MX record whose target is unreachable does not fall back to its own A record. Senders that implement the fallback as “try MX, then try the domain” rather than “use MX if present, else use the domain” produce a delivery path the domain operator never configured.

The resolution result is also the input to authentication decisions downstream. A message from a domain whose MX list is a shared provider is indistinguishable, at the DNS level, from a message from any other customer of that provider. The distinction is made by the authentication records published under the domain, which are the subject of SPF Evaluation and Its Ten-Lookup Budget.

References

  1. RFC 5321: Simple Mail Transfer Protocol — IETF
  2. RFC 1035: Domain Names - Implementation and Specification — IETF
  3. RFC 7505: A Null MX No Service Resource Record for Domains That Accept No Mail — IETF