DEV Community

Jonas Hämmerle
Jonas Hämmerle

Posted on

MX record checks: the cheap email validation step everyone skips

Regex-validating an email address only tells you the syntax is plausible. It says nothing about whether user@totallyfakedomain12345.com can receive mail. An MX record lookup closes that gap for basically zero extra latency.

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

async function domainCanReceiveMail(domain) {
  try {
    const records = await resolveMx(domain);
    return records.length > 0;
  } catch {
    return false;
  }
}
Enter fullscreen mode Exit fullscreen mode

This won't catch every typo (an MX record existing doesn't mean the specific mailbox exists — that needs an actual SMTP handshake, which is slow, unreliable, and often blocked by mail servers as spam-probing behavior). But it's a strong, cheap signal that catches a meaningful chunk of junk signups before you send a verification email into the void.

I run this as an optional flag on the email endpoint of Validate — syntax check always runs, MX check is opt-in since it adds a DNS round-trip. Sibling APIs on the same account: QR API and Currency API.

Top comments (1)

Collapse
 
ishan_shrestha profile image
Ishan Shrestha •

MX is the right cheap gate. Syntax alone is cosplay.

The part Id add next is disposable freshness. A domain can have perfect MX and still be a 10-minute burner. Static lists rot in days, so pair MX with a list that actually moves, plus soft score on brand-new domains instead of a hard reject.

Also allowlist Apple Hide My Email / SimpleLogin. They look weird and theyre real people.

Skipping SMTP RCPT as the main gate is the right call. Slow, often blocked, catch-alls lie. Keep confirmation email for ownership.

Curious if Validate fails open on DNS timeout or treats lookup failure as invalid.