Detecting business emails with MX records
What MX records reveal about an email domain (Workspace, Microsoft 365, gateways, hosting, forwarding), what they can't tell you, and pitfalls in code.
If you want to know whether an email address belongs to a company, the domain’s MX records are the best single place to start. They’re public, cheap to query, and say who actually runs the domain’s mail. They also have blind spots that will bite you if you treat them as the whole answer.
MX in two minutes
An MX (mail exchanger) record tells sending servers where to deliver mail for a domain. Each record has a priority (lower is preferred) and a host:
$ dig +short MX acme.example
1 aspmx.l.google.com.
5 alt1.aspmx.l.google.com.
5 alt2.aspmx.l.google.com.
Three edge cases matter for classification:
- Null MX.
MX 0 .(RFC 7505) means “this domain accepts no mail”. Any address on it is undeliverable. - No MX at all. SMTP then falls back to the domain’s address records (RFC 5321, “implicit MX”). Real mail setups almost always publish MX; a domain with neither MX nor an address record can’t receive mail.
- The domain doesn’t exist (NXDOMAIN). Different from “exists, but no MX”, and worth telling apart in your logs.
Fingerprints: who hosts the mail
MX hosts follow recognizable patterns per provider. A few common ones:
| MX host pattern | Means | Read as |
|---|---|---|
aspmx.l.google.com, smtp.google.com |
Google Workspace | Company, strong |
gmail-smtp-in.l.google.com |
Consumer Gmail | Personal |
*.mail.protection.outlook.com |
Microsoft 365 (Exchange Online) | Company, strong |
*.olc.protection.outlook.com |
Consumer Outlook.com / Hotmail | Personal |
*.yahoodns.net |
Consumer Yahoo Mail | Personal |
*.pphosted.com (Proofpoint), *.mimecast.com, *.iphmx.com (Cisco), *.messagelabs.com, *.hornetsecurity.com, *.barracudanetworks.com |
Email security gateways | Company, strong |
mx.zoho.com, mx.zoho.eu |
Zoho Mail | Company (another suite) |
mail.protonmail.ch |
Proton Mail | Company or individual on a custom domain |
*.messagingengine.com |
Fastmail | Company or individual on a custom domain |
*.mail.icloud.com |
iCloud+ custom domain | Often an individual’s domain |
Hosting providers’ mail (e.g. *.secureserver.net, *.ionos.com, *.mail.ovh.net) |
Web-host email | Company, moderate |
| Forwarding services (e.g. ImprovMX, Cloudflare Email Routing) | No mailboxes, forwards elsewhere | Unclear: could forward to Gmail |
Some takeaways:
- Consumer-only hosts are decisive. A custom domain whose MX is
gmail-smtp-inorolc.protection.outlook.comisn’t running a business mail service. - Security gateways are a strong business signal because companies pay for them. But they hide the suite behind them: to see Google Workspace or Microsoft 365 behind Proofpoint, look at DKIM (
google._domainkey) and SPF includes. How to find out which email provider a company uses walks through it. - Consumer-friendly custom-domain services (iCloud+, Fastmail, Proton) host plenty of real companies and plenty of individuals. They lower confidence; they don’t decide.
- Forwarding means “somewhere else”. A domain on a forwarding service has no mailboxes of its own. It’s often a side project, sometimes a throwaway, occasionally a real company that forwards to personal inboxes.
Patterns change: providers add hosts and formats (Microsoft, for example, has introduced newer MX hostnames under mx.microsoft for DNSSEC-enabled domains). Match suffixes, maintain the table, and re-test.
What MX can’t tell you
- Who the person is. MX describes the domain.
jane@acme.ioon Microsoft 365 may be an employee, a contractor or a shared mailbox. - Whether the mailbox exists. And you shouldn’t try to find out by probing. SMTP
RCPT TOchecks are unreliable (catch-all domains, greylisting) and amount to user enumeration. That question belongs to verification, not classification. - Whether it’s shared. A small ISP or regional webmail provider on its own MX looks just like a company. That’s why curated lists of shared providers come first, and DNS only classifies what lists don’t cover.
- Whether it’s disposable. Many disposable domains have perfectly normal-looking MX. One useful trick: if an MX host also serves several known disposable domains, the new domain is probably part of the same service.
- The whole suite. Identity on Microsoft and mail on Google is common; MX shows only the mail side.
Pitfalls when you implement it
Query the registrable domain. mail.eu.acme.co.uk should be checked as acme.co.uk. Use the Public Suffix List to find it. This is also a safety measure: if you query whatever subdomain users type, your service can be used to launch random-subdomain DNS floods at someone else’s nameservers.
Normalize first. Lowercase, strip a trailing dot, convert internationalized domains to punycode, reject control characters and absurd lengths (domains max out at 253 characters).
Handle DNS failures as their own outcome. NXDOMAIN (doesn’t exist), NODATA (no MX), SERVFAIL and timeouts mean different things. A timeout is not evidence that a domain is invalid. Answer from what you know, mark it as degraded, and retry later.
Use short timeouts and a fallback resolver. On a signup path, a DNS lookup that hangs for 10 seconds is worse than no lookup. DNS-over-HTTPS to a public resolver with a fallback works well from serverless runtimes.
Cache by domain. Respect TTLs, but a verdict for a domain changes rarely. Caching keeps you fast and polite.
A minimal classifier in Node
import { resolveMx } from 'node:dns/promises';
const RULES = [
[/(^|\.)gmail-smtp-in\.l\.google\.com$/, 'consumer_gmail'],
[/(^|\.)aspmx\.l\.google\.com$|^smtp\.google\.com$/, 'google_workspace'],
[/\.olc\.protection\.outlook\.com$/, 'consumer_outlook'],
[/\.mail\.protection\.outlook\.com$/, 'microsoft_365'],
[/\.yahoodns\.net$/, 'consumer_yahoo'],
[/\.(pphosted|mimecast|iphmx|messagelabs|hornetsecurity|barracudanetworks)\.com$/, 'security_gateway'],
];
export async function mxProvider(domain) {
let records;
try {
records = await resolveMx(domain);
} catch (err) {
if (err.code === 'ENOTFOUND') return { status: 'no_domain' };
if (err.code === 'ENODATA') return { status: 'no_mx' };
return { status: 'dns_error', code: err.code }; // timeouts etc.: not a verdict
}
const hosts = records
.sort((a, b) => a.priority - b.priority)
.map((r) => r.exchange.toLowerCase().replace(/\.$/, ''));
if (hosts.length === 1 && hosts[0] === '') return { status: 'null_mx' };
for (const host of hosts) {
for (const [pattern, provider] of RULES) {
if (pattern.test(host)) return { status: 'ok', provider, hosts };
}
}
return { status: 'ok', provider: 'other', hosts };
}
This gets you surprisingly far. To get to production quality you’ll also want shared-provider and disposable lists in front of it, SPF, DMARC and DKIM checks behind it, Microsoft tenant discovery, registrable-domain handling, timeouts, caching, and an evaluation set to measure changes against. For the same do-it-yourself baseline in other languages, see Check for a business email in JavaScript, Python and PHP.
Or skip the maintenance
That’s the stack behind isBusinessEmail. MX is one layer; lists, authentication records, Workspace and Microsoft 365 detection, and domain enrichment are the others. Every response tells you which ones fired:
curl -sG https://api.isbusinessemail.com/v1/check \
--data-urlencode "email=business@test.isbusinessemail.com"
Test addresses like this one need no API key and never count toward a quota.
Look up any domain’s MX with the MX lookup tool, browse a classified domain like gmail.com, or read the reason codes for the full list of signals.
Frequently asked questions
What is an MX record?
An MX (mail exchanger) record tells sending servers which hosts accept mail for a domain. Each record has a priority, where lower is preferred, and a host name.
Can MX records tell you if an email is a business email?
They are the best single place to start. Hosts such as aspmx.l.google.com or a host ending in mail.protection.outlook.com point to Google Workspace or Microsoft 365, while gmail-smtp-in.l.google.com means consumer Gmail. MX can't tell you who the person is, whether the mailbox exists or whether the domain is disposable, so check curated lists first.
What happens if a domain has no MX record?
Sending servers fall back to the domain's address records, the implicit MX from RFC 5321. A domain with neither MX nor an address record can't receive mail, and a null MX (MX 0 .) explicitly says it accepts no mail.
How do you tell Google Workspace from Microsoft 365 in MX records?
Google Workspace uses aspmx.l.google.com and its alternates, or smtp.google.com. Microsoft 365 (Exchange Online) uses hosts ending in mail.protection.outlook.com, while consumer Outlook.com uses hosts ending in olc.protection.outlook.com.
Why does MX sometimes show Proofpoint or Mimecast instead of the mail provider?
The company puts an email security gateway in front of its mailboxes, so MX names the gateway rather than the suite behind it. A DKIM key at google._domainkey and the SPF includes can reveal Google Workspace or Microsoft 365 behind it.