Most email checkers claim accuracy. Few explain how they actually verify an address.
This is that explanation.
What is SMTP?
SMTP = Simple Mail Transfer Protocol
It's the language mail servers use to send and receive email.
When you send an email:
1. Your client connects to an SMTP server
2. Sends MAIL FROM: you@yourcompany.com
3. Sends RCPT TO: recipient@their.com
4. Server responds 250 OK (yes, we accept it) or 550 Reject (no, we don't)
5. Client sends the message body
SMTP Validation: The Real Check
SMTP validation simulates steps 1–4 without sending the actual email.
This is why it's the only way to know if a mailbox truly exists.
The SMTP Handshake
→ Client: EHLO mail.validator.com
← Server: 250 OK ESMTP
→ Client: MAIL FROM:<validator@mail.validator.com>
← Server: 250 OK
→ Client: RCPT TO:<test@gmail.com>
← Server: 250 OK
(mailbox exists and accepts mail)
→ Client: QUIT
← Server: 221 Bye
If the RCPT TO returns 250, the address is Valid.
If it returns 550, the address is Invalid.
If the server doesn't respond, it's Risky or Unknown.
Why Other Methods Fail
❌ Syntax Check Only
test@example.com ✅ (looks good)
test.12345@example.com ❌ (might not exist)
Syntax is correct but we don't know if the mailbox exists.
❌ MX Record Check Only
Domain: gmail.com → MX: aspmx.l.google.com (yes, exists)
But: does test@gmail.com actually exist? Unknown.
✅ SMTP Validation
Connect to gmail SMTP → RCPT TO test@gmail.com
← 550 No such user
Result: INVALID (mailbox doesn't exist)
The Challenge: Catch-All Domains
Some servers (especially older ones) say "yes" to every address:
→ RCPT TO: realuser@company.com
← 250 OK
→ RCPT TO: fakeuser123456789@company.com
← 250 OK (also accepted!)
These are catch-all domains. The SMTP check alone can't tell if it's real.
Advanced: Scoring + Catch-All Detection
Better validators combine SMTP + other signals:
- Domain reputation — is the mail server known to bounce?
- Recent activity — was this domain active in the last 90 days?
- Honeypot checks — is it a known spam trap?
- Risky + catch-all flag — "Valid by SMTP but could be catch-all"
Score 0–10 = confidence level, not just pass/fail.
Speed vs Accuracy
| Method | Speed | Accuracy | Cost |
|---|---|---|---|
| Syntax | <1ms | 60% | Free |
| MX check | 50ms | 75% | Free |
| SMTP | 500ms–2s | 95% | ¢ |
| SMTP + scoring | 1–5s | 99% | ¢¢ |
Why SMTP Validation Matters
✅ Protects sender reputation — verify before sending
✅ Reduces bounce rates — SMTP catches invalid before send
✅ Saves on credits — don't pay ESP for bounced emails
✅ Improves deliverability — ISPs reward clean sending
How to Verify Yourself (Dev Only)
import smtplib
domain = "gmail.com"
try:
smtp = smtplib.SMTP(f"mx.{domain}")
smtp.mail("test@validator.com")
code, msg = smtp.rcpt("recipient@gmail.com")
if code == 250:
print("Valid")
else:
print("Invalid")
smtp.quit()
except:
print("Risky/Unknown")
But in production, use a service. SMTP validation at scale is complex (firewalls, rate limits, delays).
SMTP in More Detail
SMTP is a text protocol. A session is a short conversation with a sequence of commands and numeric replies. For validation, only the first half matters — the part before any message body is sent.
Ports and TLS
- 25 — the classic server-to-server port. Often blocked by hosting providers to stop spam, which is why validation services use dedicated infrastructure.
- 465 — implicit TLS (SMTPS).
- 587 — submission port with STARTTLS, used by mail clients.
A validator needs port 25 reachability to the recipient's MX. If your own server cannot reach port 25, you cannot run reliable SMTP checks yourself — this is the most common reason teams outsource verification.
EHLO, MAIL FROM, RCPT TO
→ EHLO validator.example.com
← 250-mail.example.com
← 250-PIPELINING
← 250 SIZE 35882577
→ MAIL FROM:<check@validator.example.com>
← 250 OK
→ RCPT TO:<person@example.com>
← 250 OK
EHLO opens the session and asks which extensions the server supports. MAIL FROM declares the envelope sender. RCPT TO is the actual test: the server accepts or rejects the recipient. QUIT ends the session.
The key point: RCPT TO is answered before any message data is sent. That is what makes validation possible without delivering mail.
Reading SMTP Response Codes
| Code | Meaning | Validation interpretation |
|---|---|---|
| 250 | Requested action completed | Valid (unless catch-all) |
| 251 | User not local, will forward | Valid |
| 450 | Mailbox unavailable, try later | Risky |
| 451 | Local error, try later | Risky |
| 452 | Insufficient storage | Risky (full mailbox) |
| 550 | Mailbox unavailable | Invalid |
| 551 | User not local | Invalid |
| 552 | Storage exceeded | Risky |
| 553 | Mailbox name not allowed | Invalid |
| 421 | Service not available | Unknown, retry |
A validator that treats every non-250 reply as "invalid" is wrong: 4xx codes are temporary and often resolve on retry.
Why Syntax and MX Checks Are Not Enough
Both are cheap and useful as a first filter, but neither can answer the only question that matters: does this mailbox accept mail?
- Syntax tells you the string looks like an address. It cannot see that the company closed.
- MX tells you the domain has a mail server. It cannot see that
person@was never created. - SMTP talks to that server and asks about that specific recipient. Only this step returns a real answer.
The practical consequence: a list that passes syntax and MX checks can still bounce at 20–30%. That is why "free email checker" tools that only run regex are popular and useless for deliverability work.
Catch-All Domains in Depth
A catch-all server is configured to accept mail for any local part. That is a legitimate configuration — companies use it so a typo in a prospect's address does not silently disappear — but it breaks SMTP validation.
How to handle catch-alls:
- Detect them. Send a probe to a random, obviously fake local part. If it also returns 250, the domain is catch-all.
- Flag, don't delete. Catch-alls are often real people. Deleting them can cost 5–15% of a B2B list.
- Send in small batches and measure opens and bounces. If a catch-all segment performs, keep it.
- Use additional signals — domain reputation, historical engagement, and pattern matching — to rank catch-all addresses.
Greylisting, Rate Limits and Anti-Harvesting
Real mail servers are not test harnesses. Expect:
- Greylisting — the server temporarily rejects first-time senders with a 4xx and expects a retry. Validation services retry automatically.
- Rate limiting — too many connections from one IP get throttled. Good providers spread checks across IPs and time.
- Anti-harvesting — some servers deliberately answer ambiguously to anyone probing many addresses.
- Honeypots — addresses that exist only to catch bulk senders. A good validator flags them.
This is why DIY validation scripts work on ten addresses and fall apart on ten thousand.
Real-Time vs Batch, and the Async Pattern
- Real-time is right for signup forms and checkout: one address, one immediate answer, with a strict timeout so the user never waits more than a second or two.
- Batch is right for lists: thousands of addresses, retries, and a result file you can segment.
- Async is the production pattern for both: queue the address, return immediately, verify in the background, and update the record when the result arrives.
Never block a request thread on a remote SMTP handshake. A slow or hostile server can hold the connection for 30 seconds or more.
A Better Python Example
import smtplib
import dns.resolver
def check(domain: str, address: str, timeout: int = 10) -> str:
try:
mx = str(dns.resolver.resolve(domain, "MX")[0].exchange).rstrip(".")
with smtplib.SMTP(mx, 25, timeout=timeout) as smtp:
smtp.ehlo_or_helo_if_needed()
smtp.mail("check@validator.example.com")
code, _ = smtp.rcpt(address)
if code in (250, 251):
return "valid"
if code in (450, 451, 452, 552):
return "risky"
if code in (550, 551, 553):
return "invalid"
return "unknown"
except Exception:
return "unknown"
Even this simplified version has problems at scale: it ignores greylisting, does not detect catch-alls, uses one IP, and will be blocked by providers that rate-limit. It is a learning tool, not a production validator.
Limitations and Ethics
No validator can guarantee deliverability. Mailboxes close between the check and the send; servers change policy; a "valid" address can still be abandoned. Use verification to remove predictable failures, not to promise a zero-bounce campaign.
Ethically, validate addresses you have a lawful basis to contact. SMTP probing is a technical operation, but it does not create consent, and using validation to launder a purchased list does not make the sending legal.
What Validation Cannot See
- Engagement — a valid address may never open your email.
- Intent — a real person may not want your offer.
- Consent — a deliverable address is not a lawful basis.
- Future state — a mailbox can be closed the day after you verify it.
Verification removes technical uncertainty. Everything else is still marketing.
Testing Your Own Domain First
Before validating a list, validate your sending domain:
- Send a test to a mailbox you control at Gmail, Outlook and a corporate domain.
- Check SPF, DKIM and DMARC alignment.
- Watch the first 200 sends of any new domain closely; warm-up matters more than any single verification run.
A clean list sent from a domain with broken authentication still lands in spam.
Frequently Asked Questions
Does SMTP validation send an email?
No. It stops at RCPT TO, before any message body is transmitted.
Why do some valid addresses come back as risky?
Greylisting, temporary server errors, or anti-harvesting policies. Retry after 24–48 hours.
Can I validate from my own server?
Only if it can reach port 25 and is not rate-limited or blacklisted. Most shared hosts block it.
Is catch-all detection reliable?
It reliably tells you the domain is catch-all. It cannot tell you whether a specific mailbox exists.
What accuracy should I expect?
A good SMTP-based validator is right about 95–99% of the time; the remaining uncertainty is dominated by catch-alls and temporary failures.
SPF, DKIM and DMARC in One Paragraph Each
- SPF lists the servers allowed to send for your domain. It is a DNS TXT record, and it breaks when you exceed the 10-lookup limit.
- DKIM adds a cryptographic signature to each message so the receiver can prove it was not altered. Rotate keys periodically.
- DMARC tells receivers what to do when SPF or DKIM fails (none, quarantine, reject) and sends you reports. Start with
p=none, read the reports, then tighten.
SMTP validation checks the recipient; SPF, DKIM and DMARC determine whether your own mail is trusted on the way out. A verified list sent from a domain with broken authentication still fails. Set up DMARC reporting before you scale a campaign — the reports are how you find the senders you forgot about.
Start Validating
100 SMTP validations/month, no credit card.