多年来,我慢慢开发了一个正则表达式,可以正确验证大多数电子邮件地址,假设它们不使用 IP 地址作为服务器部分。我在几个 PHP 程序中使用它......
多年来,我慢慢开发了一个 正则表达式 ,可以正确验证 大多数 电子邮件地址,假设它们不使用 IP 地址作为服务器部分。
我在几个 PHP 程序中使用它,大多数时候它都能正常工作。但是,有时有人会联系我,说某个使用它的网站有问题,最后我不得不做出一些调整(最近我意识到我不允许使用四个字符的 TLD )。
您所见过的用于验证电子邮件的最佳正则表达式是什么?
我已经看到了几种使用包含多个较短表达式的函数的解决方案,但我宁愿在简单函数中使用一个长而复杂的表达式,而不是在更复杂的函数中使用几个短表达式。
完全符合 RFC 822 的正则表达式 由于 其长度而效率低下且晦涩难懂。幸运的是,RFC 822 已被两次取代,电子邮件地址的当前规范是 RFC 5322 。RFC 5322 导致的正则表达式只要花几分钟研究一下就可以理解,并且对于实际使用来说足够高效。
页面顶部找到, http://emailregex.com/ 但它使用的 IP 地址模式在互联网上流传,存在一个错误,允许 00
在点分隔地址中使用任何无符号字节十进制值,这是非法的。其余部分似乎与 RFC 5322 语法一致,并通过了使用 的多项测试 grep -Po
,包括域名、IP 地址、错误地址以及带引号和不带引号的帐户名的情况。
纠正 00
IP 模式中的错误后,我们获得了一个可行且相当快的正则表达式。(实际代码请抓取渲染版本,而不是 markdown。)
(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\。[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\'(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*\')@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\。)+[a-z0-9](?:[a-z0-9-]*[a- z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])
或者:
(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])
Perl 和 PCRE(例如 PHP 中使用的正则表达式库)中更复杂的模式可以 毫无障碍地正确解析 RFC 5322。Python 和 C# 也可以做到这一点,但它们使用的语法与前两者不同。但是,如果您被迫使用许多功能较弱的模式匹配语言之一,那么最好使用真正的解析器。
还必须了解,按照 RFC 进行验证绝对不会告诉您该地址是否确实存在于提供的域中,或者输入该地址的人是否是其真正的所有者。人们一直以这种方式将其他人注册到邮件列表中。解决这个问题需要一种更复杂的验证方式,即向该地址发送一条消息,其中包含一个确认令牌,该令牌应在与该地址相同的网页上输入。
确认令牌是知道您已获得输入者地址的唯一方法。这就是为什么大多数邮件列表现在都使用该机制来确认注册的原因。毕竟,任何人都可以输入 [email protected]
,这甚至会被解析为合法,但不太可能是另一端的人。
对于 PHP,您 不 我引用的《 用 PHP 验证电子邮件地址的正确方法》 中给出的模式
存在这样的危险:普遍的使用和广泛的混乱编码将建立一个事实上的电子邮件地址标准,而该标准比记录的正式标准更为严格。
都不够智能 RFC 822 ,更不用说 RFC 5322 了。 这个模式 却可以。
如果您想变得花哨和迂腐, 请实现一个完整的状态引擎 。正则表达式只能充当基本的过滤器。正则表达式的问题在于,告诉某人他们的完全有效的电子邮件地址无效(误报),因为您的正则表达式无法处理它,从用户的角度来看,这只是粗鲁和不礼貌的。为此目的的状态引擎可以验证甚至更正原本被视为无效的电子邮件地址,因为它会根据每个 RFC 拆解电子邮件地址。这可以提供更令人愉悦的体验,例如
指定的电子邮件地址“myemail@address,com”无效。您指的是“ [email protected] ”吗?
另请参阅 验证电子邮件地址 ,包括评论。或 比较电子邮件地址验证正则表达式 .
Debuggex 演示