Email verification is one of those things that sounds simple until you actually try to build it. You send a SMTP command, check the response code, done — right?
Wrong. Gmail, Yahoo, Outlook, iCloud, and QQ together cover over 80% of all email addresses on the internet, and all of them have blocked SMTP-based verification. This guide explains how email verification actually works in 2025, and how to integrate it correctly.
There are several layers of verification, applied in order from cheapest to most accurate:
Most email verification services stop at layer 4. The problem: layers 1-3 are fast but low-accuracy. Layer 4 fails silently for all major consumer providers. Layer 5 is the only reliable method for Gmail, Yahoo, iCloud, QQ, and the others.
| Provider | SMTP Behavior | Result |
|---|---|---|
| Gmail | Rejects all standard SMTP commands probes | Always "unknown" |
| Yahoo | Catch-all — accepts everything | Always "valid" (false positives) |
| iCloud | Accepts all, returns 250 OK | Always "valid" (false positives) |
| QQ Mail | Blocks external SMTP connections | Always "unknown" |
| Outlook/Hotmail | Rate-limits and returns inconsistent results | Unreliable |
The reliable approach is to query each provider's native APIs:
import requests
API_KEY = "mvp_your_key" # Get free at checkmail1.com
def verify(email):
r = requests.get(
"https://checkmail1.com/api/verify",
params={"email": email},
headers={"X-API-Key": API_KEY}
)
return r.json()
result = verify("[email protected]")
print(result["status"]) # valid / invalid / unknown
print(result["score"]) # 0-100
print(result["confidence"]) # high / medium / low
const fetch = require('node-fetch');
async function verify(email) {
const res = await fetch(
`https://checkmail1.com/api/verify?email=${encodeURIComponent(email)}`,
{ headers: { 'X-API-Key': 'mvp_your_key' } }
);
return res.json();
}
verify('[email protected]').then(r => {
console.log(r.status, r.score, r.confidence);
});
<?php
function verifyEmail($email, $apiKey) {
$url = 'https://checkmail1.com/api/verify?email=' . urlencode($email);
$ctx = stream_context_create(['http' => [
'header' => "X-API-Key: $apiKey
"
]]);
return json_decode(file_get_contents($url, false, $ctx), true);
}
$result = verifyEmail('[email protected]', 'mvp_your_key');
echo $result['status']; // valid / invalid / unknown
For large lists, use the bulk upload endpoint — upload a CSV or TXT file and download results when complete:
# Upload a file
curl -X POST https://checkmail1.com/api/batch/upload \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-F "[email protected]"
# Returns: {"job_id": "abc123", "total_emails": 50000, "status": "queued"}
# Poll for progress
curl https://checkmail1.com/api/batch/jobs/abc123 \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
# Download results when done
curl "https://checkmail1.com/api/batch/jobs/abc123/download?token=YOUR_TOKEN" \
-o results.csv
| Field | Values | Description |
|---|---|---|
| status | valid / invalid / risky / unknown | Overall verdict |
| valid | true / false / null | Boolean result |
| score | 0–100 | Quality/confidence score |
| confidence | high / medium / low | How reliable the result is |
| checks.google | {checked, exists} | Google-specific result |
| credits_remaining | integer | Credits left after this request |
CheckMail1 uses credit-based pricing — pay once, use whenever. No subscriptions, no monthly fees. Credits never expire.
Payment accepted via USDT TRC20 — no credit card required.
100 free credits on signup. Accurate results for Gmail, Yahoo, iCloud, QQ, Outlook, and 50+ more providers.
Get Free API Key →