多年来,我一直在慢慢开发一个regular expression来验证大多数电子邮件地址是否正确,假设它们不使用IP地址作为服务器部分。
我在几个PHP程序中使用它,而且它大部分时间都在工作。然而,有时我会被一个在使用它的网站上遇到问题的人联系,最后我不得不做一些调整(最近我意识到我不允许4字符的tld)。
对于验证电子邮件,您所拥有或见过的最佳正则表达式是什么?
我已经看到一些解决方案使用了使用几个较短表达式的函数,但是我宁愿在简单函数中使用一个长的复杂表达式,而不是在更复杂的函数中使用多个短表达式。
Tags:
由于fully RFC 822 compliant regex的长度,它的效率很低,而且很模糊。幸运的是,RFC 822被替换了两次,当前的电子邮件地址规范是RFC 5322。RFC 5322产生了一个regex,如果研究几分钟就可以理解它,并且它的效率足以满足实际使用。
可以在页面顶部的http://emailregex.com/找到一个符合RFC 5322的regex,但它使用的IP地址模式是在internet上浮动的,其中有一个bug允许
00
在点分隔的地址中使用任何无符号字节十进制值,这是非法的。其余部分似乎与RFC 5322语法一致,并通过了几个使用grep -Po
的测试,包括case域名、IP地址、坏地址和带有或不带引号的帐户名。更正IP模式中的
00
错误,我们获得了一个工作正常且相当快的regex。(为实际代码刮除渲染版本而不是标记。)或:
这里是上面regexp的diagram的finite state machine,比regexp本身更清楚
Perl和PCRE(例如在PHP中使用的regex库)中更复杂的模式可以correctly parse RFC 5322 without a hitch。Python和C也可以做到这一点,但它们使用的语法与前两种不同。但是,如果您被迫使用许多功能较弱的模式匹配语言之一,那么最好使用真正的解析器。
同样重要的是要理解,根据RFC验证它绝对不会告诉您该地址是否实际存在于所提供的域中,或者输入地址的人是否是它的真正所有者。人们总是以这种方式注册其他人的邮件列表。修复这一问题需要一种更奇特的验证方法,即发送一条消息给该地址,其中包含一个确认令牌,该令牌将被输入到与该地址相同的网页上。
确认令牌是唯一能知道输入者地址的方法。这就是为什么大多数邮件列表现在使用这种机制来确认注册。毕竟,任何人都可以放下
president@whitehouse.gov
,这甚至可以被解析为合法的,但不太可能是另一端的人。对于PHP,应该而不是使用Validate an E-Mail Address with PHP, the Right Way中给出的模式,我引用了该模式:
这并不比其他所有非RFC模式都好。它甚至连处理RFC 822都不够聪明,更不用说RFC 5322了。This one然而,是。
如果你想变得花哨和迂腐,implement a complete state engine。正则表达式只能充当基本的筛选器。正则表达式的问题是,告诉某人他们完全有效的电子邮件地址是无效的(误报),因为从用户的角度来看,正则表达式无法处理这是粗鲁和不礼貌的。用于此目的的状态引擎可以验证甚至更正在根据每个RFC反汇编电子邮件地址时被视为无效的电子邮件地址。这样就有可能获得更愉快的体验,比如
另请参见Validating Email Addresses,包括注释。或者Comparing E-mail Address Validating Regular Expressions。
Debuggex Demo
不应使用正则表达式验证电子邮件地址。
相反,使用MailAddress类,如下所示:
MailAddress类使用BNF解析器完全按照RFC822验证地址。
如果您真的想使用regex,here it is:
这个问题被问了很多,但我认为你应该退后一步,问问自己,为什么要从语法上验证电子邮件地址?真正的好处是什么?
如果你想验证一封电子邮件是否正确,你别无选择,只能发送一封确认电子邮件,让用户回复。在许多情况下,出于安全原因或道德原因,您都会让发送确认邮件(因此您不能违背某人的意愿注册服务)。
相关问题 更多 >
编程相关推荐