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

How to validate an email address using a regular expression?

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

我在几个PHP程序中使用它,它大多数时候都能工作。但是,有时我会被一个使用它的网站有问题的人联系,最后我不得不做一些调整(最近我意识到我不允许使用4字符的TLD)。

您在验证电子邮件时看到或看到的最佳正则表达式是什么?

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


完全符合RFC822的regex由于其长度而效率低下且晦涩难懂。幸运的是,RFC822被两次取代,目前电子邮件地址的规范是RFC5322。RFC5322导致了一个regex,如果研究几分钟就可以理解,并且对于实际使用来说足够有效。

在http://emailregex.com/的页面顶部可以找到一个符合RFC 5322的regex,但使用的IP地址模式在Internet上浮动,其错误允许00用于点分隔地址中的任何无符号字节十进制值,这是非法的。其余部分似乎与RFC 5322语法一致,并通过了几个使用grep -Po的测试,包括案例域名、IP地址、坏域名和带引号和不带引号的帐户名。

纠正了IP模式中的00错误,我们得到了一个运行良好、速度相当快的regex。(为实际代码刮除呈现的版本,而不是标记。)

(?:[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])?|\[(?:(?:(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-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])

下面是上面的regexp的有限状态机图,它比regexp本身更清楚。enter image description here

Perl和PCRE中更复杂的模式(例如在PHP中使用的regex库)可以无障碍地正确解析RFC5322。python和c也可以这样做,但它们使用的语法与前两种不同。但是,如果您被迫使用许多不太强大的模式匹配语言之一,那么最好使用真正的解析器。

同样重要的是要理解,根据RFC验证它完全不会告诉您该地址是否确实存在于所提供的域中,或者输入该地址的人是否是其真正的所有者。人们总是用这种方式把其他人注册到邮件列表中。修复这一问题需要一种更高级的验证,即向该地址发送一条消息,其中包含一个确认令牌,该令牌应与地址输入在同一网页上。

确认令牌是唯一知道输入者地址的方法。这就是为什么大多数邮件列表现在使用该机制来确认注册。毕竟,任何人都可以放下[email protected],这甚至是合法的,但不太可能是另一端的人。

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

There is some danger that common usage and widespread sloppy coding will establish a de facto standard for e-mail addresses that is more restrictive than the recorded formal standard.

这并不比所有其他非RFC模式都好。它甚至不够聪明,处理甚至RFC822,更不用说RFC5322。然而,这个是。

如果你想得到花哨和学究,实现一个完整的状态引擎。正则表达式只能用作基本筛选器。正则表达式的问题在于,告诉某人他们的完全有效的电子邮件地址是无效的(误报),因为从用户的角度来看,正则表达式无法处理它是粗鲁和不礼貌的。为此目的,状态引擎可以验证甚至更正电子邮件地址,否则将被视为无效,因为它根据每个RFC反汇编电子邮件地址。这会带来一种潜在的更愉快的体验,比如

The specified e-mail address 'myemail@address,com' is invalid. Did you mean '[email protected]'?

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

Regular expression visualization

调试程序演示


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

相反,使用mailaddress类,如下所示:

mailaddress类使用bnf解析器完全按照rfc822验证地址。

如果您真的想使用regex,这里是:


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

  • 它不会捕获常见的打字错误。
  • 它不会阻止人们输入无效或虚构的电子邮件地址,或输入其他人的地址。

如果要验证电子邮件是否正确,除了发送确认电子邮件并让用户答复之外,您别无选择。在许多情况下,出于安全原因或道德原因,您必须发送确认邮件(例如,您不能违背他们的意愿为某人注册服务)。


这取决于你所说的"最好"是什么意思:如果您要捕获每个有效的电子邮件地址,请使用以下内容:

(http://www.ex-parrot.com/~pdw/mail-rfc822-address.html)如果您正在寻找更简单但能捕捉到最有效的电子邮件地址,请尝试以下方法:

编辑:从链接:

This regular expression will only validate addresses that have had any comments stripped and replaced with whitespace (this is done by the module).


这完全取决于你想要的准确度。为了我的目的,如果我只是想避开像EDOCX1(电子邮件中的空格)或steve(完全没有域)或mary@aolcom(在.com之前没有句号),我使用

当然,它会匹配那些无效的电子邮件地址,但这是玩90/10规则的问题。


[更新]我在这里整理了我所知道的关于电子邮件地址验证的所有信息:http://isemail.info,它现在不仅可以验证电子邮件地址,还可以诊断电子邮件地址的问题。我同意这里的许多评论,即验证只是答案的一部分;请参阅我的文章http://isemail.info/about。

据我所知,_email()仍然是唯一能明确告诉您给定字符串是否为有效电子邮件地址的验证器吗?我在http://isemail.info上传了一个新版本/

我整理了Cal Henderson、Dave Child、Phil Haack、Doug Lovell、RFC5322和RFC3696的测试案例。共275个测试地址。我用我能找到的所有免费验证器运行了所有这些测试。

当人们增强他们的验证器时,我将尝试使此页面保持最新。感谢Cal、Michael、Dave、Paul和Phil在编译这些测试时的帮助和合作以及对我自己的验证器的建设性批评。

人们应该特别注意RFC3696的勘误表。其中三个规范示例实际上是无效地址。地址的最大长度是254或256个字符,而不是320个字符。


根据W3C HTML5规范:

语境:

A valid e-mail address is a string that matches the ABNF production […].

Note: This requirement is a willful violation of RFC 5322, which defines a syntax for e-mail addresses that is simultaneously too strict (before the"@" character), too vague (after the"@" character), and too lax (allowing comments, whitespace characters, and quoted strings in manners unfamiliar to most users) to be of practical use here.

The following JavaScript- and Perl-compatible regular expression is an implementation of the above definition.


在Perl5.10或更高版本中很容易实现:


我用

这是RegularExpressionValidator在ASP.NET中使用的。


不知道什么是最好的,但这个至少是正确的,只要地址的注释被删除并替换为空白。

说真的。您应该使用已经编写的库来验证电子邮件。最好的方法可能是将验证电子邮件发送到该地址。


我要验证的电子邮件地址将由ASP.NET Web应用程序使用System.NET.Mail命名空间向人员列表发送电子邮件。所以,我不使用非常复杂的正则表达式,而是尝试从地址创建mailaddress实例。如果地址格式不正确,mailaddress construtor将引发异常。这样的话,我知道我至少可以把邮件拿出去。当然,这是服务器端验证,但至少您需要这样做。


快速回答

使用以下regex进行输入验证:好的。

([-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|"([]!#-[^-~ \t]|(\\[\t -~]))+")@[0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?(\.[0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?)+好的。

此regex匹配的地址:好的。

  • 具有严格符合RFC 5321/5322的本地部件(即@符号前的部件)。
  • 有一个域部分(即@符号后面的部分),它是一个主机名,至少有两个标签,每个标签最长63个字符。

第二个约束是对RFC5321/5322的限制。好的。详尽的回答

使用识别电子邮件地址的正则表达式在各种情况下可能很有用:例如扫描文档中的电子邮件地址、验证用户输入或作为数据存储库的完整性约束。好的。

但是,应该注意的是,如果您想知道地址是否实际引用了现有邮箱,则无法替代向该地址发送邮件。如果您只想检查地址的语法是否正确,那么可以使用正则表达式,但请注意,""@[]是一个语法正确的电子邮件地址,它肯定不会引用现有的邮箱。好的。

电子邮件地址的语法已经在各种RFC中定义,最显著的是RFC822和RFC5322。RFC822应被视为"原始"标准,RFC5322应被视为最新标准。RFC822中定义的语法是最宽松的,随后的标准进一步限制了语法,在这种情况下,较新的系统或服务应该识别过时的语法,但决不生成它。好的。

在这个答案中,我将使用"电子邮件地址"来表示RFC中定义的addr-spec(即[email protected],但不是"John Doe",也不是some-group:[email protected],[email protected];)。好的。

将RFC语法转换成regex有一个问题:语法不规则!这是因为它们允许电子邮件地址中可以无限嵌套的可选注释,而无限嵌套不能由正则表达式描述。要扫描或验证包含注释的地址,您需要分析器或更强大的表达式。(注意,像Perl这样的语言都有以类似regex的方式描述上下文无关语法的构造。)在这个答案中,我将忽略注释,只考虑适当的正则表达式。好的。

RFC为电子邮件定义语法,而不是电子邮件地址。地址可能出现在不同的标题字段中,这是它们主要定义的地方。当它们出现在头字段中时,地址可能包含(在词汇标记之间)空格、注释甚至换行符。然而,从语义上讲,这没有意义。通过从一个地址中删除这个空格等,您可以得到一个语义上等价的规范表示。因此,first. last (comment) @ [3.5.7.9]的规范表示是first.last@[3.5.7.9]。好的。

不同的语法应该用于不同的目的。如果您想扫描(可能非常旧)文档中的电子邮件地址,最好使用RFC822中定义的语法。另一方面,如果要验证用户输入,您可能需要使用RFC5322中定义的语法,可能只接受规范表示。您应该决定哪种语法适用于您的特定情况。好的。

我在这个答案中使用POSIX"扩展"正则表达式,假设使用与ASCII兼容的字符集。好的。RFC 822

我得到了下面的正则表达式。我邀请每个人尝试打破它。如果你发现任何误报或误报,请发表评论,我会尽快修复表达。好的。

([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(
|(\\
)*([^"\\

]|\\[^
]))*(\\
)*")(\.([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(
|(\\
)*([^"\\

]|\\[^
]))*(\\
)*"))*@([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(
|(\\
)*([^][\\

]|\\[^
]))*(\\
)*])(\.([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(
|(\\
)*([^][\\

]|\\[^
]))*(\\
)*]))*好的。

我相信它完全符合包括勘误表在内的RFC822。它只以其规范形式识别电子邮件地址。对于识别(折叠)空白的regex,请参见下面的派生。好的。

推导过程显示了我是如何得出表达式的。我列出了RFC中所有相关的语法规则,与它们显示的完全相同,后面跟着相应的regex。在发布了勘误表的地方,我为已更正的语法规则(标记为"勘误表")提供了一个单独的表达式,并在随后的正则表达式中使用更新的版本作为子表达式。好的。

如第3.1.4段所述。在RFC822中,可选的线性空白可以插入词法标记之间。在适用的情况下,我扩展了表达式以适应此规则,并将结果标记为"opt lwsp"。好的。

RFC 5322

我得到了下面的正则表达式。我邀请每个人尝试打破它。如果你发现了任何误报或误报,请发表评论,我会尽快修复表达。好的。

([-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|"([]!#-[^-~ \t]|(\\[\t -~]))+")@([-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|\[[\t -Z^-~]*])好的。

我相信它完全符合包括勘误表在内的RFC5322。它只以其规范形式识别电子邮件地址。对于识别(折叠)空白的regex,请参见下面的派生。好的。

推导过程显示了我是如何得到表达式的。我列出了RFC中所有相关的语法规则,与它们出现的完全相同,后面跟着相应的regex。对于包含语义无关(折叠)空白的规则,我给出了一个单独的regex,标记为"(normalized)",它不接受这个空白。好的。

我忽略了来自RFC的所有"obs-"规则。这意味着regex只匹配严格符合RFC5322的电子邮件地址。如果您必须匹配"旧"地址(例如更宽松的语法,包括"obs-"规则),您可以使用上一段中的RFC822正则表达式之一。好的。

请注意,一些来源(尤其是W3C)声称RFC5322对本地部分(即@符号前的部分)过于严格。这是因为".."、"A..B"和"A."不是有效的点原子,而它们可以用作邮箱名称。然而,RFC允许像这样的本地部件,除非它们必须被引用。因此,你应该写"a..b"@example.net,而不是[email protected],这在语义上是等价的。好的。进一步限制

SMTP(定义见RFC5321)进一步限制了一组有效的电子邮件地址(或者实际上是邮箱名)。强加这种更严格的语法似乎是合理的,这样匹配的电子邮件地址就可以实际用于发送电子邮件。好的。

RFC5321基本上只保留"局部"部分(即@符号前的部分),但在域部分(即@符号后的部分)更严格。它只允许主机名代替点原子,地址字代替域字。好的。

当涉及到主机名和IP地址时,RFC5321中的语法太过宽泛。我冒昧地"修正"了相关的规则,使用这个草案和RFC1034作为指导方针。这是生成的regex。好的。

([-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|"([]!#-[^-~ \t]|(\\[\t -~]))+")@([0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?(\.[0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?)*|\[((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|IPv6:((((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){6}|::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){5}|[0-9A-Fa-f]{0,4}::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){4}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):)?(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){3}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,2}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){2}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,3}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,4}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::)((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3})|(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3})|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,5}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3})|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,6}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::)|(?!IPv6:)[0-9A-Za-z-]*[0-9A-Za-z]:[!-Z^-~]+)])好的。

