推荐正则^[a-za-z0-9][a-za-z0-9._%-]*@[a-za-z0-9][a-za-z0-9.-]*[a-za-z0-9](?:.[a-za-z0-9][a-za-z0-9.-]*[a-za-z0-9])*\.[a-za-z]{2,}(?:\.[a-za-z]{2,})*$,可正确匹配.com.cn等多级域名后缀,兼顾首尾字符限制与层级递归。

支持 .com.cn、.net.cn 等多级域名后缀
常见正则会把 example@company.com.cn 当作非法,因为只匹配单个点(.)加一个顶级域,而 .com.cn 实际含两个点、两级后缀。关键不是“多加一个 .”,而是让域名部分能递归匹配“标签+点”的组合。
推荐用这个结构:/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}(?:.[a-zA-Z]{2,})*$/
-
[a-zA-Z0-9.-]+.匹配主域名(如company.),允许中间有连字符 -
[a-zA-Z]{2,}匹配第一级后缀(如com) -
(?:.[a-zA-Z]{2,})*非捕获组,支持零次或多次追加二级后缀(如.cn),避免额外分组开销
注意:不要写成 .([a-zA-Z]{2,}){2,}——这会错误要求至少两个后缀,且无法区分层级。
避免误杀单字母用户名或单数字域名
像 i@fufuok.com 或 fufu@9.cn 被多数正则拒之门外,是因为用了 [a-zA-Z0-9]+ 但没放开首字符限制,或对域名部分加了多余长度约束(比如 {3,})。
修正要点:
- 本地部分(@前)用
[a-zA-Z0-9][a-zA-Z0-9._%-]*:确保开头是字母或数字,后面才允许符号 - 域名主体(@后到倒数第一个点)用
[a-zA-Z0-9][a-zA-Z0-9.-]*[a-zA-Z0-9]:强制首尾为字母数字,禁止以-或.开头/结尾 - 去掉全局长度限制(如
{1,20}),长度校验应单独用strlen()控制
示例片段:/^[a-zA-Z0-9][a-zA-Z0-9._%-]*@[a-zA-Z0-9][a-zA-Z0-9.-]*[a-zA-Z0-9](?:.[a-zA-Z0-9][a-zA-Z0-9.-]*[a-zA-Z0-9])*.[a-zA-Z]{2,}(?:.[a-zA-Z]{2,})*$/
为什么不用 RFC 5322 全量正则?
网上常提的超长 RFC 兼容正则(如带引号、括号、IPv4 域名等)在 PHP 中实际几乎不可用:
- PCRE 引擎对嵌套断言支持有限,
preg_match()可能直接报PREG_BACKTRACK_LIMIT_ERROR - 匹配耗时随字符串长度指数增长,
user@very.long.domain.name.example.org就可能卡住 - 真实业务中,没人用
"John Doe"@example.com这种带空格引号的邮箱注册
真正需要兼容的,是企业常用但非标准的后缀(如 .group、.tech、.xyz),这些只需放宽 [a-zA-Z]{2,} 为 [a-zA-Z]{2,6} 即可,不必上 RFC。
filter_var() 是补位,不是替代
filter_var($email, FILTER_VALIDATE_EMAIL) 能识别 a@b.co.uk 和 test@localhost,但它不校验长度、不拒绝空格、也不阻止 user@..com 这类明显错误。
建议组合用法:
- 先用宽松正则快速筛掉明显非法格式(如无 @、连续点、开头点)
- 再用
filter_var()做二次确认,尤其对多级后缀更稳 - 最后检查总长(
strlen($email) )和本地部分长度(≤64 字符)
单独依赖 filter_var() 会放过 user@example.com(开头空格);单独依赖正则又容易漏掉 admin@mail.example.co.jp ——两者缺一不可。
最易被忽略的是:正则里所有点号(.)都必须转义为 .,否则会变成“任意字符”通配符,导致 test@domainXcom 也能过检。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











