Verification Reasons
Complete reference for all verification reason codes returned by BillionVerify API — what each reason means and how to act on it.
Every verification result includes a reason field that explains why the email received its status. Use this reference to build precise filtering logic, diagnose unexpected results, and tune your sending strategy.
How reasons work
The reason field appears in all verification responses alongside the status field:
{
"email": "user@example.com",
"status": "valid",
"reason": "smtp_deliverable"
}Reasons are stable string identifiers — you can use them directly in filtering rules or downstream conditional logic.
Valid
Emails with status: "valid" are confirmed deliverable.
| Reason | Description |
|---|---|
smtp_deliverable | SMTP RCPT returned 250 OK — mailbox confirmed deliverable. Also produced when Microsoft 365 DBEB mode confirms delivery or when a catch-all domain additionally confirms the specific address. |
Invalid
Emails with status: "invalid" should be removed from your list — delivery is not possible.
| Reason | Description |
|---|---|
invalid_syntax | Email address fails syntax parsing — malformed local part, domain, or missing @. |
no_mx_records | Domain has no MX records (NXDOMAIN or empty MX lookup result). |
spf_reject_all | Domain has no MX records and an SPF record with -all — the domain explicitly rejects all inbound mail. |
mailbox_not_found | SMTP 550/5xx confirmed the mailbox does not exist on the remote server. |
host_not_found | The MX hostname did not respond — host unreachable or non-existent. |
Unknown
Emails with status: "unknown" could not be conclusively verified. Some of these are temporary (retryable); others represent structural limitations.
| Reason | Retryable | Description |
|---|---|---|
smtp_unverifiable | No | The provider blocks automated SMTP verification (Apple iCloud, Microsoft consumer, Proton, Tuta). Result is based on domain-level heuristics. |
smtp_blocked | No | The remote SMTP server explicitly blocked or blacklisted the connection. |
smtp_eof_blocked | Yes | The MX closed the connection before sending a banner — typically a per-IP rate limiter or fail2ban rule. |
smtp_timeout | Yes | SMTP operation timed out (context deadline or cancellation). |
smtp_connection_failed | No | Generic SMTP connection failure — no more specific class matched. |
smtp_rate_limited | Yes | Remote SMTP server returned a rate-limit response (421, 450, 451, or messaging limit exceeded). |
smtp_greylisted | Yes | Generic greylisting response detected — retry after a delay. |
mimecast_greylist | Yes | Mimecast-specific greylist / 451 temporary failure. |
proofpoint_ad_lookup | Yes | Proofpoint AD async lookup in progress (421 4.1.1 temp-fail during recipient validation). |
policy_temp_fail | Yes | Generic 4xx temporary failure from remote policy enforcement. |
google_rate_limit | Yes | Google MX returned a rate-limit or temporary rejection response. |
google_dmarc_misalignment | No | Domain DMARC configuration is misaligned — Google rejects based on DMARC policy. |
m365_ip_rep_block | Yes | Microsoft 365 rejected the connection due to IP reputation (4.7.650 / 4.7.651 codes). |
mailbox_full | No | Mailbox exists but is over quota (SMTP 452 or full inbox response). |
mailbox_disabled | No | Mailbox exists but has been disabled or deactivated. |
dns_timeout | Yes | DNS or MX lookup timed out — transient resolver issue. |
dns_lookup_error | Yes | DNS lookup failed with a non-NXDOMAIN error (SERVFAIL, UDP timeout, or resolver error). |
yahoo_api_verified | No | Yahoo Registration API confirmed the address is deliverable (batch path). |
yahoo_api_not_deliverable | No | Yahoo Registration API confirmed the address is not deliverable (batch path). |
yahoo_api_error | Yes | Yahoo Registration API call failed — general error. |
yahoo_api_unavailable | Yes | Yahoo Registration API was unavailable (batch-level health failure). |
yahoo_api_eof | Yes | Yahoo API returned early EOF — transient TCP/TLS drop. |
yahoo_api_unavailable_after_fallback | Yes | Yahoo API failed and the SMTP fallback also failed. |
carrier_blocked | No | Japanese carrier domain (docomo.ne.jp, au.com, etc.) — SMTP is blocked by carrier policy. |
internal_verifier_error | Yes | Unclassified internal verifier error — transient failure. |
rate_limited | Yes | Email was rate-limited during batch processing (alias for smtp_rate_limited in file jobs). |
bucket_default_skip_smtp_unknown | No | Account-level verification mode is set to skip SMTP — result is based on domain checks only. |
Risky
Emails with status: "risky" have a moderate deliverability risk.
| Reason | Retryable | Description |
|---|---|---|
mx_only_verification_semaphore_timeout | Yes | SMTP concurrency semaphore timed out — MX-only fallback confirmed valid MX records but the mailbox could not be individually verified. |
Catch-all
Emails with status: "catchall" belong to domains that accept mail for all addresses. Individual deliverability cannot be confirmed.
| Reason | Description |
|---|---|
catch_all_domain | Domain confirmed as catch-all — random RCPT probe accepted by the mail server. |
catch_all_deliverable | Catch-all domain, and the specific address also returned 250 OK on RCPT. |
catch_all_inferred | Catch-all status inferred from cached evidence (indirect, not a live probe). |
m365_internal_relay | Microsoft 365 domain configured as internal relay — all RCPT accepted but not individually verified. |
gateway_accept_all | Security gateway (Mimecast, Proofpoint, etc.) is in accept-all mode. |
forwarding_alias | Email forwarding alias service (SimpleLogin, Firefox Relay, Duck.com). |
region_consumer_accept_all | Regional consumer domain (e.g. naver.com, daum.net) known to accept all inbound — SMTP probe is skipped. |
bucket_default_skip_smtp_catchall | Account-level verification mode is set to skip SMTP catch-all detection. |
Role
Emails with status: "role" belong to shared inboxes (e.g. info@, support@, noreply@). These addresses are typically deliverable but have low engagement.
Role addresses inherit the reason from their underlying SMTP check — no dedicated reason codes exist for this status. For example, a role address that passes SMTP will show reason: "smtp_deliverable".
Disposable
Emails with status: "disposable" belong to temporary email services. Accepting these usually leads to low-quality signups.
| Reason | Description |
|---|---|
disposable_domain | Domain is listed as a known disposable / temporary email provider. |
Using reasons in filtering
You can combine status and reason for precise list segmentation. For example, to keep unknown emails that are only unknown due to temporary issues:
function isRetryableUnknown(result) {
const retryableReasons = new Set([
'smtp_eof_blocked', 'smtp_timeout', 'smtp_rate_limited',
'smtp_greylisted', 'mimecast_greylist', 'proofpoint_ad_lookup',
'policy_temp_fail', 'google_rate_limit', 'm365_ip_rep_block',
'dns_timeout', 'dns_lookup_error', 'yahoo_api_error',
'yahoo_api_unavailable', 'yahoo_api_eof',
'yahoo_api_unavailable_after_fallback', 'internal_verifier_error',
'rate_limited', 'mx_only_verification_semaphore_timeout',
]);
return result.status === 'unknown' && retryableReasons.has(result.reason);
}