laravel 的 email 验证仅做 rfc 格式检查,不验证邮箱真实性;需真实校验应结合验证码发送、异步清洗或新增 deliverable_email 规则,避免覆盖原生规则,并防范临时邮箱。

email规则默认不验证邮箱格式是否真实存在
Laravel 的 email 验证规则只做基础 RFC 格式检查(比如是否有 @、域名部分是否合法),**不会发 DNS 查询,也不会连 SMTP 服务器**。所以 test@invalid 或 user@no-such-domain-12345.com 都能通过。
如果你需要更严格的校验,得自己加逻辑——但别急着写正则或调 API,先看场景:
- 前端表单提交?用
email+ 前端 type="email" 已足够,防的是手误,不是钓鱼 - 用户注册/密码重置?必须配合邮箱发送验证码,这才是真实性的最终验证手段
- 后台批量导入联系人?建议跳过实时校验,改用异步队列 + 第三方服务(如 MailboxValidator)批量清洗
自定义 email 规则时别直接覆盖内置规则
有人会想:我写个 strict_email 然后在 App\Providers\AppServiceProvider::boot() 里用 Validator::extend() 替换掉原生 email ——这很危险。
原因有三:
- Laravel 内部很多地方(比如
ResetPasswordRequest)硬编码依赖email规则语义,替换后可能让认证流程静默失败 - 第三方包(如 Jetstream、Fortify)也依赖原生行为,一改就崩
- 你写的“严格”逻辑很可能只是多查了个 MX 记录,而 MX 存在 ≠ 邮箱可收信(比如
admin@github.com就收不到外部邮件)
正确做法是:新增一个独立规则名,比如 deliverable_email,并在明确需要它的场景中显式使用。
用 filter_var + dns_get_record 做轻量级预检(慎用)
如果真要在 API 层加一层快速过滤,可以用 PHP 原生函数组合,但要注意边界:
-
filter_var($email, FILTER_VALIDATE_EMAIL)是必须的第一步,它比正则快且准 - 提取域名后调
dns_get_record($domain, DNS_MX)查 MX 记录,但要设超时(默认无超时,可能卡住整个请求) - 不能查 A 记录代替 MX —— 很多企业邮箱用的是第三方服务商(如 Google Workspace),A 记录指向自己官网,MX 才指向 gmail-smtp-in.l.google.com
- 本地开发环境(如 Valet、Docker)常禁 DNS 查询,
dns_get_record会直接返回 false,需 fallback
示例片段(放在自定义验证规则里):
if (! filter_var($value, FILTER_VALIDATE_EMAIL)) {
return false;
}
$domain = explode('@', $value)[1];
// 注意:生产环境务必加 try/catch 和超时控制
if (! function_exists('dns_get_record') || ! @dns_get_record($domain, DNS_MX)) {
return false;
}
真正要防的不是格式错误,而是临时邮箱和一次性邮箱
攻击者不用伪造格式,直接用 xxx@guerrillamail.com 或 yyy@10minutemail.net 注册,你的系统照样收得到验证邮件——但用户几小时后就失联。
这类问题靠格式校验无解,得用名单策略:
- 维护一个已知一次性邮箱域名列表(如
mailinator.com、trashmail.com),用Str::endsWith($email, $disposableDomains)快速拦截 - 用开源库如
email-validator(PHP 版)集成黑名单 + 语法 + DNS 检查,但它仍不保证 100% 可投递 - 最稳的方式:所有注册流程强制走双因素(邮箱 + 手机短信 / TOTP),临时邮箱无法完成闭环
别把邮箱当成身份凭证本身,它只是触发验证的通道。通道是否通畅,得靠后续动作来证明,而不是在 POST body 里反复抠字符。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











