BlogGuides

How Email Validation Works: A Technical Guide

Rahul Lakhaney
By Rahul LakhaneyPublished on: Mar 28, 2026 · Updated: Mar 30, 2026 · 12 min read · Last reviewed: Mar 2026

TL;DR

A practitioner's breakdown of what happens when you validate an email address: syntax parsing, DNS and MX lookups, SMTP handshake verification, catch-all detection, disposable provider filtering, and how to integrate validation into your workflow with the Enrich API.

What email validation actually checks

Email validation is not a single check. It is a pipeline of five distinct verification layers, each catching a different class of bad addresses. Skip any layer and you will let garbage into your list.

1. Syntax validation confirms the address follows RFC 5322 formatting rules. It checks for an @ symbol, valid local-part characters, a properly formed domain, and correct length limits (64 characters for local-part, 255 for the full address). This catches typos like "john@.com" or "john@@company.com" but nothing else. About 2% to 5% of form submissions fail syntax checks alone.

2. MX record lookup queries DNS to confirm the domain has mail exchange servers configured. A domain without MX records cannot receive email. This catches made-up domains ("john@notarealcompany.xyz") and domains that exist but do not handle mail. It adds roughly 50ms to the validation pipeline.

3. SMTP verification connects to the mail server and simulates sending a message without actually delivering it. This confirms the specific mailbox exists. More on this in the next section.

4. Catch-all detection identifies domains configured to accept email for any address, making individual mailbox verification impossible.

5. Disposable provider detection flags addresses from temporary email services like Guerrilla Mail, Mailinator, and 10MinuteMail. These addresses self-destruct, so sending to them is pointless. Enrich maintains a list of 30,000+ disposable domains that is updated weekly.

How SMTP verification works step by step

SMTP verification is the most technically interesting part of the validation pipeline. Here is exactly what happens during a verification request.

The validator opens a TCP connection to the recipient's mail server on port 25 (or 587). It sends a HELO/EHLO command to identify itself. The mail server responds with a 250 status code if it is ready to talk.

Next, the validator sends a MAIL FROM command with a sender address. Then it sends the critical command: RCPT TO with the email address being validated. This is where the magic happens. The mail server checks whether the mailbox exists and responds with either a 250 (mailbox exists), 550 (mailbox does not exist), or 452 (mailbox full).

Here is a simplified version of what the protocol exchange looks like:

TSTypeScript
// Simplified SMTP verification flow
async function verifyEmail(email: string): Promise<boolean> {
  const domain = email.split('@')[1];
  const mxRecords = await dns.resolveMx(domain);
  const mx = mxRecords.sort((a, b) => a.priority - b.priority)[0];
  const socket = await connect(mx.exchange, 25);
  await send(socket, `EHLO verify.enrich.so`);
  await send(socket, `MAIL FROM:<check@enrich.so>`);
  const response = await send(socket, `RCPT TO:<${email}>`);
  await send(socket, 'QUIT');
  return response.code === 250;
}

The validator never sends a DATA command, so no actual email is delivered. It is a handshake, not a message. The entire process takes 200ms to 2 seconds depending on the mail server's response time.

Some mail servers rate-limit SMTP verification attempts or block them entirely. Good validators (including Enrich) rotate source IPs, throttle requests per domain, and use caching to avoid triggering anti-abuse protections.

Catch-all vs valid vs risky: understanding the verdict

Validation does not return a simple true/false. It returns a verdict with nuance, and understanding that nuance determines whether you send or suppress.

Valid means the mail server confirmed the mailbox exists and is accepting messages. This is the green light. Send with confidence. Roughly 70% to 80% of addresses in a well-maintained B2B list will return valid.

Invalid means the mail server explicitly rejected the address. The mailbox does not exist, the domain has no MX records, or the syntax is broken. Never send to invalid addresses. Every invalid send counts as a hard bounce, and hard bounces above 2% will tank your sender reputation with Gmail, Outlook, and other providers.

Catch-all (also called accept-all) means the domain's mail server is configured to accept email for any address, whether the mailbox exists or not. Common with smaller companies using Google Workspace or custom mail setups. For catch-all addresses, the SMTP handshake always returns 250, so you cannot confirm the specific mailbox. The address might be real or it might bounce.

The practical guidance: send to catch-all addresses cautiously. Segment them separately, monitor bounce rates closely, and remove any that bounce. Some teams skip catch-all addresses entirely for cold outreach but include them for inbound lead follow-up where the person just filled out a form.

Risky means the address passed basic checks but has warning signals: the mailbox is full, the server is temporarily unavailable, or the domain has a history of high bounce rates. Treat risky addresses like catch-all: proceed with caution and monitor results.

Unknown means the validator could not reach the mail server (timeout, connection refused, or greylisting). Retry these after 24 hours. If they remain unknown after two attempts, suppress them.

