What is an MX record? And how email validation uses it
The DNS record that routes your mail, the priority numbers next to it, and why one missing MX record tells you more than any regex ever will.
Contents
You typed "what is an MX record" into a search box, and the odds are good you did it while building or debugging email validation. Maybe your signup form keeps accepting addresses at domains that can't receive mail. Maybe you read that checking DNS beats a regex and want to know which record to check. Here is the record, what the numbers next to it mean, and why one absent record tells you more than most of what people bolt onto email validation.
What an MX record actually is
An MX (Mail eXchanger) record is a DNS record that names the mail server or servers responsible for receiving email for a domain. When something sends mail to you@example.com, the sending server doesn't guess where to deliver it. It asks DNS for the MX records of example.com and connects to whatever host those records point at.
An MX record has two parts: a priority (a number) and a hostname. A domain usually publishes several:
example.com. 3600 IN MX 10 mail1.example.com.
example.com. 3600 IN MX 20 mail2.example.com.
The number is the preference, and lower is higher priority. A sender tries priority 10 before 20, and only falls back to 20 if the first host is unreachable. Equal numbers mean "either is fine, spread the load." It is a failover list, not a ranking of quality. That is all the number does — nothing about it says a mailbox exists behind the server. The hostname itself has to resolve to an address, and per RFC 5321 it must not point at a CNAME.
The A-record fallback (implicit MX)
Here is the caveat that keeps "no MX means no mailbox" honest. If a domain has no MX record at all, RFC 5321 says the sender falls back to the domain's A or AAAA record and tries to deliver there. This is the "implicit MX." So a domain with an A record but no MX can still, technically, receive mail.
In practice, any domain that actually accepts email publishes MX records. The implicit-MX fallback is a legacy courtesy, not how modern mail is run. Which is exactly why the check is worth so much.
Why "no MX" is the most useful check past syntax
Syntax validation — a regex, or your language's built-in parser — tells you an address is shaped like an address. It says nothing about whether the domain to the right of the @ can receive mail. jsmith@exmaple.com (typo intended) has perfectly valid syntax and is completely undeliverable.
An MX lookup closes most of that gap for the price of one DNS query. No MX record and no A-record fallback means nothing on the internet will accept mail for that domain, which means the address is dead — and you learned it without sending anything. That single check catches fat-fingered domains, abandoned domains, and made-up domains that syntax waves straight through.
For the difference between this kind of checking and actually confirming a specific mailbox exists, see validation vs. verification.
Look it up yourself
You don't need a service for this. Every OS ships a DNS client.
dig, on macOS and Linux:
dig MX gmail.com +short
5 gmail-smtp-in.l.google.com.
10 alt1.gmail-smtp-in.l.google.com.
20 alt2.gmail-smtp-in.l.google.com.
nslookup, on Windows and most everywhere else:
nslookup -type=mx gmail.com
Empty output means no MX records. Run the same query against the domain in a suspect address before you trust it.
One line of code
The same lookup from inside your app. Python, using dnspython:
import dns.resolver
answers = dns.resolver.resolve("gmail.com", "MX")
print([(r.preference, str(r.exchange)) for r in answers])
Node, using the built-in dns module — no dependency at all:
const dns = require("node:dns/promises");
dns.resolveMx("gmail.com").then(console.log);
For a fuller walk-through wired into a signup handler, see validating email in Python.
If that is all you need, stop here — genuinely. A syntax check plus an MX lookup is most of the practical value in email validation, and you can run both in-process for free.
Where Boundstone fits, and where it stops
The API earns its place when you want the same answer across every language and client without maintaining DNS code and blocklists yourself, plus the parts a raw MX lookup doesn't hand you: a maintained disposable-domain list, role-account detection (info@, admin@), and the MX lookup itself run live over DNS-over-HTTPS.
POST /v1/verify/email returns valid_syntax, domain, mx_found, disposable, role_account, and free_provider. Every response also carries the honesty contract: two lists stating what was and wasn't checked. For a valid address, checks.performed is:
["syntax", "mx", "disposable_list", "role_list"]
and checks.not_performed is:
["smtp_mailbox", "catch_all"]
Read that second list closely, because it is the point. Boundstone does a live MX lookup, so it confirms a mail server exists for the domain. It does not open an SMTP connection to ask that server whether you@ specifically has a mailbox (smtp_mailbox), and it does not probe for catch-all behavior (catch_all). Those probes are unreliable, get your IP throttled, and providers increasingly answer them dishonestly anyway. So we don't claim them. mx_found: true means exactly "this domain can receive mail," and nothing more — which is the whole reason you can trust it.
The short version
- An MX record names a domain's mail servers. The priority number is failover order (lower first), not a measure of quality.
- No MX and no A-record fallback means undeliverable. The domain cannot receive mail — caught with one query and zero sent mail.
- You can do this yourself for free.
dig MX domain +short, ordns.resolveMx/ dnspython in code — often all you need. - Boundstone runs that MX lookup live over DoH and adds disposable and role checks under one contract across languages. It does not SMTP-probe the mailbox (
smtp_mailbox) or detect catch-all (catch_all), and it says so on every response.
Try it without a key: the email validator tool.