多年来,我慢慢地开发了一个正则表达式,它可以正确验证大多数电子邮件地址,假设它们不使用IP地址作为服务器部分。

我在几个PHP程序中使用它,而且大多数时候都可以使用。然而,不时有人与我联系,他们对使用它的网站有问题,我最终不得不做出一些调整(最近我意识到我不允许四个字符的TLD)。

你有或见过验证电子邮件的最佳正则表达式是什么?

我见过几种使用函数的解决方案,这些函数使用了几个较短的表达式,但我宁愿在简单函数中使用一个长的复杂表达式,而不是在更复杂的函数中使用几个短表达式。


当前回答

我从不麻烦用自己的正则表达式创建,因为很可能其他人已经提出了更好的版本。我总是使用regexlib来找到一个我喜欢的。

其他回答

这个问题被问了很多,但我认为你应该退后一步,问问自己为什么要从语法上验证电子邮件地址?真正的好处是什么?

它不会捕捉常见的拼写错误。它并不阻止人们输入无效或虚构的电子邮件地址,或输入其他人的地址。

如果您想验证电子邮件是否正确,您别无选择,只能发送确认电子邮件并让用户回复。在许多情况下,出于安全原因或道德原因(例如,您不能违背某人的意愿签署服务),您必须发送确认邮件。

我不相信bortzmeyer所说的“语法(RFC 5322中指定的)太复杂了”(无法用正则表达式处理)。

这是语法(来自3.4.1。添加规范规范):

addr-spec       =   local-part "@" domain
local-part      =   dot-atom / quoted-string / obs-local-part
domain          =   dot-atom / domain-literal / obs-domain
domain-literal  =   [CFWS] "[" *([FWS] dtext) [FWS] "]" [CFWS]
dtext           =   %d33-90 /          ; Printable US-ASCII
                    %d94-126 /         ;  characters not including
                    obs-dtext          ;  "[", "]", or "\"

假设点原子、带引号的字符串、obs局部部分、obs域本身是正则语言,这是一个非常简单的语法。只需将addr-spec产品中的本地部分和域替换为它们各自的产品,您就拥有了一种可直接转换为正则表达式的正则语言。

没有一个是真正有用的。我在回答“是否有用于电子邮件地址验证的PHP库?”时讨论了一些问题?,它也在电子邮件地址的正则表达式识别难吗?中讨论?。

简而言之,不要期望一个可用的正则表达式能够完成正确的工作。最好的正则表达式将验证语法,而不是电子邮件的有效性(jhohn@example.com是正确的,但它可能会反弹…)。

这一切都取决于你想要的准确度。出于我的目的,我只是想避开bob@aol.com(电子邮件中的空格)或steve(完全没有域名)或mary@aolcom(在.com之前没有句点),我使用

/^\S+@\S+\.\S+$/

当然,它会匹配不是有效电子邮件地址的内容,但这是一个常见的简单错误问题。

可以对该正则表达式进行任意数量的更改(其中一些在这个答案的注释中),但它很简单,易于理解,是一个很好的第一次尝试。

在Perl 5.10或更高版本中很容易:

/(?(DEFINE)
   (?<address>         (?&mailbox) | (?&group))
   (?<mailbox>         (?&name_addr) | (?&addr_spec))
   (?<name_addr>       (?&display_name)? (?&angle_addr))
   (?<angle_addr>      (?&CFWS)? < (?&addr_spec) > (?&CFWS)?)
   (?<group>           (?&display_name) : (?:(?&mailbox_list) | (?&CFWS))? ;
                                          (?&CFWS)?)
   (?<display_name>    (?&phrase))
   (?<mailbox_list>    (?&mailbox) (?: , (?&mailbox))*)

   (?<addr_spec>       (?&local_part) \@ (?&domain))
   (?<local_part>      (?&dot_atom) | (?&quoted_string))
   (?<domain>          (?&dot_atom) | (?&domain_literal))
   (?<domain_literal>  (?&CFWS)? \[ (?: (?&FWS)? (?&dcontent))* (?&FWS)?
                                 \] (?&CFWS)?)
   (?<dcontent>        (?&dtext) | (?&quoted_pair))
   (?<dtext>           (?&NO_WS_CTL) | [\x21-\x5a\x5e-\x7e])

   (?<atext>           (?&ALPHA) | (?&DIGIT) | [!#\$%&'*+-/=?^_`{|}~])
   (?<atom>            (?&CFWS)? (?&atext)+ (?&CFWS)?)
   (?<dot_atom>        (?&CFWS)? (?&dot_atom_text) (?&CFWS)?)
   (?<dot_atom_text>   (?&atext)+ (?: \. (?&atext)+)*)

   (?<text>            [\x01-\x09\x0b\x0c\x0e-\x7f])
   (?<quoted_pair>     \\ (?&text))

   (?<qtext>           (?&NO_WS_CTL) | [\x21\x23-\x5b\x5d-\x7e])
   (?<qcontent>        (?&qtext) | (?&quoted_pair))
   (?<quoted_string>   (?&CFWS)? (?&DQUOTE) (?:(?&FWS)? (?&qcontent))*
                        (?&FWS)? (?&DQUOTE) (?&CFWS)?)

   (?<word>            (?&atom) | (?&quoted_string))
   (?<phrase>          (?&word)+)

   # Folding white space
   (?<FWS>             (?: (?&WSP)* (?&CRLF))? (?&WSP)+)
   (?<ctext>           (?&NO_WS_CTL) | [\x21-\x27\x2a-\x5b\x5d-\x7e])
   (?<ccontent>        (?&ctext) | (?&quoted_pair) | (?&comment))
   (?<comment>         \( (?: (?&FWS)? (?&ccontent))* (?&FWS)? \) )
   (?<CFWS>            (?: (?&FWS)? (?&comment))*
                       (?: (?:(?&FWS)? (?&comment)) | (?&FWS)))

   # No whitespace control
   (?<NO_WS_CTL>       [\x01-\x08\x0b\x0c\x0e-\x1f\x7f])

   (?<ALPHA>           [A-Za-z])
   (?<DIGIT>           [0-9])
   (?<CRLF>            \x0d \x0a)
   (?<DQUOTE>          ")
   (?<WSP>             [\x20\x09])
 )

 (?&address)/x