如何使用正则表达式验证电子邮件地址?

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

我在几个PHP程序中使用它,并且它在大多数时间都有效。 但是,有时我会接触到某个使用它的站点有问题的人,最后我不得不作出一些调整(最近我意识到我不允许使用4个字符的顶级域名)。

什么是您验证电子邮件的最佳正则表达式?

我已经看到了几个使用几个较短表达式的函数的解决方案,但我宁愿在一个简单的函数中使用一个长的复杂表达式,而不是在一个更复杂的函数中使用几个简短的表达式。


完全兼容RFC 822的正则表达式由于其长度而效率低下且不明显。 幸运的是,RFC 822被取代了两次,目前的电子邮件地址规范是RFC 5322.RFC 5322导致了一个正则表达式,如果学习几分钟就可以理解,并且对于实际使用而言足够高效。

一个符合RFC 5322标准的正则表达式可以在http://emailregex.com/的页面顶部找到,但是使用在因特网上浮动的IP地址模式,其错误允许00中的任何无符号字节十进制值以点分隔的地址,这是非法的。 其余部分似乎与RFC 5322语法一致,并通过使用grep -Po多项测试,其中包括域名,IP地址,错误和带和不带引号的帐户名称。

纠正IP模式中的00错误,我们获得了一个工作和相当快的正则表达式。 (为实际的代码擦除渲染版本,而不是降价。)

