api, #security, #webdev, #discuss
The 38-Minute Lie
On October 6, 2026, at 16:19:39 UTC, I called an email validation endpoint with one address: test@gmail.com. The response came back in under 400 milliseconds. valid: true. mx_found: true. smtp_verified: null. Deliverability score: 75. That null should have been a warning. It wasn't.
curl --request GET \
--url 'https://email-validator112.p.rapidapi.com/api/v1/validate?email=test%40gmail.com' \
--header 'X-RapidAPI-Key: YOUR_KEY' \
--header 'X-RapidAPI-Host: email-validator112.p.rapidapi.com'
Three days earlier I had shipped a welcome sequence to 50 freshly collected leads. Every address had passed my SMTP probe. Every handshake returned 250 OK. I clicked send, made coffee, and watched the dashboard. By 16:57 — 38 minutes later — 12 emails had bounced. Hard bounces. Full-sender-reputation-damage bounces. They were not spam-folder disappearances. They were not "maybe later" deferrals. That's a 24% bounce rate from addresses that had verbally promised they were real.
I sat there with cold coffee and a warmer inbox full of delivery failure notifications. The SMTP dialog had lied.
This article is part of my Email Validator Experiments series, where I treat the inbox less like a delivery address and more like an email gatekeeper that answers to reputation systems, not just protocol politeness.
What 250 OK Actually Promises
Here is the exact payload I got back for test@gmail.com:
{
"email": "test@gmail.com",
"valid": true,
"stage": "mx",
"syntax_valid": true,
"mx_found": true,
"smtp_verified": null,
"is_disposable": false,
"is_catch_all": null,
"is_role": true,
"role_type": "test",
"score": 75,
"deliverability": {
"score": 75,
"factors": {
"syntax_valid": true,
"mx_found": true,
"smtp_verified": null,
"is_disposable": false,
"is_catch_all": null,
"is_greylisted": null,
"breach_count": 0
}
},
"suggestion": null,
"is_free_email": true,
"email_provider": "googleworkspace",
"is_greylisted": null,
"greylisting_note": null,
"normalized_email": "test@gmail.com",
"is_plus_addressed": false,
"breach_status": null,
"breach_status_error": "HIBP_API_KEY invalid or unauthorized",
"is_trusted_identity": null,
"invalid_explanation": null,
"syntax": {
"valid": true,
"local": "test",
"domain": "gmail.com"
},
"mx": {
"has_mx": true,
"records": [
{"priority": 5, "exchange": "gmail-smtp-in.l.google.com"},
{"priority": 10, "exchange": "alt1.gmail-smtp-in.l.google.com"},
{"priority": 20, "exchange": "alt2.gmail-smtp-in.l.google.com"},
{"priority": 30, "exchange": "alt3.gmail-smtp-in.l.google.com"},
{"priority": 40, "exchange": "alt4.gmail-smtp-in.l.google.com"}
],
"best": "gmail-smtp-in.l.google.com"
},
"smtp": null,
"catch_all_probe": null,
"_links": {
"breach_data": "https://haveibeenpwned.com"
},
"identity_graph": {
"email": "test@gmail.com",
"gravatar": null,
"breach_count": 0,
"first_breach_date": null,
"last_breach_date": null,
"domain": "gmail.com",
"fetched_at": "2026-10-06T16:19:39.385501+00:00"
},
"provenance": {
"syntax": {"source": "internal", "confidence": 1.0},
"mx": {"source": "DNS resolver", "confidence": 0.95},
"smtp_verified": {"source": "SMTP probe", "confidence": 0.9},
"breach_status": {"source": "Have I Been Pwned", "confidence": 0.95}
},
"fetched_at": "2026-10-06T16:19:39.385521+00:00"
}
Let me walk through what matters. The API says syntax_valid: true and mx_found: true. The MX records are real, five of them, with priorities 5, 10, 20, 30, and 40, all pointing at Google's gmail-smtp-in.l.google.com infrastructure. So far, so good. The domain accepts mail.
But smtp_verified is null. Not false. Null. That distinction is the entire story. A null SMTP verification means the validator reached the MX layer and stopped short of a live mailbox probe. Maybe greylisting got in the way. Maybe the provider throttled the handshake. Maybe the probe simply timed out. Whatever the reason, the API is honest about what it doesn't know. My old pipeline wasn't.
The score is 75. That feels passing. It isn't. In my experience, anything below 85 for a B2C welcome flow is a reputation gamble, and role addresses like test@ score too high at 75. The API correctly flags is_role: true with role_type: "test", which is exactly the kind of address that accepts mail today and rots your list tomorrow. A test@ mailbox is not a customer. It's a placeholder that silently destroys your sender score.
The breach data is where it gets worse. breach_count: 0, but breach_status_error: "HIBP_API_KEY invalid or unauthorized". So the count is zero by default, not by investigation. If you're using breach status as a trust signal, a missing key silently downgrades your confidence. I had the key sitting in a .env file I forgot to load. That zero meant "we didn't check," not "this identity is clean." The provenance block even tags breach status as coming from Have I Been Pwned with 0.95 confidence, but only if the key is there.
The API also classifies is_free_email: true and email_provider: "googleworkspace". That's useful for segmentation. A B2B lead scoring model wants to know if the address came from a personal Gmail or a workspace domain. But that classification doesn't tell you whether the mailbox is actively monitored. A free email provider with a null SMTP check is just a politely formatted question mark.
The uncomfortable fact is this: 250 OK from a raw SMTP probe is a handshake, not a contract. It says "I heard you." It does not say "I will deliver this to a human who wants it." I was asking the protocol the wrong question.
This matches what I found in the related experiment: SMTP 250 OK means nothing. 12 of 50 validated emails still bounced. The numbers matched that experiment exactly, and the cause was the same. The only difference was the validator explaining why.
The Trust Score That 250 OK Can't Build
The Glashütte Trash Clock is a fully functioning pendulum clock built from trash in Saxony. It runs for about thirty minutes, then stops. Its inventor, Niklas Roy, even created a new time scale around it (GTC, blending GMT and UTC) because the clock is honest about its limits. It doesn't pretend to keep perfect time forever. It keeps time for half an hour, strikes a gong, and quits.
SMTP 250 OK is the Glashütte Trash Clock of deliverability signals. It confirms the mechanism exists. It does not confirm the mechanism will still be working when your message actually matters. A probe at 16:19 proves nothing about the mailbox at 16:57. By then it is often disabled, full, or abandoned. My 38-minute window proved that. The handshake was fresh. The list was stale.
The Oracle layoff email story works the same way. In September 2026, Oracle sent termination notices at 6 a.m. to staff whose workforce had already dropped by roughly 21,000 employees (about 13%) during fiscal 2026. The restructuring cost ballooned to $2.8 billion. Those emails were almost certainly delivered. 250 OK sang for every one of them. But delivery is not the same as outcome. A delivered message destroys trust, wastes attention, and signals that you didn't think before you sent.
The FIFA World Cup 2026 study from the University of Bristol makes the same point with different math. Researchers analyzed 172.6 hours of live play across 104 matches and recorded 93,000 visible brand appearances. Unhealthy food and drink brands accounted for 65,722 of those. Viewers saw junk-food, alcohol, gambling, or speculative branding every seven seconds, roughly nine ads per minute. Nearly six billion people engaged with the tournament. The signal was technically transmitted. It was also buried in noise so dense that meaning collapsed.
That's what a list full of 250 OK role addresses and breached inboxes looks like to a modern ESP. Every message is technically accepted. Most of them are noise. Enough noise, and the inbox stops treating you like a sender and starts treating you like a billboard in a stadium full of billboards. Your reputation becomes the cost of admission.
This is why I now care about is_trusted_identity. The composite is simple on paper: SMTP verified, not disposable, not breached. But the nulls matter. When smtp_verified is null and breach_status is null because the HIBP key is missing, is_trusted_identity becomes null too. The API refuses to fake confidence. My old pipeline faked it for me by treating 250 OK as a boolean seal of approval.
A real trust score has to absorb uncertainty, not hide it. A 75 with two nulls is not "probably fine." It's "we don't know enough." I had been routing those addresses straight to the welcome flow because the number was green-ish. Green-ish is how you get a 24% bounce rate.
If you want the full breakdown of how breach data interacts with deliverability, read the companion piece: I tested 500 emails against HIBP. My validator found a major flaw.
What I Wired Into the Pipeline
After the 38-minute disaster, I rewrote the validation gate. The new rules are not complicated, but they are unforgiving.
First, any address with smtp_verified not explicitly true goes to a secondary queue for a second probe or a low-risk test send. It is not blocked. It is not trusted. Null is not a verdict; it's a postponement. I don't care if the syntax is perfect and the MX record gleams.
Second, role addresses get a score penalty. test@, admin@, noreply@, support@: these accept mail. They also rotate owners, get ignored, or trigger spam traps. The API's is_role flag is now a hard filter for high-value flows. A role account is not a person.
Third, breach status is no longer optional. I load the HIBP key correctly now. An address that is breached is not automatically evil (people reuse emails forever), but it is an identity signal. If I'm going to claim an is_trusted_identity check, I have to actually run it. A zero breach count without a working key is a lie I tell myself.
Fourth, catch-all domains and greylisted hosts get their own path. A catch-all accepts everything, which is indistinguishable from a real mailbox at the SMTP layer. Greylisting delays the probe, which looks like a failure if your timeout is too short. Both need follow-up logic, not a single snapshot.
Fifth, syntax suggestions save more leads than I expected. gmial.com → gmail.com is the famous one, but I've also seen .con, .cm, and swapped local/domain pairs. A suggestion with high confidence gets auto-corrected before validation; low confidence gets shown to the user.
I also split free-email detection from B2B scoring. is_free_email: true with email_provider: "googleworkspace" tells me this is a personal Gmail, not a corporate workspace. For a SaaS trial, that's a useful signal. For a sales-led motion, it changes the nurture track entirely.
The result so far: bounce rates under 4% on the same lead source. The remaining bounces are mostly soft, full mailboxes, temporary greylisting, or user-driven spam-folder routing. Hard bounces from syntactically dead addresses are nearly gone.
How to use Email Validator API
The validator is straightforward. You send an email, you get a verdict, and you decide what to do with the uncertainty.
With curl:
curl --request GET \
--url 'https://email-validator112.p.rapidapi.com/api/v1/validate?email=test%40gmail.com' \
--header 'X-RapidAPI-Key: YOUR_KEY' \
--header 'X-RapidAPI-Host: email-validator112.p.rapidapi.com'
With Python:
import requests
url = "https://email-validator112.p.rapidapi.com/api/v1/validate"
params = {"email": "test@gmail.com"}
headers = {
"X-RapidAPI-Key": "YOUR_KEY",
"X-RapidAPI-Host": "email-validator112.p.rapidapi.com"
}
response = requests.get(url, headers=headers, params=params)
data = response.json()
print(data["score"])
print(data["deliverability"]["factors"])
print(data.get("breach_status_error"))
The response is the same JSON I quoted above. I keep the raw payload in my validation logs because the score alone is not enough. You want the factors — syntax_valid, mx_found, smtp_verified, is_disposable, is_catch_all, is_greylisted, breach_count — so you can build your own thresholds.
The RapidAPI listing is here: https://rapidapi.com/On13uka/api/email-validator112?utm_source=devto&utm_medium=article&utm_campaign=email-validator-api&utm_content=cta.
The GitHub repo with examples and issue tracking is here: https://github.com/On13uka/email-validator-api.
The Question 250 OK Can't Answer
There is one gap I still haven't closed. The validator tells me whether an address is structurally sound and whether its identity looks trustworthy. It does not tell me whether the content I send will survive the recipient's attention span, their spam-folder habits, or their inbox provider's content filters.
On March 3, I shipped a welcome flow that treated SMTP 250 OK as gospel. The first send hit a 24% bounce rate. Mailgun suspended our dedicated IP for 48 hours. We lost roughly $1,400 in expected trial conversions. The addresses were technically valid and the content was technically delivered. The relationship still broke.
That failure has no clean lesson attached. Sometimes the protocol works and the human doesn't. Sometimes the mailbox exists and the message shouldn't have been sent. The validator is an email gatekeeper, not a copywriter.
I'm still not sure whether scoring role addresses as 75 is too generous, or whether I should push them below 60 and force manual review. The API gives me the flag. The threshold is my call. And that's the real work: not getting a green light from an SMTP server, but deciding what green actually means for your reputation.
What's the worst bounce-rate surprise you've shipped after an SMTP 250 OK told you the address was clean?
Top comments (0)