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

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

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

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


当前回答

根据我所看到的,一个完全符合标准的正则表达式是允许的:

/^(?!(^[.-].*|.*[.-]@|.*\.{2,}.*)|^.{254}.+@)([a-z\xC0-\xFF0-9!#$%&'*+\/=?^_`{|}~.-]+@)(?!.{253}.+$)((?!-.*|.*-\.)([a-z0-9-]{1,63}\.)+[a-z]{2,63}|(([01]?[0-9]{2}|2([0-4][0-9]|5[0-5])|[0-9])\.){3}([01]?[0-9]{2}|2([0-4][0-9]|5[0-5])|[0-9]))$/gim

演示/调试分析(交互式)

拆分:

^(?!(^[.-].*|.*[.-]@|.*\.{2,}.*)|^.{254}.+@)
([a-z\xC0-\xFF0-9!#$%&'*+\/=?^_`{|}~.-]+@)
(?!.{253}.+$)
(
    (?!-.*|.*-\.)
    ([a-z0-9-]{1,63}\.)+
    [a-z]{2,63}
    |
    (([01]?[0-9]{2}|2([0-4][0-9]|5[0-5])|[0-9])\.){3}
    ([01]?[0-9]{2}|2([0-4][0-9]|5[0-5])|[0-9])
)$

分析:

(?!(^[.-].*|.*[.-]@|.*\.{2,}.*)|^.{254}.+@)

对以。,以一结尾,有。。或超过254个字符的最大长度


([a-z\xC0-\xFF0-9!#$%&'*+\/=?^_`{|}~.-]+@)

匹配一个或多个允许的字符,并应用负面外观


(?!.{253}.+$)

域名部分的负前瞻性,总共限制为253个字符


(?!-.*|.*-\.)

每个域名的负前瞻性,不允许以开头或结尾。


([a-z0-9-]{1,63}\.)+

域名中允许的字符的简单组匹配,每个字符限制为63个字符


[a-zA-Z]{2,63}

允许的顶级域的简单组匹配,该域目前仍仅限于字母,但确实包含4个字母以上的TLD。


(([01]?[0-9]{2}|2([0-4][0-9]|5[0-5])|[0-9])\.){3}
([01]?[0-9]{2}|2([0-4][0-9]|5[0-5])|[0-9])

域名的替代方案:这将IP地址中的前3个数字与匹配。然后是IP地址中没有的第四个数字。在它背后。

其他回答

根据我所看到的,一个完全符合标准的正则表达式是允许的:

/^(?!(^[.-].*|.*[.-]@|.*\.{2,}.*)|^.{254}.+@)([a-z\xC0-\xFF0-9!#$%&'*+\/=?^_`{|}~.-]+@)(?!.{253}.+$)((?!-.*|.*-\.)([a-z0-9-]{1,63}\.)+[a-z]{2,63}|(([01]?[0-9]{2}|2([0-4][0-9]|5[0-5])|[0-9])\.){3}([01]?[0-9]{2}|2([0-4][0-9]|5[0-5])|[0-9]))$/gim

演示/调试分析(交互式)

拆分:

^(?!(^[.-].*|.*[.-]@|.*\.{2,}.*)|^.{254}.+@)
([a-z\xC0-\xFF0-9!#$%&'*+\/=?^_`{|}~.-]+@)
(?!.{253}.+$)
(
    (?!-.*|.*-\.)
    ([a-z0-9-]{1,63}\.)+
    [a-z]{2,63}
    |
    (([01]?[0-9]{2}|2([0-4][0-9]|5[0-5])|[0-9])\.){3}
    ([01]?[0-9]{2}|2([0-4][0-9]|5[0-5])|[0-9])
)$

分析:

(?!(^[.-].*|.*[.-]@|.*\.{2,}.*)|^.{254}.+@)

对以。,以一结尾,有。。或超过254个字符的最大长度


([a-z\xC0-\xFF0-9!#$%&'*+\/=?^_`{|}~.-]+@)

匹配一个或多个允许的字符,并应用负面外观


(?!.{253}.+$)

域名部分的负前瞻性,总共限制为253个字符


(?!-.*|.*-\.)

每个域名的负前瞻性,不允许以开头或结尾。


([a-z0-9-]{1,63}\.)+

域名中允许的字符的简单组匹配,每个字符限制为63个字符


[a-zA-Z]{2,63}

允许的顶级域的简单组匹配,该域目前仍仅限于字母,但确实包含4个字母以上的TLD。


(([01]?[0-9]{2}|2([0-4][0-9]|5[0-5])|[0-9])\.){3}
([01]?[0-9]{2}|2([0-4][0-9]|5[0-5])|[0-9])

域名的替代方案:这将IP地址中的前3个数字与匹配。然后是IP地址中没有的第四个数字。在它背后。

我不建议使用正则表达式,电子邮件地址太复杂了。这是一个常见的问题,所以我猜有很多库都包含验证器-如果您使用Java,apachecommons验证器的EmailValidator是一个很好的验证器。

这是我做的。它不是防弹版,但它“简单”,几乎可以检查所有内容。

[\w+-]+(?:\.[\w+-]+)*@[\w+-]+(?:\.[\w+-]+)*(?:\.[a-zA-Z]{2,4})

我认为已经有了解释,因此您可以根据需要进行修改:

(e) [\w+-]+匹配a-z、a-z、_、+、-至少一次

(m) (?:\.[\w+-]+)*匹配a-z、a-z、_、+、-0或更多次,但需要以a开头。(点)

@ = @

(i) [\w+-]+匹配a-z、a-z、_、+、-至少一次

(l) (?:\.[\w+-]+)*匹配a-z、a-z、_、+、-0或更多次,但需要以a开头。(点)

(com)(?:\.[a-zA-Z]{2,4})匹配a-Z,a-Z 2到4次,从a开始。(点)

给出e(-m)@i(.l).com,其中(.m)和(.l)是可选的,但也可以重复多次。

我认为这会验证所有有效的电子邮件地址,但会阻止潜在的无效地址,而不使用在大多数情况下不需要的过于复杂的正则表达式。

请注意,这将允许+@-.com,但这是保持简单的折衷方案。

奇怪的是,您“不能”使用4个字符的TLD。您禁止人们使用.info和.name,以及长度限制stop、travel和.museum,但是的,它们比2个字符的TLD和3个字符的TLC更常见。

你也应该允许大写字母。电子邮件系统将规范本地部分和域部分。

对于域部分的正则表达式,域名不能以'-'开头,也不能以'-'结尾。Dash只能介于两者之间。

如果您使用PEAR库,请查看他们的邮件功能(我忘记了确切的名称/库)。您可以通过调用一个函数来验证电子邮件地址,它根据RFC 822中的定义验证电子邮件地址。

自2010年5月以来,互联网上存在非拉丁语(中文、阿拉伯文、希腊文、希伯来文、西里尔文等)域名。每个人都必须更改使用的电子邮件正则表达式,因为这些字符肯定不会被[a-z]/i或\w覆盖。他们都会失败。

毕竟,验证电子邮件地址的最佳方法仍然是向有问题的地址发送电子邮件以验证地址。如果电子邮件地址是用户身份验证(注册/登录等)的一部分,那么您可以将其与用户激活系统完美结合。即,发送带有指向指定电子邮件地址的唯一激活密钥的链接的电子邮件,并且仅当用户使用电子邮件中的链接激活了新创建的帐户时才允许登录。

如果正则表达式的目的只是在UI中快速通知用户指定的电子邮件地址格式不正确,那么最好还是检查它是否与以下正则表达式基本匹配:

^([^.@]+)(\.[^.@]+)*@([^.@]+\.)+([^.@]+)$

就这么简单。你到底为什么会在意名字和域名中使用的字符?输入有效的电子邮件地址是客户的责任,而不是服务器的。即使客户端输入语法上有效的电子邮件地址,如aa@bb.cc,这不能保证它是合法的电子邮件地址。没有一个正则表达式可以涵盖这一点。