注意,根据用例的不同,您可能不希望在regex中允许"常规地址文本"。另外请注意,我在最后的regex中使用了一个负的lookahead (?!IPv6:),以防止"常规地址文字"部分与格式错误的ipv6地址匹配。有些regex处理器不支持负向前看。如果要去掉整个"通用地址文字"部分,请从regex中删除子字符串|(?!IPv6:)[0-9A-Za-z-]*[0-9A-Za-z]:[!-Z^-~]+。好的。

推导如下:好的。

用户输入验证

一个常见的用例是用户输入验证,例如在HTML表单上。在这种情况下,排除地址文本和要求主机名中至少有两个标签通常是合理的。以前一节中改进的RFC 5321 regex为基础,得到的表达式为:好的。

([-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|"([]!#-[^-~ \t]|(\\[\t -~]))+")@[0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?(\.[0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?)+好的。

我不建议进一步限制本地部分,例如通过排除带引号的字符串,因为我们不知道某些主机允许使用哪种邮箱名称(如"a..b"@example.net甚至"a b"@example.net)。好的。

我也不建议针对文字顶级域列表进行明确验证,甚至不建议使用长度限制(记住".museum"如何使[a-z]{2,4}无效),但如果必须:好的。

([-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|"([]!#-[^-~ \t]|(\\[\t -~]))+")@([0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?\.)*(net|org|com|info|等…)等好的。

如果您决定执行显式顶级域验证,请确保您的regex是最新的。好的。进一步考虑

当只接受域部分中的主机名(@符号之后)时,上面的regex只接受最多63个字符的标签,因为它们应该接受。但是,它们并不强制要求整个主机名的长度不能超过253个字符(包括点)。虽然严格地说,这个约束仍然是规则的,但是要生成一个包含这个规则的regex是不可行的。好的。

另一个考虑因素,特别是在使用regex进行输入验证时,是对用户的反馈。如果用户输入的地址不正确,最好给出的反馈比简单的"语法错误地址"多一点。用"香草"正则表达式是不可能的。好的。

这两个注意事项可以通过解析地址来解决。在某些情况下,主机名上的额外长度约束也可以通过使用一个额外的regex来解决,该regex检查主机名,并将地址与两个表达式匹配。好的。

此答案中的所有regex都没有针对性能进行优化。如果性能是一个问题,您应该看看您选择的regex是否可以优化(以及如何优化)。好的。好啊。


网络上有很多这样的例子(我认为即使是一个可以完全验证RFC的例子——但是如果内存可用的话,它有数十/数百行长)。人们往往会对验证这类事情感到不知所措。为什么不检查一下它有一个@和至少一个。并满足一些简单的最小长度。输入一封假电子邮件,仍然匹配任何有效的regex,这很简单。我想假阳性比假阴性更好。


在决定允许哪些字符时,请记住您的撇号和连字符朋友。我无法控制我的公司使用我的名字从人力资源系统生成我的电子邮件地址。这包括我姓中的撇号。我不能告诉你有多少次我被阻止与一个网站互动,因为我的电子邮件地址是"无效的"。


此regex来自Perl的email::valid library。我相信这是最准确的,它符合所有822。它基于O'Reilly书中的正则表达式:

Regular expression built using Jeffrey Friedl's example in
Mastering Regular Expressions (http://www.ora.com/catalog/regexp/).


在用PHP编写时,我建议您使用PHP内置电子邮件验证。

如果运行的PHP版本低于5.3.6,请注意以下问题:https://bugs.php.net/bug.php?ID=53091

如果您想了解更多关于内置验证如何工作的信息,请参见这里:php的filter_var filter_validate_email是否实际工作?


Cal Henderson(Flickr)在PHP中写了一篇名为"解析电子邮件地址"的文章,并展示了如何正确地进行符合RFC(2)822的电子邮件地址解析。您还可以使用获得CC许可的PHP、Python和Ruby获取源代码。


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


没有真正有用的。我在回答中讨论了一些问题:是否有用于电子邮件地址验证的PHP库?在regexp中还讨论了如何硬识别电子邮件地址?

简言之,不要期望一个单一的、可用的regex做一个适当的工作。最好的regex将验证语法,而不是电子邮件的有效性([email protected]是正确的,但它可能会反弹…)。


一个至少不会拒绝任何有效电子邮件地址的简单正则表达式是检查某个内容,后跟@符号,然后是句点和至少2个内容。它不会拒绝任何东西,但是在审阅规范之后,我找不到任何有效和被拒绝的电子邮件。

email=~/.+@[^@]+\.[^@]{2,}$/


您可以使用jquery验证插件使用的插件:


有关验证电子邮件地址的最佳正则表达式的最全面评估,请参阅此链接;"比较电子邮件地址验证正则表达式"

以下是用于引用的当前top表达式:


更不用说在不久的将来允许使用非拉丁(中文、阿拉伯语、希腊语、希伯来语、西里尔文等)域名。每个人都必须更改regex使用的电子邮件,因为这些字符肯定不会被[a-z]/i\w覆盖。他们都会失败。

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

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

就这么简单。你到底为什么会关心名字和域名中使用的字符?客户有责任输入一个有效的电子邮件地址,而不是服务器的。即使客户输入一个语法上有效的电子邮件地址,如[email protected],这也不能保证它是合法的电子邮件地址。没有一个Regex可以覆盖这一点。


HTML5规范建议使用一个简单的regex来验证电子邮件地址:

这故意不符合RFC5322。

Note: This requirement is a willful violation of RFC 5322, which defines a syntax for e-mail addresses that is simultaneously too strict (before the @ character), too vague (after the @ character), and too lax (allowing comments, whitespace characters, and quoted strings in manners unfamiliar to most users) to be of practical use here.

根据RFC 3696勘误表1690,总长度也可以限制为254个字符。


对于一个生动的演示,下面的怪物是相当好的,但仍然不能正确识别所有语法上有效的电子邮件地址:它可以识别多达四层的嵌套注释。

对于解析器来说,这是一个任务,但是即使地址在语法上是有效的,它仍然可能无法交付。有时你不得不求助于乡巴佬式的"嘿,你们,看我们!"


这是我使用的PHP。我选择这个解决方案的精神是"假阳性比假阴性更好",正如这里的另一位评论员所声明的,关于保持您的响应时间上升和服务器负载下降…当使用正则表达式消除最简单的用户错误时,实际上不需要浪费服务器资源。如果你想的话,你可以发送一封测试邮件来跟进。


RFC 5322标准:

允许点原子本地部分、带引号的字符串本地部分、过时(混合点原子和带引号的字符串)本地部分、域名域(IPv4、IPv6和IPv4映射的IPv6地址)、域文本域和(嵌套)CFW。

RFC 5321标准:

允许点原子本地部分、带引号的字符串本地部分、域名域和(IPv4、IPv6和IPv4映射的IPv6地址)域文本域。

基本的:

允许点原子本地部分和域名域(至少需要两个域名标签,TLD限制为2-6个字母字符)。


根据官方标准RFC 2822,有效的电子邮件regex是

如果你想在Java中使用它,它真的很简单。


奇怪的是你"不能"允许4个字符的TLD。你在禁止人们使用.info和.name,以及限制长度的stop、travel和.museum,但是是的,它们比两个字符的tld和三个字符的tld要少。

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

对于域部分的regex,域名不能以"-"开头,也不能以"-"结尾。破折号只能停留在中间。

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



我已经用了一段时间了,这是你的regex的润色版,它没有给我太多的惊喜。我从未在电子邮件中遇到过撇号,因此它不会验证这一点。它确实验证了[email protected]试@例子.测试.????.???????,但没有奇怪地滥用这些非字母数字字符[email protected]

它确实支持IP地址[email protected],但我还没有对它进行足够的改进,以处理诸如999.999.999.1之类的假IP范围。

它还支持超过3个字符的所有TLD,这些字符停止了[email protected],我认为原始的let-through。我已经被打败了,现在有太多的TLD超过3个字符。

我知道阿克罗斯曼已经放弃了他的雷格克斯,但这种味道仍然存在。


如果您可以接受空值(这不是无效的电子邮件),并且正在运行php 5.2+,我建议:


我总是使用下面的正则表达式来验证电子邮件地址。这是我见过的验证电子邮件地址的最好的regex。

我在ASP.NET代码中总是使用这个正则表达式,我对此非常满意。

使用此程序集引用

并尝试以下代码,因为它很简单,可以为您完成工作。

此函数用于验证电子邮件字符串。如果电子邮件字符串为空,则返回假;如果电子邮件字符串的格式不正确,则返回假。只有电子邮件的格式有效时才会返回true。


我知道这个问题是关于regex的,但我猜想90%阅读这些解决方案的开发人员都在试图验证浏览器中显示的HTML表单中的电子邮件地址。

如果是这种情况,我建议检查新的HTML5 表单元素:

HTML5:

CSS3:

http://jsfiddle.net/myre7/1

这有两个优点:

  • 自动验证,无需定制解决方案:简单易用
  • 没有javascript,如果JS已被禁用,则没有问题。
  • 没有服务器必须为此计算任何内容
  • 用户有即时反馈
  • 旧浏览器应自动回退到输入类型"文本"
  • 移动浏览器可以显示专用键盘(@-键盘)
  • 使用CSS3,表单验证反馈非常简单
  • 明显的缺点可能是缺少对旧浏览器的验证,但这会随着时间的推移而改变。比起这些疯狂的雷鬼杰作,我更喜欢这个。

    还可以看到:

    • http://jsfiddle.net/myre7/1/
    • http://diveintohtml5.info/forms.html
    • http://blog.mozilla.org/webdev/2011/03/14/html5-form-validation-on-sumo/


    我们使用http://www.aspnetmx.com/已有几年的成功经验。您可以选择要验证的级别(例如语法检查、域检查、MX记录或实际电子邮件)。

    对于前端表单,我们通常会验证域是否存在以及语法是否正确,然后在进行批量邮件发送之前,我们会进行更严格的验证以清除数据库。


    我使用多步骤验证。由于没有完美的方法来验证电子邮件地址,因此无法创建完美的电子邮件地址,但至少您可以通知用户他/她正在做错误的事情-这是我的方法

    1)我首先使用非常基本的regex进行验证,它只检查电子邮件是否正好包含一个@符号,并且在该符号之前或之后不是空白的。如/^[^@\s]+@[^@\s]+$/

    2a)如果第一个验证器没有通过(对于大多数地址,它应该是不完美的),那么警告用户电子邮件是无效的,并且不允许他/她继续输入。

    2b)如果通过,则针对更严格的regex进行验证-这可能会禁止有效的电子邮件。如果不通过,则会警告用户可能发生的错误,但允许用户继续。与步骤(1)不同,因为这是一个明显的错误,所以不允许用户继续。

    换句话说,第一次自由验证只是为了去掉明显的错误,它被视为"错误"。人们输入一个空地址,不带@符号的地址等等。这应该被视为错误。第二个更严格,但被视为"警告",允许用户继续输入,但警告用户至少检查他/她输入的条目是否有效。这里的关键是错误/警告方法——错误是指在99.99%的情况下不能成为有效电子邮件的东西。

    当然,你可以调整什么使第一个正则表达式更自由,第二个正则表达式更严格。

    根据您的需要,上述方法可能适用于您。


    这是电子邮件的regex之一


    我不相信Bortzmeyer在上面所说的"语法(在rfc5322中指定)对它来说太复杂了"(不能用正则表达式来处理)。

    语法如下:(摘自http://tools.ietf.org/html/rfc5322第3.4.1节)

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


    我看到的每个regex(包括微软使用的一些regex)都不允许通过以下有效电子邮件:[email protected]

    刚刚有一个真正的客户有一个这种格式的电子邮件地址,他不能下订单。

    我的决定是:

    • 一个最小的正则表达式,不会有假阴性。或者使用带有一些附加检查的MailAddress构造函数(见下文):
    • 检查常见的输入错误.cmo.gmial.com并要求确认Are you sure this is your correct email address. It looks like there may be a mistake.允许用户接受他们键入的内容(如果他们确定)。
    • 处理在实际发送电子邮件时反弹,并手动验证它们以检查是否存在明显错误。


    我没有找到任何处理顶级域名的,但应该考虑。

    所以对我来说,以下的工作-

    很容易被丢弃的电子邮件,比如[email protected], [email protected]

    如果需要,可以进一步编辑域名,例如特定国家/地区的域名等。


    对我来说,检查电子邮件的正确方法是:

  • 检查符号@是否存在,符号前后有一些非@符号:
    /^[^@]+@[^@]+$/
  • 尝试用一些"激活码"向此地址发送电子邮件。
  • 当用户"激活"他的电子邮件地址时,我们会看到一切都是正确的。
  • 当然,当用户输入"奇怪"的电子邮件时,您可以在前端显示一些警告或工具提示,以帮助他避免常见的错误,如域部分没有点或名称中没有引用的空格等。但如果用户真的想要地址"hello@world",您必须接受它。

    另外,您必须记住,电子邮件地址标准是并且可以进化,所以您不能只输入一些"标准有效"的regexp一次又一次。而且,您必须记住,一些具体的互联网服务器可能会使一些通用标准的细节失效,实际上使用自己的"修改后的标准"。

    所以,只需检查@,在前端提示用户并在给定地址发送验证电子邮件。


    我仍在使用:

    但随着ipv6和unicode的出现,也许:

    是最好的。Gmail已经允许连续点,但MicrosoftExchangeServer2007拒绝了它们。


    根据我的理解,最有可能的情况是……


    现在有更多(1000)个TLD。这里的大多数答案需要投票否决,因为它们不再正确-这个问题可能有第二版。

    请随意访问其他帖子的更新讨论…


    对于php,我使用nette框架中的电子邮件地址验证程序-http://api.nette.org/2.3.3/source utils.validators.php.html 234-247


    我找到了一篇不错的文章,上面说验证电子邮件地址的最佳方法是使用regex expresion:/.+@.+\..+/i


    列表项

    我用这个函数


    根据RFC 2821和RFC 2822,电子邮件地址的本地部分可以使用以下任何ASCII字符:

  • 大写和小写字母
  • 数字0到9
  • 人物,!γ%$&AM'*+/=?^ {{}}
  • 字符"."的前提是它不是本地部分的第一个或最后一个字符。
  • 比赛:

    非匹配:

    对于符合RFC 2821、2822的产品,您可以使用:

    电子邮件-符合RFC 2821、2822


    由于新的通用顶级域(gtlds)即将到来(例如伦敦,.basketball,.通),此线程中发布的正则表达式现在已过时。要验证电子邮件地址,有两个答案(与绝大多数相关)。

  • 正如主答案所说-不要使用正则表达式,只需向地址发送电子邮件来验证它(捕获无效地址的异常)
  • 使用非常通用的regex至少要确保它们使用的是电子邮件结构{something}@{something}.{something}。使用详细的regex是没有意义的,因为你不能全部捕捉到它们,几年后会有一个新的批处理,你必须再次更新正则表达式。
  • 我决定使用正则表达式,因为不幸的是,有些用户不会读取表单,也不会将错误的数据放在错误的字段中。这至少会在他们试图将非电子邮件的内容放入电子邮件输入字段时提醒他们,这样可以节省您在电子邮件问题上为用户提供支持的时间。


    此规则与我们的后缀服务器无法发送的内容匹配。

    允许字母、数字、-、-、+、、&;、/、!

    没有-Fo.@ BA.com

    没有ASD@ -BAR.com


    嗯,奇怪的是,没有在答案中看到这个答案。这是我做的。它不是一个防弹版本,但它是"简单的",检查几乎所有的东西。

    我认为已经有了一个解释,如果您需要,可以修改它:

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

    (m)(?:\.[\w+-]+)*匹配a-z、a-z、x、+、-零次或更多次,但需要从a开始。(点)

    @=@

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

    (l)(?:\.[\w+-]+)*匹配a-z、a-z、x、+、-零次或更多次,但需要从a开始。(点)

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

    给予e(.m)@i(.l).com,其中(.m)(.l)是可选的,但也可以重复多次。我认为这会验证所有有效的电子邮件地址,但会阻止潜在的无效地址,而不使用在大多数情况下不必要的过于复杂的正则表达式。

    注意,这将允许[email protected],但这是保持简单的折衷办法。


    我不建议使用regex——电子邮件地址太复杂了。这是一个常见的问题,所以我猜想有很多库包含一个验证器——如果你使用Java,Apache Calon验证器的EualValueAuthor是一个很好的库。


    没有人提到本地化的问题(i18),如果你有来自世界各地的客户呢?然后,您需要按国家/地区对regex进行子分类,我看到开发人员最终构建了一个大型字典/配置。检测用户的浏览器语言设置可能是一个很好的起点。


    不得不提的是,几乎已经添加了新的域名"yandex"。可能的电子邮件:[email protected]。而且还支持大写字母,所以稍微修改一下的Acrosman解决方案版本是:


    Java邮件API对我们有魔力。

    我从这里得到这个


    如果你想改进一个已经相当好用了几年的regex,那么答案取决于你到底想要达到什么样的目标——什么样的电子邮件地址失败了。微调电子邮件正则表达式非常困难,我还没有看到一个完美的解决方案。

    • 如果您的应用程序在本质上涉及到一些非常技术性的东西(或者组织内部的东西),那么您可能需要支持IP地址而不是域名,或者在电子邮件地址的"本地"部分提供注释。
    • 如果您的应用程序是多国的,我会考虑重点支持unicode/utf8。

    您问题的主要答案当前链接到"完全RFC"?822–符合REGEX"。然而,尽管regex的复杂性和它在RFC规则中对细节的假定关注,但在Unicode支持方面它完全失败了。

    我为我的大多数应用程序编写的regex着重于Unicode支持,以及对RFC标准的合理良好的总体遵从性:

    我将避免复制粘贴完整的答案,所以我将这个链接到我在这里提供的类似答案:如何验证Unicode电子邮件?

    上面的regex还有一个实时演示,网址是:http://jsfiddle.net/aossikine/qclvh/3/


    很好,我把代码转换成Java来匹配编译器。


    世界上最流行的博客平台WordPress使用此功能验证电子邮件地址。

    但他们是通过多个步骤来实现的。

    在使用此函数中提到的regex时,不再需要担心。

    这是函数……


    根据我所看到的,一个完全按照标准所说的做的regex是允许的,是这样的:

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

    分裂:

    分析:

    对以.开头、以..结尾、或超过最大长度254个字符的地址进行反向前瞻。

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

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

    不允许以.开头或结尾的每个域名都为负向前看。

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

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

    域名的替代方法:将IP地址中的前3个数字与后面的.匹配,然后将IP地址中的第4个数字与后面没有.的数字匹配。


    下面是验证电子邮件地址的正则表达式


    如前所述,您不能用regex验证电子邮件。但是,这里是我们目前用来确保用户输入不是完全伪造的(忘记TLD等)。

    此regex将允许在@符号前后使用IDN域和特殊字符(如umlauts)。


    我有一个类似的愿望:希望在电子邮件地址中快速检查语法,而不会超出电子邮件发送实用程序的范围(Mail::RFC822::Address答案,这显然是正确的答案)。我是这样做的(我是一个posix-re人,所以我通常不使用\d和pcre的类似工具,因为它们会使我看不清东西):

    这是正确的RFC,但明确排除了过时的表单以及直接IP(IP和传统IP都是),该实用程序的目标组中的某个人(主要是:在IRC上发送邮件时打扰我们的人)通常不会想要或需要这些IP。

    IDN(国际化域名)明确不在电子邮件范围内:地址如"foo@c"?cilinchor bonn.de"必须在网上写"[email protected]"(这包括mailto:html中的链接和类似的乐趣),只允许GUI显示(接受然后转换)这些名称到(和来自)用户。


    我发现了一个符合RFC2822的正则表达式。上述标准符合RFC 5322。这个正则表达式的性能似乎相当好,可以覆盖大多数情况,但是随着RFC5322成为标准,可能会有一些应该堵塞的孔。

    文档中说您不应该使用上面的正则表达式,而是更喜欢这种风格,这种风格更易于管理。

    我注意到这是区分大小写的,所以我对这个着陆点做了修改。


    您可以对任何电子邮件地址使用以下正则表达式

    对于PHP

    对于JavaScript


    根据W3组织和维基百科的有效regex

    例如!γ%$&AM'*+/=?^`[email protected]


    这匹配了99.99%的电子邮件地址,包括一些更新的顶级域名扩展,如信息、博物馆、名称等。它还允许直接绑定到IP地址的电子邮件。


    我用这个;


    我用过

    包括大写字母。在这种情况下,您甚至不需要使用ToLowercase。


    对于Angular2/Angular7,我使用以下模式:

    它还允许在末尾添加额外的空间,在将其发送到后端之前应该截断这些空间,但是有些用户,特别是在移动设备上,很容易在末尾错误地添加空间。


    正则表达式的简捷语法

    在代码中使用验证电子邮件。


    为了使用javascript验证电子邮件地址,使用此功能(根据W3School)更方便和高效:

    我用它,它很完美。我希望有用。