(:[A-Z0-9#$%& '* + / = ^ _`{|}〜 - +(?! [A-Z0-9#$%&!]'?* + / ?= ^ _`{|}〜 - ] +)* |“(?:[ x01- X08 X0B X0C x0e- X1F X21 x23- x5b x5d- 0x7F部分] | [ x01- X09 X0B X0C x0e- 0x7F部分])*“)@(:(:[α-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- 0x7F部分] | [ x01- X09 X0B X0C x0e- 0x7F部分])+)])

这里是上述正则表达式的有限状态机的图,它比正则表达式本身更清晰 在这里输入图像描述

Perl和PCRE中更复杂的模式(例如PHP中使用的正则表达式库)可以正确解析RFC 5322。 Python和C#也可以这样做,但它们使用与前两种不同的语法。 但是,如果您不得不使用其中一种功能较弱的模式匹配语言,那么最好使用真正的解析器。

理解根据RFC验证它也告诉你,该地址是否实际存在于提供的域中,或者输入地址的人是否是其真正的所有者,这一点完全没有意义。 人们一直以这种方式签署其他邮件列表。 解决这个问题需要更多的验证,包括向该地址发送一条消息,其中包含一个确认令牌,该令牌旨在与地址相同的网页上输入。

确认令牌是了解您获得进入者地址的唯一途径。 这就是为什么大多数邮件列表现在都使用该机制来确认注册。 毕竟,任何人都可以放下president@whitehouse.gov ,甚至可以解析为合法,但不太可能是另一端的人。

对于PHP,你不应该使用PHP中验证电子邮件地址给出的模式,我引用的是正确的方式:

普遍使用和广泛的草率编码将会对电子邮件地址建立一个事实上的标准,这是比记录的正式标准更严格的标准。

这并不比所有其他非RFC模式更好。 它甚至不够聪明,甚至无法处理RFC 822,更不用说RFC 5322了。但是,这一点是。

如果你想变得花俏和迂腐,那就实现一个完整的状态引擎。 正则表达式只能作为基本的过滤器。 正则表达式的问题在于,告诉某人他们完全有效的电子邮件地址是无效的(误报),因为您的正则表达式无法处理它,从用户的角度来看只是粗鲁而不礼貌。 一个用于此目的的状态引擎既可以验证甚至纠正电子邮件地址,否则这些电子邮件地址会被视为无效,因为它会根据每个RFC分解电子邮件地址。 这可以带来更可喜的体验,例如

指定的电子邮件地址'myemail @ address,com'无效。 你的意思是'myemail@address.com'?

另请参阅验证电子邮件地址,包括注释。 或比较验证正则表达式的电子邮件地址。

正则表达式可视化

Debuggex演示


您不应该使用正则表达式来验证电子邮件地址。

相反,请使用MailAddress类,如下所示:

try {
    address = new MailAddress(address).Address;
} catch(FormatException) {
    //address is invalid
}

MailAddress类使用BNF解析器完全根据RFC822验证地址。

如果你真的想使用正则表达式,这里是:

(?:(?:rn)?[ t])*(?:(?:(?:[^()<>@,;:".[] 00-31]+(?:(?:(?:rn)?[ t]
)+|Z|(?=[["()<>@,;:".[]]))|"(?:[^"r]|.|(?:(?:rn)?[ t]))*"(?:(?:
rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:".[] 00-31]+(?:(?:(
?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|"(?:[^"r]|.|(?:(?:rn)?[ 
t]))*"(?:(?:rn)?[ t])*))*@(?:(?:rn)?[ t])*(?:[^()<>@,;:".[] 00-
31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|[([^[]r]|.)*
](?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:".[] 00-31]+
(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|[([^[]r]|.)*](?:
(?:rn)?[ t])*))*|(?:[^()<>@,;:".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z
|(?=[["()<>@,;:".[]]))|"(?:[^"r]|.|(?:(?:rn)?[ t]))*"(?:(?:rn)
?[ t])*)*<(?:(?:rn)?[ t])*(?:@(?:[^()<>@,;:".[] 00-31]+(?:(?:(?:
rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|[([^[]r]|.)*](?:(?:rn)?[
 t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:".[] 00-31]+(?:(?:(?:rn)
?[ t])+|Z|(?=[["()<>@,;:".[]]))|[([^[]r]|.)*](?:(?:rn)?[ t]
)*))*(?:,@(?:(?:rn)?[ t])*(?:[^()<>@,;:".[] 00-31]+(?:(?:(?:rn)?[
 t])+|Z|(?=[["()<>@,;:".[]]))|[([^[]r]|.)*](?:(?:rn)?[ t])*
)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:".[] 00-31]+(?:(?:(?:rn)?[ t]
)+|Z|(?=[["()<>@,;:".[]]))|[([^[]r]|.)*](?:(?:rn)?[ t])*))*)
*:(?:(?:rn)?[ t])*)?(?:[^()<>@,;:".[] 00-31]+(?:(?:(?:rn)?[ t])+
|Z|(?=[["()<>@,;:".[]]))|"(?:[^"r]|.|(?:(?:rn)?[ t]))*"(?:(?:r
n)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:".[] 00-31]+(?:(?:(?:
rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|"(?:[^"r]|.|(?:(?:rn)?[ t
]))*"(?:(?:rn)?[ t])*))*@(?:(?:rn)?[ t])*(?:[^()<>@,;:".[] 00-31
]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|[([^[]r]|.)*](
?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:".[] 00-31]+(?
:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|[([^[]r]|.)*](?:(?
:rn)?[ t])*))*>(?:(?:rn)?[ t])*)|(?:[^()<>@,;:".[] 00-31]+(?:(?
:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|"(?:[^"r]|.|(?:(?:rn)?
[ t]))*"(?:(?:rn)?[ t])*)*:(?:(?:rn)?[ t])*(?:(?:(?:[^()<>@,;:".[] 
00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|"(?:[^"r]|
.|(?:(?:rn)?[ t]))*"(?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>

