Email Validation With Regex vs an API: What Regex Can't Tell You

"What's the best regex for validating email?" is one of the most-asked programming questions of all time. The honest answer: a regex can only check the shape of an address, and the shape is the least important part of whether an email will be delivered.

This post covers what regex can and can't do, a regex that's good enough, and what to use for everything regex can't see.

Why "perfect" email regexes don't exist

The official grammar (RFC 5321/5322) allows things you'd never expect in a form:

"john..doe"@example.com         quoted local part with consecutive dots
user+tag@example.com            plus addressing
user@[192.168.2.1]              IP-address literal
very.unusual."@".unusual.com@example.com

Regexes that try to cover the whole spec run to hundreds of characters, are impossible to review, and still disagree with real mail servers. Meanwhile, simple regexes reject valid addresses people actually use, such as o'brien@example.ie or long new TLDs like .photography.

A regex that's good enough

For a form, you want to reject obvious garbage and let the server-side check handle the rest:

const EMAIL = /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/;

It requires something before the @, a domain with a dot, and a TLD of at least 2 characters, with no spaces. It's intentionally permissive. Browsers do something similar for <input type="email">.

In Python, prefer a real parser over a regex. email-validator (used by Pydantic's EmailStr) handles internationalised addresses correctly:

from email_validator import validate_email, EmailNotValidError

try:
    info = validate_email("Jane.Doe@Example.com", check_deliverability=False)
    print(info.normalized)  # Jane.Doe@example.com
except EmailNotValidError as e:
    print(e)

Try your own inputs in the email syntax checker, which also catches domain typos like gmial.com.

What regex can't tell you

Every one of these addresses passes any reasonable regex:

Address Problem Regex sees it?
jane@gmial.com Typo in a popular domain No
jane@acme-corp-old.com Domain has no mail server (no MX) No
j.doe@acme.com Mailbox doesn't exist No
x7k2@mailinator.com Disposable address No
anything@catchall-corp.com Catch-all: can't be confirmed No
info@acme.com Role address, not a person No

Each of those is either a bounce, a fake signup or wasted outreach, and together they're most of the bad addresses in a real list.

The layers of real validation

  1. Syntax: regex or parser. Free, instant, local.
  2. Domain: does the domain exist and have MX records? (Try the MX lookup.)
  3. Known bad providers: disposable and spamtrap domains.
  4. Mailbox: ask the mail server whether the recipient exists, without sending an email.
  5. Catch-all detection: does the server accept every address, making step 4 meaningless?

Steps 1 to 3 can be done yourself with DNS and a maintained list. Steps 4 and 5 need SMTP conversations from well-reputed IPs, careful rate limiting and constant upkeep, because providers throttle and block verifiers. That's why most teams use an API for them.

Using an API for layers 2 to 5

curl -X POST https://www.mailrambo.com/v1/verify \
  -H "Authorization: Bearer $MAILRAMBO_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email": "j.doe@acme.com"}'
{ "email": "j.doe@acme.com", "deliverable": false, "reason": "mailbox_not_found", "credits_remaining": 48 }

You still run your regex first. It's free, it gives instant feedback in the browser, and MailRambo doesn't charge for addresses that fail syntax anyway.

  • Browser: type="email" plus a light regex, for instant feedback only.
  • Server: a parser for syntax, then one API call for everything else.
  • Decision: block mailbox_not_found, disposable and invalid_syntax. Decide explicitly about catch_all: allow it at signup, exclude it from outreach.

Summary

Regex answers "does this look like an email?" It can't answer "will this email be delivered?" Use a permissive regex for instant feedback, and a verification API for the checks that actually prevent bounces and fake signups.

Test any address with the free email verifier.

Run these checks from your code

Verify addresses at signup, clean lists and read SPF/DKIM/DMARC with one API call. 100 free verifications a month, test keys that cost nothing, and the API on every plan.