我最近在某处读到,写一个正则表达式来匹配一个电子邮件地址,考虑到标准的所有变化和可能性是非常困难的,而且比最初假设的要复杂得多。
这是为什么?
是否有任何已知且经过验证的正则表达式实际上可以完全做到这一点?
使用正则表达式匹配电子邮件地址有哪些好的替代方法?
我最近在某处读到,写一个正则表达式来匹配一个电子邮件地址,考虑到标准的所有变化和可能性是非常困难的,而且比最初假设的要复杂得多。
这是为什么?
是否有任何已知且经过验证的正则表达式实际上可以完全做到这一点?
使用正则表达式匹配电子邮件地址有哪些好的替代方法?
对于正式的电子邮件规范,是的,由于诸如评论之类的递归(特别是如果您不先删除对空白的评论)以及各种不同的格式(电子邮件地址是'不总是有人@somewhere.tld)。您可以接近(使用一些庞大且难以理解的正则表达式模式),但检查电子邮件的更好方法是进行非常熟悉的握手:
当他们点击链接时,您知道:
比盲目接受电子邮件地址要好得多。
有许多 Perl 模块(例如)可以做到这一点。不要尝试编写自己的正则表达式来做到这一点。看着
Mail::VRFY
将进行语法和网络检查(某处的 SMTP 服务器是否接受此地址)
https://metacpan.org/pod/Mail::VRFY
RFC::RFC822::Address
- 递归下降电子邮件地址解析器。
https://metacpan.org/pod/RFC::RFC822::地址
Mail::RFC822::Address
- 基于正则表达式的地址验证,值得一看只是为了疯狂的正则表达式
http://ex-parrot.com/~pdw/Mail-RFC822-Address.html
其他语言也有类似的工具。下面疯狂的正则表达式...
(?:(?:\r\n)?[ \t])*(?:(?:(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t]
)+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:
\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(
?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[
\t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\0
31]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\
](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+
(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:
(?:\r\n)?[ \t])*))*|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z
|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)
?[ \t])*)*\<(?:(?:\r\n)?[ \t])*(?:@(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\
r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[
\t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)
?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t]
)*))*(?:,@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[
\t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*
)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t]
)+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*)
*:(?:(?:\r\n)?[ \t])*)?(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+
|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r
\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t
]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031
]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](
?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?
:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?
:\r\n)?[ \t])*))*\>(?:(?:\r\n)?[ \t])*)|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?
:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?
[ \t]))*"(?:(?:\r\n)?[ \t])*)*:(?:(?:\r\n)?[ \t])*(?:(?:(?:[^()<>@,;:\\".\[\]
\000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|
\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>
@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"
(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t]
)*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\
".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?
:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[
\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*|(?:[^()<>@,;:\\".\[\] \000-
\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(
?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)*\<(?:(?:\r\n)?[ \t])*(?:@(?:[^()<>@,;
:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([
^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\"
.\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\
]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*(?:,@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\
[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\
r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\]
\000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]
|\\.)*\](?:(?:\r\n)?[ \t])*))*)*:(?:(?:\r\n)?[ \t])*)?(?:[^()<>@,;:\\".\[\] \0
00-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\
.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,
;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?
:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*
(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".
\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[
^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]
]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*\>(?:(?:\r\n)?[ \t])*)(?:,\s*(
?:(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\
".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(
?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[
\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t
])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t
])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?
:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|
\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*|(?:
[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\
]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)*\<(?:(?:\r\n)
?[ \t])*(?:@(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["
()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)
?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>
@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*(?:,@(?:(?:\r\n)?[
\t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,
;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t]
)*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\
".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*)*:(?:(?:\r\n)?[ \t])*)?
(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".
\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:
\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\[
"()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])
*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])
+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\
.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z
|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*\>(?:(
?:\r\n)?[ \t])*))*)?;\s*)
无论如何,验证电子邮件地址并不是很有帮助。它不会捕捉到常见的拼写错误或虚构的电子邮件地址,因为这些在语法上往往看起来像有效地址。
如果您想确定地址是否有效,您别无选择,只能发送确认邮件。
如果您只是想确保用户输入的内容看起来像电子邮件,而不仅仅是“asdf”,请检查@。更复杂的验证并没有真正提供任何好处。
(我知道这不能回答你的问题,但我认为无论如何都值得一提)
BNF 中有一个上下文无关语法,用于描述RFC-2822中的有效电子邮件地址。它很复杂。例如:
" @ "@example.com
是一个有效的电子邮件地址。我不知道有任何正则表达式可以完全做到这一点;通常给出的示例要求首先删除注释。我写了一个递归下降解析器来完全完成一次。
我现在整理了来自 Cal Henderson、Dave Child、Phil Haack、Doug Lovell 和 RFC 3696 的测试用例。总共有 158 个测试地址。
我针对我能找到的所有验证器运行了所有这些测试。比较在这里: http: //www.dominicsayers.com/isemail
随着人们增强他们的验证器,我将尝试使此页面保持最新。感谢 Cal、Dave 和 Phil 在编译这些测试时提供的帮助和合作,以及对我自己的验证器的建设性批评。
人们应该特别注意针对 RFC 3696 的勘误表。其中三个规范示例实际上是无效地址。地址的最大长度是 254 或 256 个字符,而不是320。
这并不是胡说八道,因为允许使用诸如“+”之类的字符对于打击垃圾邮件的用户非常有用,例如myemail+sketchysite@gmail.com(即时一次性 Gmail 地址)。
只有当网站接受它时。
在我看来,是否接受奇怪、不常见的电子邮件地址格式取决于人们想用它们做什么。
如果您正在编写一个邮件服务器,那么您必须非常准确且极其正确地接受您所接受的内容。因此,上面引用的“疯狂”正则表达式是合适的。
然而,对于我们其他人来说,我们主要只是对确保用户在 Web 表单中键入的内容看起来合理并且没有某种 sql 注入或缓冲区溢出感兴趣。
坦率地说,在注册邮件列表、时事通讯或网站时,是否有人真正关心让某人输入包含评论、换行符、引号、空格、括号或其他乱码的 200 个字符的电子邮件地址?对此类小丑的正确回应是“当您的地址看起来像 username@domain.tld 时再回来”。
我所做的验证包括确保只有一个“@”;没有空格、空值或换行符;“@”右侧的部分至少有一个点(但不是连续两个点);并且没有引号、括号、逗号、冒号、感叹号、分号或反斜杠,所有这些都比实际电子邮件地址的某些部分更有可能是黑客攻击的尝试。
是的,这意味着我拒绝有人可能试图在我的网站上注册的有效地址——也许我“错误地”拒绝了多达 0.001% 的真实地址!我可以忍受这一点。
引用和其他各种很少使用但有效的 RFC 部分使其变得困难。除了“这很难”之外,我对这个话题的了解还不够多,无法做出明确的评论——但幸运的是,其他人已经详细地写了这篇文章。
至于它的有效正则表达式,Perl Mail::Rfc822::Address 模块包含一个显然可以工作的正则表达式- 但前提是任何注释已经被空格替换。(电子邮件地址中的评论?你明白为什么它比人们想象的要难......)
当然,其他地方大量的简化正则表达式将验证几乎每个真正被使用的电子邮件地址......
一些正则表达式的风格实际上可以匹配嵌套的括号(例如,Perl 兼容的括号)。也就是说,我看到了一个声称正确匹配 RFC 822 的正则表达式,它是两页没有任何空格的文本。因此,检测有效电子邮件地址的最佳方法是向其发送电子邮件并查看它是否有效。
只是添加一个比@mmaibaum 列出的更不疯狂的正则表达式:
^[a-zA-Z]([.]?([a-zA-Z0-9_-]+)*)?@([a-zA-Z0-9\-_]+\.)+[a-zA-Z]{2,4}$
它不是万无一失的,当然也没有涵盖整个电子邮件规范,但它确实在满足最基本的要求方面做得不错。更好的是,它有点易于理解,并且可以编辑。
抄自HouseOfFusion.com的讨论,这是一个世界级的 ColdFusion 资源。
在 Java 中检查电子邮件地址的一种简单而好的方法是使用 Apache Commons Validator库的 EmailValidator 。
在发送电子邮件之前,我总是会检查输入表单中的电子邮件地址与此类内容 - 即使您只发现一些拼写错误。您可能不想为“交付失败”通知邮件编写自动扫描程序。:-)
这真的很难,因为根据电子邮件规范RFC 2822,电子邮件地址中有很多有效的东西。您通常看不到的东西,例如 + 是电子邮件地址的完全有效字符.. 根据规范。
有一整节专门讨论电子邮件地址http://regexlib.com,这是一个很好的资源。我建议您确定对您而言重要的标准并找到一个匹配的标准。大多数人真的不需要完全支持规范允许的所有可能性。
如果您在 .NET Framework 上运行,只需尝试实例化一个MailAddress
对象并捕获FormatException
它是否爆炸,或者提取Address
它是否成功。无需对捕获异常的性能进行任何废话(实际上,如果这只是在单个 Web 表单上,它不会产生太大的影响)MailAddress
,.NET 框架中的类会经历一个非常完整的解析过程(它不使用正则表达式)。打开 Reflector 并搜索MailAddress
并MailBnfHelper.ReadMailAddress()
查看它所做的所有花哨的东西。比我聪明的人花了很多时间在 Microsoft 构建该解析器,当我实际向该地址发送电子邮件时,我将使用它,所以我也可以使用它来验证传入地址。
试试这个:
"(?:[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])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-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])+)\])"
在这里查看详细信息。
然而,与其执行 RFC822 标准,或许从另一个角度来看它会更好。如果邮件服务器不反映标准,标准所说的并不重要。因此,我认为在验证电子邮件地址时,最好模仿最流行的邮件服务器所做的事情。
许多人尝试过,许多人都接近了。您可能想阅读wikipedia 文章和其他一些 文章。
具体来说,您需要记住,许多网站和电子邮件服务器对电子邮件地址的验证很宽松,因此它们基本上没有完全实施该标准。不过,电子邮件一直在工作就足够了。
Java的这个类中有一个验证器: http ://www.leshazlewood.com/?p=23
这是由 Shiro 的创建者(正式为 Ki,正式为 JSecurity)编写的
测试电子邮件地址有效性的优缺点:
有两种类型的正则表达式可以验证电子邮件:
正则表达式不可能匹配所有有效的电子邮件地址和无效的电子邮件地址,因为某些字符串可能看起来像有效的电子邮件地址,但实际上并没有发送到任何人的收件箱。测试一封电子邮件是否真的有效的唯一方法是向该地址发送一封电子邮件,看看您是否得到某种回应。考虑到这一点,在匹配电子邮件方面过于严格的正则表达式似乎并没有太大的用途。
我认为大多数要求电子邮件正则表达式的人都在寻找第一个选项,即过于松散的正则表达式。他们想测试一个字符串,看看它是否看起来像一封电子邮件,如果它肯定不是一封电子邮件,那么他们可以对用户说:“嘿,你应该在这里放一封电子邮件,这肯定是不是有效的电子邮件。也许您没有意识到此字段是用于电子邮件的,或者可能有错字”。
如果用户输入的字符串看起来很像有效的电子邮件,但实际上不是,那么这是一个应该由应用程序的不同部分处理的问题。
谁能提供一些关于为什么会这样的见解?
是的,这是一个极其复杂的标准,它允许许多今天没有人真正使用的东西。:)
是否有任何已知且经过验证的正则表达式实际上可以完全做到这一点?
这是完全解析整个标准的一种尝试...
http://ex-parrot.com/~pdw/Mail-RFC822-Address.html
使用正则表达式匹配电子邮件地址有哪些好的替代方法?
我猜想以您使用的任何语言为它使用现有框架?尽管那些可能会在内部使用正则表达式。这是一个复杂的字符串。正则表达式旨在解析复杂的字符串,因此这确实是您的最佳选择。
编辑:我应该补充一点,我链接到的正则表达式只是为了好玩。我不赞成使用这样复杂的正则表达式——有人说“如果你的正则表达式不止一行,那么它肯定会在某处出现错误”。我链接到它以说明标准的复杂性。
为了这篇文章的完整性,PHP 也有一个语言内置函数来验证电子邮件。
对于 PHP 使用带有特定 EMAIL 验证类型的 nice filter_var :)
php 中不再有疯狂的电子邮件正则表达式:D
var_dump(filter_var('bob@example.com', FILTER_VALIDATE_EMAIL));
在尝试创建正则表达式来验证电子邮件时,似乎总是有一种无法解释的格式。尽管电子邮件中有些字符无效,但基本格式是 local-part@domain,本地部分最多大约 64 个字符,域大约 253 个字符。除此之外,它有点像狂野的西部。
我认为答案取决于您对经过验证的电子邮件地址的定义以及您的业务流程可以容忍的内容。正则表达式非常适合确保电子邮件格式正确,并且您知道它们有很多变体可以使用。这里有几个变化:
变体 1:
(?:[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])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-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])+)\])
变体2:
\A(?:[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])?|\[(?:(?:25[0-5]|2[0-][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-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])+)\])\z
仅仅因为电子邮件在语法上是正确的并不意味着它是有效的。
一封电子邮件可以遵守 RFC 5322 并通过正则表达式,但不会真正了解电子邮件的实际可传递性。如果您想知道这封电子邮件是否是伪造的电子邮件,或者它是一次性的、不可交付的还是已知的机器人,该怎么办?如果您想排除粗俗或以某种方式存在争议或有问题的电子邮件怎么办?顺便说一句,大家都知道,我在一家数据验证公司工作,我只是想充分披露我为 Service Objects 工作,但作为电子邮件验证领域的专业人士,我觉得我们提供的解决方案提供了更好的解决方案验证比正则表达式。随意给它看一下,我认为它可以帮助很多。您可以在我们的开发指南中查看更多信息。它实际上做了很多很酷的电子邮件检查和验证。
这是一个例子:
电子邮件:mickeyMouse@gmail.com
{
"ValidateEmailInfo":{
"Score":4,
"IsDeliverable":"false",
"EmailAddressIn":"mickeyMouse@gmail.com",
"EmailAddressOut":"mickeyMouse@gmail.com",
"EmailCorrected":false,
"Box":"mickeyMouse",
"Domain":"gmail.com",
"TopLevelDomain":".com",
"TopLevelDomainDescription":"commercial",
"IsSMTPServerGood":"true",
"IsCatchAllDomain":"false",
"IsSMTPMailBoxGood":"false",
"WarningCodes":"22",
"WarningDescriptions":"Email is Bad - Subsequent checks halted.",
"NotesCodes":"16",
"NotesDescriptions":"TLS"
}
}