@,;:".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|"
(?:[^"r]|.|(?:(?:rn)?[ t]))*"(?:(?:rn)?[ t])*))*@(?:(?:rn)?[ t]
)*(?:[^()<>@,;:".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:
".[]]))|[([^[]r]|.)*](?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?
:[^()<>@,;:".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[
]]))|[([^[]r]|.)*](?:(?:rn)?[ t])*))*|(?:[^()<>@,;:".[] 00-
31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|"(?:[^"r]|.|(
?:(?:rn)?[ t]))*"(?:(?:rn)?[ t])*)*<(?:(?:rn)?[ t])*(?:@(?:[^()<>@,;
:".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|[([
^[]r]|.)*](?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:"
.[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|[([^[
]r]|.)*](?:(?:rn)?[ t])*))*(?:,@(?:(?:rn)?[ t])*(?:[^()<>@,;:".
[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|[([^[]
r]|.)*](?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:".[] 
00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|[([^[]r]
|.)*](?:(?:rn)?[ t])*))*)*:(?:(?:rn)?[ t])*)?(?:[^()<>@,;:".[] 
00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|"(?:[^"r]|
.|(?:(?:rn)?[ t]))*"(?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,
;:".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|"(?
:[^"r]|.|(?:(?:rn)?[ t]))*"(?:(?:rn)?[ t])*))*@(?:(?:rn)?[ t])*
(?:[^()<>@,;:".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".
[]]))|[([^[]r]|.)*](?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[
^()<>@,;:".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]
]))|[([^[]r]|.)*](?:(?:rn)?[ t])*))*>(?:(?:rn)?[ t])*)(?:,s*(
?:(?:[^()<>@,;:".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:
".[]]))|"(?:[^"r]|.|(?:(?:rn)?[ t]))*"(?:(?:rn)?[ t])*)(?:.(?:(
?:rn)?[ t])*(?:[^()<>@,;:".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[
["()<>@,;:".[]]))|"(?:[^"r]|.|(?:(?:rn)?[ t]))*"(?:(?:rn)?[ t
])*))*@(?:(?:rn)?[ t])*(?:[^()<>@,;:".[] 00-31]+(?:(?:(?:rn)?[ t
])+|Z|(?=[["()<>@,;:".[]]))|[([^[]r]|.)*](?:(?:rn)?[ t])*)(?
:.(?:(?:rn)?[ t])*(?:[^()<>@,;:".[] 00-31]+(?:(?:(?:rn)?[ t])+|
Z|(?=[["()<>@,;:".[]]))|[([^[]r]|.)*](?:(?:rn)?[ t])*))*|(?:
[^()<>@,;:".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[
]]))|"(?:[^"r]|.|(?:(?:rn)?[ t]))*"(?:(?:rn)?[ t])*)*<(?:(?:rn)
?[ t])*(?:@(?:[^()<>@,;:".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["
()<>@,;:".[]]))|[([^[]r]|.)*](?:(?:rn)?[ t])*)(?:.(?:(?:rn)
?[ t])*(?:[^()<>@,;:".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>

@,;:".[]]))|[([^[]r]|.)*](?:(?:rn)?[ t])*))*(?:,@(?:(?:rn)?[
 t])*(?:[^()<>@,;:".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,
;:".[]]))|[([^[]r]|.)*](?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t]
)*(?:[^()<>@,;:".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:
".[]]))|[([^[]r]|.)*](?:(?:rn)?[ t])*))*)*:(?:(?:rn)?[ t])*)?
(?:[^()<>@,;:".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".
[]]))|"(?:[^"r]|.|(?:(?:rn)?[ t]))*"(?:(?:rn)?[ t])*)(?:.(?:(?:
rn)?[ t])*(?:[^()<>@,;:".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[[
"()<>@,;:".[]]))|"(?:[^"r]|.|(?:(?:rn)?[ t]))*"(?:(?:rn)?[ t])
*))*@(?:(?:rn)?[ t])*(?:[^()<>@,;:".[] 00-31]+(?:(?:(?:rn)?[ t])
+|Z|(?=[["()<>@,;:".[]]))|[([^[]r]|.)*](?:(?:rn)?[ t])*)(?:
.(?:(?:rn)?[ t])*(?:[^()<>@,;:".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z
|(?=[["()<>@,;:".[]]))|[([^[]r]|.)*](?:(?:rn)?[ t])*))*>(?:(
?:rn)?[ t])*))*)?;s*)

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

  • 它不会遇到常见的错别字。
  • 它不会阻止人们输入无效的电子邮件地址或输入其他人的地址。
  • 如果您想验证电子邮件是否正确,您别无选择,只能发送确认电子邮件并让用户回复。 在许多情况下,出于安全原因或出于道德原因,您必须发送确认邮件(所以您不能按照自己的意愿签署某项服务)。

    链接地址: http://www.djcxy.com/p/327.html

    上一篇: How to validate an email address using a regular expression?

    下一篇: How to validate an email address in JavaScript?