Bounce rate impact on sender reputation

Sender reputation is a score that email providers (Gmail, Microsoft, Yahoo) assign to your sending domain and IP address. It determines whether your emails land in the inbox, the spam folder, or get blocked entirely. Bounce rate is one of the biggest factors in that score.

Hard bounces above 2% are dangerous. Google's Postmaster Tools documentation states that senders should keep bounce rates below 2% to maintain good standing. Microsoft is even stricter for new sending domains. A single campaign with a 5% bounce rate can trigger spam filtering for your entire domain for weeks.

The math is straightforward. If you have 10,000 contacts and 8% are invalid (a common number for lists that have not been validated in 6+ months), that is 800 hard bounces. Send to all 10,000 and your bounce rate is 8%, well above the danger threshold. Validate first, remove the 800 invalid addresses, and your bounce rate drops to nearly zero.

Recovery is slow. Once your sender reputation takes a hit, recovery takes 2 to 4 weeks of consistent, clean sending. During that period, even your emails to valid, engaged contacts may land in spam. For sales teams running outbound sequences, this means weeks of lost pipeline.

The cost of validation is negligible compared to the cost of a damaged reputation. Enrich charges 1 credit per email validation. On the Growth Pack ($49/mo for 100K credits), that is $0.00049 per validation. Validating 10,000 emails costs less than $5. The cost of not validating, a damaged domain reputation and weeks of emails going to spam, is orders of magnitude higher.

Validate every email before you send. No exceptions.

The 2% rule
Keep hard bounce rates below 2% at all times. A single campaign above 5% can damage your sender reputation for weeks. Validate every address before sending.

When to validate: three critical integration points

Email validation is not a one-time cleanup task. It should run at three specific points in your workflow to keep your data clean continuously.

1. At form submission (real-time). Validate email addresses the moment someone fills out a form on your website. This catches typos ("gnail.com" instead of "gmail.com"), fake addresses, and disposable emails before they enter your system. Real-time validation adds 200ms to 500ms of latency, which is invisible to the user. The payoff is huge: you never ingest a bad address in the first place.

Integrate validation into your form handler:

TSTypeScript
app.post('/signup', async (req, res) => {
  const { email, name } = req.body;
  const validation = await enrich.emailValidation.validate({ email });
  if (validation.result === 'invalid') {
    return res.status(400).json({
      error: 'Please enter a valid email address'
    });
  }
  if (validation.disposable) {
    return res.status(400).json({
      error: 'Please use your work email address'
    });
  }
  await createUser({ email, name, emailStatus: validation.result });
  return res.status(200).json({ success: true });
});

2. Before outreach campaigns. Validate your entire send list 24 to 48 hours before launch. Even if addresses were valid when you collected them, people change jobs and mailboxes get deactivated. A list that was 98% valid three months ago might be 90% valid today.

3. Quarterly CRM cleanup. Run batch validation on your entire contact database every quarter. Flag invalid addresses for removal, update catch-all status, and identify contacts that need re-enrichment. With B2B data decaying at 30% per year, quarterly validation catches roughly 7% to 8% of records that have gone stale since the last check.

All three integration points work together: real-time validation prevents bad data from entering, pre-campaign validation catches decay, and quarterly cleanup maintains long-term database health.

Enrich's email validation API

Enrich's Email Validation API runs all five verification layers (syntax, MX, SMTP, catch-all, disposable) in a single API call that returns results in under 500ms.

  • result: "valid", "invalid", "risky", or "unknown"
  • smtp_check: whether the SMTP handshake confirmed the mailbox
  • mx_found: whether the domain has MX records
  • catch_all: whether the domain is configured as catch-all
  • disposable: whether the address is from a disposable email provider
  • free_provider: whether the address is from a free provider (Gmail, Yahoo, etc.)
  • role_account: whether the address is a role-based address (info@, support@, admin@)

Pricing: 1 credit per validation. On the Growth Pack ($49/mo for 100K credits), you can validate 100,000 emails per month. That is enough to validate your entire CRM quarterly and still have credits left for real-time validation.

Batch validation: Submit up to 500K email addresses in a single batch request. Results are delivered via webhook as they complete. Batch validation is ideal for quarterly CRM cleanup and pre-campaign list scrubbing.

You can also use Enrich's free email validation tool to validate individual addresses without an API key. It is useful for quick one-off checks during sales research or when verifying a contact before sending a manual email.

Getting started: Sign up at dash.enrich.so for 100 free credits. That is 100 email validations at no cost, enough to test accuracy against your own data before committing to a plan.

Free validation tool
Test Enrich's email validation instantly at enrich.so/free-tools/email-validation. No signup required for single lookups.

Frequently Asked Questions

Try Enrich for free

100 free API credits. No credit card required. Start enriching data in minutes.