How to check mx records
Run nslookup -type=MX mozilla.org 8.8.8.8 and read the preference number on each line. Lower wins, so preference 1 is tried first and preference 10 last. Equal numbers leave the choice to the sending server. Then confirm every exchanger resolves to an address and is not itself an alias.
Checker offline. Follow the manual steps below, they give the same answer.
Why check this
Run this before a mail provider swap goes live, and again on the staging sign-off of any release that sends mail to internal addresses. The failure it prevents is the one where the application sends fine, the SMTP log says accepted, and the mail lands at the previous provider because one of four MX records was never moved.
The check answers two questions. Which hosts accept mail for this domain, and in what order does a sender try them. It does not tell you that those hosts answer on port 25, and it does not tell you that mail reaching them is delivered to a mailbox. It is a routing read, not a delivery test.
Prerequisites
nslookup. Windows ships it, and the same command works fromcmd, from PowerShell and from a POSIX shell. The last argument is the resolver to ask.- Node 22 for steps 2 and 3. No package is needed, and the resolver is set in the script rather than inherited from the operating system.
- RFC 5321 section 5.1 for the preference rule and for the requirement that an MX target be a name with an address record.
Steps
- Step 1.
Read the MX set of a domain that publishes several.
nslookup -type=MX mozilla.org 8.8.8.8Non-authoritative answer: Server: dns.google Address: 8.8.8.8 mozilla.org MX preference = 1, mail exchanger = aspmx.l.google.com mozilla.org MX preference = 10, mail exchanger = aspmx3.googlemail.com mozilla.org MX preference = 5, mail exchanger = alt2.aspmx.l.google.com mozilla.org MX preference = 5, mail exchanger = alt1.aspmx.l.google.comFour records, printed in the order 1, 10, 5, 5. The print order carries no meaning. A sender tries
aspmx.l.google.comfirst because 1 is the lowest number, then either of the two records at 5, thenaspmx3.googlemail.com. - Step 2.
Sort by preference and validate each target in one pass. Save this as
mx.jsand runnode mx.js mozilla.org.const { Resolver } = require('node:dns'); const r = new Resolver(); r.setServers(['8.8.8.8']); const name = process.argv[2]; r.resolveMx(name, (err, recs) => { if (err) { console.log('MX ' + err.code); return; } recs.sort((a, b) => a.priority - b.priority); let i = 0; const next = () => { if (i >= recs.length) return; const m = recs[i++]; r.resolveCname(m.exchange, (ce, cn) => { r.resolve4(m.exchange, (ae, addrs) => { console.log( String(m.priority).padStart(3) + ' ' + m.exchange.padEnd(38) + ' cname=' + (ce ? ce.code : cn.join(',')) + ' a=' + (ae ? ae.code : addrs.length + ' addr') ); next(); }); }); }; next(); });1 aspmx.l.google.com cname=ENODATA a=1 addr 5 alt2.aspmx.l.google.com cname=ENODATA a=1 addr 5 alt1.aspmx.l.google.com cname=ENODATA a=1 addr 10 aspmx3.googlemail.com cname=ENODATA a=1 addrA healthy target has no CNAME and at least one address. Both columns say so here.
- Step 3.
Learn what the two defective shapes look like in the same columns. Save this as
mxt.jsand runnode mxt.js www.github.com _dmarc.mozilla.org aspmx.l.google.com.const { Resolver } = require('node:dns'); const r = new Resolver(); r.setServers(['8.8.8.8']); let i = 2; const next = () => { if (i >= process.argv.length) return; const n = process.argv[i++]; r.resolveCname(n, (ce, cn) => { r.resolve4(n, (ae, addrs) => { console.log(n.padEnd(30) + ' cname=' + (ce ? ce.code : cn.join(',')) + ' a=' + (ae ? ae.code : addrs.join(','))); next(); }); }); }; next();www.github.com cname=github.com a=140.82.121.4 _dmarc.mozilla.org cname=ENOTFOUND a=ENODATA aspmx.l.google.com cname=ENODATA a=142.251.127.27The first line is an alias. An MX record whose target looks like that is invalid, because RFC 5321 requires the target to be a name with an address record, not a name that redirects. The second line is a name with no address at all. An MX pointing there gives a sender nothing to connect to. The third line is what a correct target looks like.
- Step 4.
Read a domain that declares it accepts no mail, and see what each tool calls it.
nslookup -type=MX example.com 8.8.8.8Non-authoritative answer: Server: dns.google Address: 8.8.8.8 example.com MX preference = 0, mail exchanger = (root)(root)is the root of the DNS tree written as a name, which is the null MX of RFC 7505. Node reports the same record as[{"exchange":"","priority":0}], an empty string.
How to read the result
| What you see | What it means | What to do |
| --- | --- | --- |
| Several records with different preferences | Lowest preference is tried first, the rest are fallbacks | Confirm each fallback accepts mail, not only the first |
| Two records with the same preference | The sender picks between them | Both must work. Neither is a spare |
| mail exchanger = (root) or "exchange":"" | Null MX. The domain publishes that it receives no mail | Correct for a send-only domain, a defect on one that accepts mail |
| cname= shows a name | The MX target is an alias, which RFC 5321 forbids | Replace the target with a name that carries the address itself |
| a=ENODATA on a target | The target name exists and has no address | Add the address record or point the MX somewhere else |
| MX ENODATA for the domain | No MX record. Senders fall back to the A record | Publish an MX, or a null MX if the domain sends only |
Common mistakes
What to check next
- How to check dns records: the same domain, every type, when the MX is only one of the values that moved.
- How to check SPF record: the MX names who receives, SPF names who may send.
- How to check ptr record: the reverse name of your sending address, which receivers check before they accept.
- How to check cname record: the type that must never appear under an MX target, read directly.
- DNS record lookup: the same queries from the browser, against more than one resolver.
FAQ
How to check mx record of a domain?
Query the registrable domain, not a host under it. nslookup -type=MX example.org 8.8.8.8 is the whole command. Mail is addressed to the part after the @, so an MX published at www.example.org routes nothing.
How to check mx record in cmd?
The same line works in cmd, in PowerShell and in a POSIX shell: nslookup -type=MX mozilla.org 8.8.8.8. PowerShell also has Resolve-DnsName mozilla.org -Type MX, which prints the preference in a column named Preference and adds the TTL.
Which MX is used when two have the same preference?
The sending server chooses, and nothing in the protocol says how. Both records are in active use. Test both, and size both for the full volume, because a sender is allowed to send everything to one of them.
Does a lower preference number mean lower priority?
No. The number is a preference, and the record with the smallest number is tried first. Preference 1 outranks preference 10. The field is often labelled priority in control panels, which reverses the everyday sense of the word.
Verified
Verified by Maks Vernynslookup Windows 11 build 22631node 22.23.2
Each output block is what the command above it printed on that date, on the host named in the step. Figures read from a live site move between runs. Compare the shape of the answer rather than the digits, and see the methodology for how a page is re-verified.
Related on this site
- Checker: dns-records A, AAAA, CNAME, MX, NS, TXT with TTL from two public resolvers, mismatch between resolvers
- DNS migration checklist
- Email testing checklist
- All email and dns checks
basic6 minpublished updated Maks Verny