What Is Email Verification? A Developer's Guide
When a user types an email address into your signup form, what do you actually know about it? If you're only checking syntax — does it look like an email? — you know almost nothing. Email verification is the process of determining whether an address is real, reachable, and worth contacting.
This guide explains what verification actually checks, how each layer works, and where it belongs in your stack.
What email verification is not
Syntax validation is not email verification. Checking that an address matches /^[^\s@]+@[^\s@]+\.[^\s@]+$/ tells you only that the string has an @ sign and a dot. It won't catch:
test@mailinator.com— disposable address, deleted in 10 minutesnoreply@example.com— role address that nobody readsuser@nonexistent-domain.com— domain with no mail serverghost@real-company.com— address where the mailbox was deleted
A full verification pipeline has five distinct layers. Each one eliminates a different class of bad addresses.
Layer 1: Syntax validation
The first check normalises and validates the address format per RFC 5321 and RFC 5322. Beyond the basic regex, this catches edge cases like:
- Double dots (
user..name@domain.com) - Leading or trailing dots in the local part
- Invalid characters in the local part
- Overly long addresses (RFC limit: 254 characters total, 64 in the local part)
Most addresses fail here only due to user typos, and this step completes in microseconds.
Layer 2: Domain and MX record lookup
A valid syntax doesn't mean the domain exists or accepts mail. The second layer performs DNS lookups:
- MX record lookup — does the domain have mail exchange records pointing to an SMTP server?
- A record fallback — if no MX record exists, does the domain resolve at all?
- Domain existence — is the domain registered and not expired?
A domain like emai.com (common typo for email.com) passes syntax validation but has no MX record — and never will. This check eliminates entire categories of typos and recently-expired domains.
# Manual check: look up MX records for a domain
dig MX gmail.com
# ;; ANSWER SECTION:
# gmail.com. 3600 IN MX 5 gmail-smtp-in.l.google.com.Layer 3: SMTP verification
The most valuable check is an SMTP dialogue with the mail server. The verifier connects to the MX server, starts a conversation, and asks whether the mailbox exists — without actually sending an email.
The exchange looks like this:
→ EHLO verifier.mailbeam.dev
← 250-smtp.gmail.com Hello
→ MAIL FROM:<probe@mailbeam.dev>
← 250 2.1.0 OK
→ RCPT TO:<user@gmail.com>
← 250 2.1.5 OK ← mailbox exists
If the server responds with a 550 or 551 to the RCPT TO command, the mailbox doesn't exist. The verifier then issues a RSET to abort before any message is sent.
This catches addresses that pass syntax and MX checks but have no actual inbox — common after employee churn, account closures, or bulk-created fake accounts.
SMTP limitations
Some mail servers don't play along. They respond 250 OK to every address regardless (catch-all behaviour) to avoid revealing which mailboxes exist. Others rate-limit SMTP verification probes. This is where layer four matters.
Layer 4: AI scoring for ambiguous addresses
When SMTP gives an ambiguous result — typically catch-all domains — a verification API can apply a machine learning model trained on historical sending data to estimate the probability that the address is real.
The model considers signals like:
- Historical bounce rate for the domain
- Whether the domain is associated with a known catch-all pattern
- Domain age and email volume patterns
- Local part patterns (random strings often indicate auto-generated addresses)
The output is a confidence score (Mailbeam uses 0–100) rather than a binary result. This lets you apply different thresholds based on your use case:
const result = await mb.verify(email);
if (result.catchAll) {
// Corporate email — accept high-confidence, flag medium, reject low
if (result.score >= 70) return "accept";
if (result.score >= 40) return "flag_for_review";
return "reject";
}Layer 5: Metadata checks
Beyond deliverability, verification APIs surface useful metadata:
disposable— is this a known temporary email domain (Mailinator, 10MinuteMail, etc.)?role— is this a role address likeinfo@,noreply@,admin@?suggestion— did the user probably meangmail.cominstead ofgmai.com?free— is this a free provider (Gmail, Outlook)?
These flags let you apply different rules for different address types — for example, accepting role addresses for billing contacts but rejecting them for marketing lists.
When to use email verification
At signup (real-time)
The highest-value integration point. Verify the address before the account is created, while the user is still on the form.
// Next.js Server Action
async function createAccount(formData: FormData) {
const email = formData.get("email") as string;
const result = await mb.verify(email);
if (!result.valid) {
return { error: result.suggestion
? `Did you mean ${result.suggestion}?`
: "That email address doesn't appear to be valid." };
}
if (result.disposable) {
return { error: "Temporary email addresses are not allowed." };
}
// proceed with account creation
}Real-time verification requires a sub-100ms API — anything slower and you're blocking the user's form submission noticeably.
Before bulk sends
Before importing a CSV or sending to a cold list, run a batch verification job. This protects your sender reputation before any damage is done.
const results = await mb.verifyBatch(emails);
const deliverable = results
.filter(r => r.valid && r.score >= 60)
.map(r => r.email);Periodic list cleaning
Email addresses decay at roughly 20–30% per year. Addresses that were valid 18 months ago may now bounce. Running list cleaning every 6 months keeps bounce rates in check without requiring frontend changes.
What to do with the result
A common mistake is treating verification as a binary gate. The better pattern is tiered handling:
| Result | Action |
|---|---|
valid: true, score >= 70 | Accept immediately |
valid: true, score 40–69 | Accept but monitor engagement |
valid: true, score < 40, catchAll: true | Accept for high-intent flows; reject for cold outreach |
valid: false, suggestion | Show suggestion to user |
disposable: true | Block with a message |
valid: false, no suggestion | Show generic validation error |
Summary
Email verification is a pipeline, not a single check:
- Syntax — is the format valid?
- DNS/MX — does the domain accept mail?
- SMTP — does the specific mailbox exist?
- AI scoring — for catch-all domains, what's the confidence?
- Metadata — is it disposable, a role address, or a typo?
Running all five layers — either via an API or by building your own pipeline — is what separates a real address from one that looks real.