验证原因码
BillionVerify API 所有验证结果 reason 字段的完整参考手册——每个原因码的含义及处理建议。
每条验证结果都包含一个 reason 字段,用于说明该邮箱被判定为当前状态的具体原因。参考本文档可构建精准的过滤规则、诊断异常结果,并优化发送策略。
原因码的工作方式
reason 字段与 status 字段一同出现在所有验证响应中:
{
"email": "user@example.com",
"status": "valid",
"reason": "smtp_deliverable"
}原因码是稳定的字符串标识符,可直接用于过滤规则或下游条件逻辑。
valid(有效)
status: "valid" 的邮箱经确认可投递。
| 原因码 | 说明 |
|---|---|
smtp_deliverable | SMTP RCPT 返回 250 OK——邮箱确认可投递。当 Microsoft 365 DBEB 模式确认投递,或 catch-all 域名同时确认了该具体地址时,也会使用此原因码。 |
invalid(无效)
status: "invalid" 的邮箱应从名单中移除——无法投递。
| 原因码 | 说明 |
|---|---|
invalid_syntax | 邮箱地址语法解析失败——本地部分、域名格式有误或缺少 @。 |
no_mx_records | 域名没有 MX 记录(NXDOMAIN 或 MX 查询返回空)。 |
spf_reject_all | 域名没有 MX 记录且 SPF 记录包含 -all——域名明确拒绝所有入站邮件。 |
mailbox_not_found | SMTP 550/5xx 确认远程服务器上该邮箱不存在。 |
host_not_found | MX 主机无响应——主机不可达或不存在。 |
unknown(未知)
status: "unknown" 的邮箱无法得出确定结论。部分原因是临时性的(可重试),其余则属于结构性限制。
| 原因码 | 可重试 | 说明 |
|---|---|---|
smtp_unverifiable | 否 | 该服务商屏蔽自动化 SMTP 验证(Apple iCloud、Microsoft 消费者邮箱、Proton、Tuta),结果基于域名级启发式判断。 |
smtp_blocked | 否 | 远程 SMTP 服务器明确屏蔽或封禁了连接。 |
smtp_eof_blocked | 是 | MX 服务器在发送 banner 之前关闭了连接——通常是 IP 速率限制或 fail2ban 规则触发。 |
smtp_timeout | 是 | SMTP 操作超时(上下文截止时间或取消)。 |
smtp_connection_failed | 否 | 通用 SMTP 连接失败——无更具体的分类命中。 |
smtp_rate_limited | 是 | 远程 SMTP 服务器返回了速率限制响应(421、450、451 或消息限制超额)。 |
smtp_greylisted | 是 | 检测到通用灰名单响应——延迟后可重试。 |
mimecast_greylist | 是 | Mimecast 专属灰名单 / 451 临时失败。 |
proofpoint_ad_lookup | 是 | Proofpoint AD 异步查询进行中(收件人验证时返回 421 4.1.1 临时失败)。 |
policy_temp_fail | 是 | 远程策略强制执行导致通用 4xx 临时失败。 |
google_rate_limit | 是 | Google MX 返回速率限制或临时拒绝响应。 |
google_dmarc_misalignment | 否 | 域名 DMARC 配置不对齐——Google 按 DMARC 策略拒绝。 |
m365_ip_rep_block | 是 | Microsoft 365 因 IP 信誉问题拒绝连接(4.7.650 / 4.7.651 代码)。 |
mailbox_full | 否 | 邮箱存在但已超出配额(SMTP 452 或邮箱已满响应)。 |
mailbox_disabled | 否 | 邮箱存在但已被禁用或停用。 |
dns_timeout | 是 | DNS 或 MX 查询超时——临时解析器问题。 |
dns_lookup_error | 是 | DNS 查询失败,非 NXDOMAIN 错误(SERVFAIL、UDP 超时或解析器错误)。 |
yahoo_api_verified | 否 | Yahoo 注册 API 确认该地址可投递(批量路径)。 |
yahoo_api_not_deliverable | 否 | Yahoo 注册 API 确认该地址不可投递(批量路径)。 |
yahoo_api_error | 是 | Yahoo 注册 API 调用失败——通用错误。 |
yahoo_api_unavailable | 是 | Yahoo 注册 API 不可用(批量级健康失败)。 |
yahoo_api_eof | 是 | Yahoo API 返回提前 EOF——TCP/TLS 短暂中断。 |
yahoo_api_unavailable_after_fallback | 是 | Yahoo API 失败且 SMTP 兜底也失败。 |
carrier_blocked | 否 | 日本运营商域名(docomo.ne.jp、au.com 等)——运营商策略屏蔽 SMTP。 |
internal_verifier_error | 是 | 未分类内部验证器错误——临时故障。 |
rate_limited | 是 | 批量处理中被速率限制(文件任务中 smtp_rate_limited 的别名)。 |
bucket_default_skip_smtp_unknown | 否 | 账户级验证模式设置为跳过 SMTP——结果仅基于域名检查。 |
risky(高风险)
status: "risky" 的邮箱存在中等程度的投递风险。
| 原因码 | 可重试 | 说明 |
|---|---|---|
mx_only_verification_semaphore_timeout | 是 | SMTP 并发信号量超时——MX 兜底验证确认 MX 记录有效,但无法单独验证该邮箱。 |
catchall(全收域)
status: "catchall" 的邮箱属于接受所有地址的域名,无法确认单个地址是否可投递。
| 原因码 | 说明 |
|---|---|
catch_all_domain | 域名确认为 catch-all——随机 RCPT 探测被邮件服务器接受。 |
catch_all_deliverable | Catch-all 域名,且该具体地址的 RCPT 也返回了 250 OK。 |
catch_all_inferred | 从缓存证据推断出 catch-all 状态(间接推断,非实时探测)。 |
m365_internal_relay | Microsoft 365 域名配置为内部中继——所有 RCPT 均被接受,但未单独验证。 |
gateway_accept_all | 安全网关(Mimecast、Proofpoint 等)处于全收模式。 |
forwarding_alias | 邮件转发别名服务(SimpleLogin、Firefox Relay、Duck.com)。 |
region_consumer_accept_all | 已知接受所有入站邮件的区域消费者域名(如 naver.com、daum.net)——跳过 SMTP 探测。 |
bucket_default_skip_smtp_catchall | 账户级验证模式设置为跳过 SMTP catch-all 检测。 |
role(角色邮箱)
status: "role" 的邮箱属于共享收件箱(如 info@、support@、noreply@)。这类地址通常可投递,但互动率较低。
角色邮箱继承其底层 SMTP 检查的 reason——该状态没有专属的原因码。例如,通过 SMTP 验证的角色邮箱会显示 reason: "smtp_deliverable"。
disposable(一次性邮箱)
status: "disposable" 的邮箱属于临时邮箱服务。接受这类邮箱通常会导致低质量注册。
| 原因码 | 说明 |
|---|---|
disposable_domain | 域名在已知一次性/临时邮箱服务商列表中。 |
按原因码过滤的示例
结合 status 和 reason 可实现精准名单分类。例如,仅保留因临时问题而 unknown 的邮箱:
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);
}