Email validation in depth, beyond isValid

One boolean is a summary of a dozen signals, and the summary throws away the reasons. Learn what each field really measures, where it misleads, and how to turn the set into a decision you can explain to a support ticket.

If you finished the Fundamentals level you have probably already built a signup gate that blocks an address when isValid is false or isDisposable is true. That gate is fine for a free tier. It is not enough for a sales form that routes leads to humans, a marketplace that pays sellers, or a newsletter whose sender reputation you care about. Those flows need to know why an address looks bad, because the right response differs: a typo deserves a hint, a role mailbox deserves a human, a domain that refuses mail deserves a hard stop.

This lesson takes the Email Validator response apart field by field, shows you real responses where the fields disagree with intuition, and ends with a decision function you can drop into any backend.

What one call actually returns

Start with an address that exercises most of the response: a Gmail address with dots, mixed case and a +tag.

Try it liveEmail Validator20 credits
GEThttps://api.apiverve.com/v1/emailvalidator
curl "https://api.apiverve.com/v1/emailvalidator?email=Jane.Doe%2Bnews%40gmail.com" \
  -H "x-api-key: YOUR_API_KEY"
Sign in or create a free account to run this with your own key.

Look at isSubaddressed and normalizedEmail: the address you will store and the address you dedupe on are different strings.

The response comes back lowercased ([email protected]) and carries roughly twenty fields. They fall into four groups, and it helps to think of them that way rather than as a flat list.

GroupFieldsQuestion it answers
ShapeisRegexValid, hasTypo, username, domainIs this string an email address at all?
DeliverabilityisMxValid, mxRecord, isNullMx, canReceiveMailCan mail for this domain be delivered anywhere?
Domain posturehasSpf, hasDmarc, isFreeEmail, isCompanyEmail, isDisposableWhat kind of domain is it, and is it run properly?
MailboxisRoleAccount, isSubaddressed, normalizedEmailWhat kind of mailbox is this, and have we seen it before?

isValid is the roll-up. In every response used for this lesson it matched isRegexValid && isMxValid: the shape is acceptable and the domain has MX records. It does not consider disposability, role accounts or anything in the mailbox group. Treat it as a deliverability summary, not a verdict.

Three fields are premium: suggestedCorrection, riskScore and riskLevel. They are useful when your plan includes them, and your code must keep working when they are absent. Every other field in the table is on every plan. The call costs 20 credits, which matters later when you decide what to call and in what order.

Deliverability: MX, null MX and the A-record fallback

Mail for a domain is routed by its MX records. No MX records usually means mail cannot be delivered, but "usually" hides two special cases that the response separates for you.

Null MX. RFC 7505 lets a domain publish a single MX record pointing at . to declare "this domain accepts no mail, do not try." example.com does exactly that:

Try it liveEmail Validator20 credits
GEThttps://api.apiverve.com/v1/emailvalidator
curl "https://api.apiverve.com/v1/emailvalidator?email=user%40example.com" \
  -H "x-api-key: YOUR_API_KEY"
Sign in or create a free account to run this with your own key.

isNullMx is true and canReceiveMail is false. This is the one deliverability answer that is a deliberate no, not a missing record.

A null MX is the strongest reject signal in the response. The domain owner has told the world nobody reads mail there. A person typing such an address is either testing your form or hiding.

The A-record fallback. RFC 5321 says that when a domain has no MX record at all, a sender may deliver to the domain's A record instead. isMxValid ignores that fallback; canReceiveMail follows it. The difference shows up on parked and misspelled domains. Validate [email protected] and you get isMxValid: false, mxRecord: null, and canReceiveMail: true, because the typo domain has a web server but no mail exchanger. Technically a mail server could try delivery there. In practice that address is a typo, and the person who owns gmial.com is not your customer.

The rule that falls out: isMxValid: false is a reject or review signal even when canReceiveMail is true. Use canReceiveMail only to separate "can never work" (null MX, nothing resolvable) from "probably misconfigured".

Looking at the records directly

When you need the actual records, for example to show a support agent which provider hosts a customer's mail, MX Lookup returns them for a bare domain at 10 credits a call.

Try it liveMX Lookup10 credits
GEThttps://api.apiverve.com/v1/mxlookup
curl "https://api.apiverve.com/v1/mxlookup?domain=gmail.com" \
  -H "x-api-key: YOUR_API_KEY"
Sign in or create a free account to run this with your own key.

The records arrive in no particular order. The lowest priority number is the preferred server.

Two details catch people. First, the mx array is not sorted: for gmail.com the priority-5 record is last. Sort it yourself before you call the first entry "primary". Second, a domain with no usable MX records does not return an empty array. mxlookup on example.com returns HTTP 404 with the error no mx records found for domain. That is the "no result for your input" kind of 404, not an unknown API, so your client must treat it as an answer rather than a failure to retry.

mx.js (Node 18+, ESM)
const BASE = 'https://api.apiverve.com/v1';

export async function mxRecords(domain) {
  const res = await fetch(`${BASE}/mxlookup?${new URLSearchParams({ domain })}`, {
    headers: { 'x-api-key': process.env.APIVERVE_API_KEY },
    signal: AbortSignal.timeout(3000),
  });
  const body = await res.json().catch(() => null);
  if (res.status === 404) return []; // no MX records: an answer, not an outage
  if (!res.ok || body?.status !== 'ok') throw new Error(body?.error || `HTTP ${res.status}`);
  return [...body.data.mx].sort((a, b) => a.priority - b.priority);
}

You rarely need both mxlookup and emailvalidator for the same address, because the validator already reports the preferred exchanger as mxRecord. Reach for mxlookup when you are auditing domains rather than addresses, such as checking a list of B2B customer domains after a migration.

Check yourself

An address returns isMxValid false, mxRecord null, isNullMx false and canReceiveMail true. What is the most accurate reading?

Answer the check above to continue.

Run every example on your own key. Free plan, no card.

Scaling up?

Volume pricing, custom SLAs, and dedicated support for high-traffic teams.

Contact sales