本文目录导读:

不完全可靠,存在局限性。
PHP 中使用正则表达式校验邮箱格式,只能保证 格式上基本符合规范,但无法保证 该邮箱真实存在、可以接收邮件 或 符合某些特定服务的规则。
正则能做什么(靠谱的地方)
- 检查基本结构:确保有 符号, 前后有字符,有点 分隔域名后缀。
- 过滤明显错误:
abc@、@.com、user@domain(缺少顶级域名)等。 - 快速过滤垃圾输入:防止用户乱填。
一个常见的中等强度正则示例:
$email = "user@example.com";
$pattern = '/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/';
if (preg_match($pattern, $email)) {
echo "格式正确";
} else {
echo "格式错误";
}
这个正则已经能过滤掉大多数乱填的输入。
正则做不到的地方(不靠谱的原因)
✅ 合法但过长的邮箱
- 正则通常不检查长度,但 RFC 5321 规定邮箱地址总长度不能超过 254 个字符,局部部分(@ 前)不超过 64 个字符,正则很难优雅地检查这个。
✅ 合法的特殊字符
- 邮箱允许很多特殊字符,如 (双引号包裹)、、空格、 等。
"john.doe"@example.com或user+tag@example.co.uk是合法邮箱,但许多不严格的正则会拒绝它们。
✅ IP 地址作为域名
user@[192.168.1.1]是合法格式(很少见),常规正则会认为它是错的。
✅ 新顶级域名
- 现在顶级域名可以是任意长度,
.info、.在线、.公司、.london。 - 如果你的正则只允许 2-4 个字母的后缀(如
\.\w{2,4}$),就会误杀很多真实邮箱(someone@example.london)。
⚠️ 点号位置限制
- 按照标准,中文 (句号)是不允许的,域名中也不能连续出现两个点 (如
user@example..com非法),好一点的正则会处理这个,但简单正则不会。
更专业的建议:用 PHP 内置函数
PHP 原生提供了 filter_var() 函数,比你自己写正则更靠谱:
$email = "user@example.com";
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
echo "邮箱格式有效";
} else {
echo "邮箱格式无效";
}
为什么推荐 filter_var?
- 它基于 RFC 规范 实现,处理了上述大部分复杂情况。
- 它考虑了长度限制、特殊字符、顶级域名等多方面规则。
- 性能好,经过充分测试。
真正「可靠」的校验流程
如果你需要 业务级可靠性(比如注册、发送邮件),正则只是第一道防线,完整的流程应该是:
| 步骤 | 操作 | 可靠性说明 |
|---|---|---|
| 前端检查 | 用正则初步过滤明显错误的输入 | 低(仅防误触) |
| 后端检查 | 使用 filter_var($email, FILTER_VALIDATE_EMAIL) |
中高(格式合规) |
| DNS 检查 | 使用 checkdnsrr(array_pop(explode('@', $email)), 'MX') 检查域名有无邮件交换记录 |
高(域名真实) |
| 发送验证邮件 | 向该邮箱发送一个含唯一验证链接的邮件,用户点击才激活账号 | ✅ 最可靠 |
示例代码(步骤 2 + 3):
function validateEmail($email) {
// 1. 格式校验
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
return false;
}
// 2. 取出域名部分
$domain = substr(strrchr($email, '@'), 1);
// 3. 检查域名是否有 MX 记录(可能存在)
if (!checkdnsrr($domain, 'MX')) {
// 注意:有些域名有A记录但没有MX也能收信,所以这个检查不是绝对
// 但可以过滤掉大量不存在或未配置邮箱的域名
return false;
}
return true;
}
| 场景 | 建议 |
|---|---|
| 简单表单校验(非关键功能) | 用 filter_var() 就够了 |
| 注册/支付/订阅等重要业务 | 必须 DNS 检查 + 发送验证邮件 |
| 只依赖自己写的正则 | ❌ 不可靠,建议弃用 |
一句话结论: 正则校验邮箱格式 作为初步过滤是可靠的,但要达到 真正业务可靠,必须结合 DNS 检查和邮件验证,建议直接使用 PHP 内置的 filter_var 替代手写正则。