Plainwork

Plainwork / MailGate Email Check API / Email regex vs MX check: what each catches

Email regex vs MX check: what each one actually catches

A regex tells you whether a string looks like an email address. An MX lookup tells you whether the domain after the @ is set up to receive mail. They answer different questions, and most signup forms only ask the first one.

What a regex can and cannot tell you

InputPasses a typical regexPasses an MX check
[email protected]YesYes
[email protected] (typo)YesOften yes, because typo domains can have MX records
[email protected]YesNo (no MX, no A record)
[email protected] (disposable)YesYes, it receives mail perfectly well
jane@NoNot applicable

Two rows stand out. A typo domain and a disposable domain both pass an MX check, because both are real mail servers. That is why a domain list (disposable domains) and a typo dictionary (common misspellings of gmail, hotmail, yahoo, outlook, icloud) are separate layers on top of MX.

A regex that does not reject real people

const looksLikeEmail = /^[^@\s]+@[^@\s]+\.[^@\s]{2,}$/.test(email);

Keep it this loose. Plus tags ([email protected]), new long top-level domains and subdomains are all valid. Stricter patterns copied from forums regularly reject them.

An MX check in Node.js

import { resolveMx, resolve4 } from "node:dns/promises";

async function domainCanReceiveMail(email) {
  const domain = email.split("@")[1];
  try {
    const mx = await resolveMx(domain);
    if (mx.length) return "mx";
  } catch {}
  try {
    const a = await resolve4(domain);   // RFC 5321 falls back to the A record
    if (a.length) return "a-only";
  } catch {}
  return "none";
}

A domain with MX records is the strong signal. A domain with only an A record can technically receive mail but usually does not, so treat a-only as risky rather than valid. Browsers cannot run DNS queries, so this runs on your server.

Or get all the layers in one request

The MailGate endpoint does syntax, MX, disposable-domain, role-account and typo checks and returns a 0 to 100 score with a verdict:

curl "https://pw-d20261007a2.plainwork-apps.workers.dev/[email protected]"
# {"valid_syntax":true,"disposable":false,"did_you_mean":"[email protected]","mx":"a-only","score":45,"verdict":"risky", ...}

What none of these can do

No regex or domain-level check can prove a specific mailbox exists or belongs to the person typing it. Only a confirmation link does that. Use the cheap checks to avoid sending confirmation emails that will bounce, and the confirmation email as the final gate.

Related: validating email in JavaScript, blocking disposable signups, and the free list cleaner (runs in your browser). The free API tier is 20 checks a day with no signup; the $5/month plan removes the cap.

More from the catalogue

Other small tools

See everything →