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

How can I validate an email address using a regular expression?

提问人: 提问时间:10/14/2008 最后编辑:19 revs, 15 users 52%acrosman 更新时间:5/18/2023 访问量:2436397

问:

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

我在几个PHP程序中使用它,而且它大部分时间都在工作。但是,有时有人会联系我,他们在使用它的网站时遇到问题,我最终不得不做出一些调整(最近我意识到我不允许使用四个字符的顶级域名)。

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

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

正则表达式

评论

10赞 Jasen 8/30/2017
可以验证 IDNA 格式是否正确的正则表达式不适合 stackexchange。(规范化的规则非常曲折,特别不适合正则表达式处理)
13赞 klutt 1/9/2018
为什么你不应该这样做:使用正则表达式验证电子邮件地址会造成伤害吗?
0赞 Ṃųỻịgǻňạcểơửṩ 7/23/2018
正则表达式可能是可变的,因为在某些情况下,电子邮件骗局可以包含空格,而在其他时候,它不能包含任何空格。
0赞 Did 5/17/2021
您可以检查 Symfonys 正则表达式是否进行松散和严格的检查:github.com/symfony/symfony/blob/5.x/src/Symfony/Component/...
0赞 MMMahdy-PAPION 6/8/2021
仅使用正则表达式可能会损害服务器安全性,但如果它只是作为一种输入模式,我建议使用这个: stackoverflow.com/questions/5601647/...

答:

199赞 3 revs, 3 users 73%Per Hornshøj-Schierbeck #1

我使用

^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$

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

评论

37赞 Phrogz 1/20/2011
喝倒彩!我的(不明智的)地址被拒绝了。[email protected]
5赞 Tomasz Szulc 11/19/2015
根据此页面 data.iana.org/TLD/tlds-alpha-by-domain.txt 没有顶级只有一个字符的域,例如“something.c”、“something.a”,以下是支持至少 2 个字符的版本:“something.pl”、“something.us”:^\\w+([-+.']\\w+)*@\\w+([-.]\\w+)*\\.\\w{2,}([-.]\\w+)*$
6赞 Patanjali 11/28/2015
@Wayne惠蒂。您已经遇到了一个主要问题,即是迎合绝大多数地址,还是满足所有地址的需求,包括那些没有人会使用的地址,除了测试电子邮件验证。
2赞 Pratik Joshi 12/6/2015
我们想要对此:)的解释。人们来这里是为了看看为什么会这样。也请考虑正则表达式的解释!不是每个人都足够先进,可以不加解释地知道你在那里写了什么。谢谢
3赞 Simon_Weaver 2/10/2017
这实际上无效(我们的一个客户有一个类似的地址)'[email protected]
149赞 3 revs, 2 users 55%Peter Mortensen #2

我不知道最好,但这个至少是正确的,只要地址的评论被剥离并用空格替换。

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

评论

3赞 bortzmeyer 10/14/2008
据我所知,有些图书馆也错了。我依稀记得PHP PEAR有这样一个错误。
0赞 Chris Vest 10/14/2008
该页面的底部还有一个免责声明,内容是关于规范中正则表达式不支持的几件事。
7赞 tchrist 11/8/2010
这是 RFC 822 规范,而不是 RFC 5322 规范。
14赞 Blazemonger 10/27/2011
归根结底,他是对的,因为真正验证电子邮件地址的唯一方法是向其发送电子邮件并等待回复。
78赞 2 revs, 2 users 75%Peter Mortensen #3

互联网上有很多这样的例子(我认为即使是一个完全验证 RFC 的例子——但如果没记错的话,它有几十/几百行长)。

人们往往会得意忘形地验证这种事情。为什么不检查它有一个 @ 和至少一个并满足一些简单的最小长度?输入一封假电子邮件并且仍然匹配任何有效的正则表达式是微不足道的。我猜误报比漏报好。.

评论

1赞 tchrist 11/8/2010
是的,但是哪个 RFC?:)这个 [RFC‐5322–validator ](stackoverflow.com/questions/201323/...) 只有大约 40 行长。
17赞 Sijmen Mulder 2/15/2011
一个。不是必需的。TLD 可以有电子邮件地址,也可以有 IPv6 地址
3赞 Synchro 9/10/2014
RFC并不是故事的结局:ICANN不再允许“无点”域名:icann.org/news/announcement-2013-08-30-en
44赞 Kon #4

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

评论

0赞 Tim Wißmann 7/9/2021
不错的网站,但是他们内置的电子邮件垃圾邮件保护部分隐藏了一些模式,这有点奇怪。尤其是那些与电子邮件匹配相关的内容。:D
1赞 Peter Mortensen 2/13/2022
该链接是一个搜索查询,例如“搜索结果:找到 4128 个正则表达式”。具体是哪一个?你如何选择?
3342赞 25 revs, 20 users 17%bortzmeyer #5

完全符合 RFC 822 的正则表达式由于其长度而效率低下且模糊不清。幸运的是,RFC 822 被取代了两次,当前电子邮件地址的规范是 RFC 5322。RFC 5322 导致一个正则表达式,如果研究几分钟就可以理解该正则表达式,并且对于实际使用来说足够有效。

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

纠正 IP 模式中的错误,我们得到了一个工作且相当快的正则表达式。(抓取呈现的版本,而不是 Markdown 以获取实际代码。00

(?:[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])+)\])

艺术

(?:[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])+)\])

这是上述正则表达式的有限状态机,它比正则表达式本身更清晰enter image description here

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

同样重要的是要了解,根据 RFC 对其进行验证绝对不会告诉您该地址是否实际存在于提供的域中,或者输入该地址的人是否是其真正的所有者。人们总是以这种方式将其他人注册到邮件列表。要解决这个问题,需要一种更高级的验证,包括向该地址发送一条消息,其中包含一个确认令牌,该令牌旨在与该地址在同一网页上输入。

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

对于 PHP,您不应该使用我引用的 Validate an E-Mail Address with PHP, the Right Way 中给出的模式:

存在着一些危险,即普遍使用和普遍的草率编码将建立一种比记录的正式标准更严格的电子邮件地址事实上的标准。

这并不比所有其他非 RFC 模式好。它甚至不够智能,无法处理 RFC 822,更不用说 RFC 5322 了。然而,这个是。

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

指定的电子邮件地址“myemail@address,com”无效。你的意思是“[email protected]”?

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

Regular expression visualization

Debuggex 演示

评论

259赞 Tomalak 10/14/2008
你说“没有好的正则表达式。这是针对电子邮件地址验证的常规还是特定?
59赞 Luk 10/15/2008
@Tomalak:仅适用于电子邮件地址。正如 bortzmeyer 所说,RFC 非常复杂
46赞 Dominic Sayers 4/8/2009
你提到的 linux 期刊文章在几个方面都是错误的。特别是,洛弗尔显然没有阅读勘误表RFC3696并重复了RFC已发布版本中的一些错误。更多信息请见:dominicsayers.com/isemail
8赞 Synchro 9/10/2014
请注意,当前的 HTML5 规范包括用于电子邮件类型输入验证的正则表达式和 ABNF,它故意比原始 RFC 更具限制性。
18赞 Jared Beck 4/11/2019
RFC 822,第 6.2.4 节。明确和明确地允许使用大写字母,但这个答案没有。 w3.org/Protocols/rfc822/#z26 也许这个答案的作者打算不敏感地应用他们的正则表达式。如果是这样,则应在答案的正文中明确说明。
553赞 6 revs, 5 users 72%Andy Lester #6

这完全取决于您想要的准确性。出于我的目的,我只是想排除诸如(电子邮件中的空格)或(根本没有域)或(.com 之前没有句点)之类的东西,我使用bob @ aol.comstevemary@aolcom

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

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

可以对该正则表达式进行任意数量的更改(其中一些在此答案的评论中),但它简单易懂,并且是一个很好的第一次尝试。

评论

9赞 bortzmeyer 10/15/2008
它与有效且有效的电子邮件地址foobar@dk不匹配(尽管大多数邮件服务器可能不接受它或添加 something.com。
7赞 David Thornley 12/18/2009
@Richard: 包含在 ..\S
67赞 Andy Lester 10/17/2012
JJJ:是的,它会匹配很多废话。它将匹配 &$*#$(@$0(%))$#。&*)(*$。对我来说,我更关心的是抓住奇怪的摸索手指错别字,而不是我完全是垃圾。YMMV。mary@aolcom
14赞 Chris Moschini 8/5/2014
只是为了控制迹象:jsfiddle.net/b9chris/mXB96@/^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/
27赞 Piskvor left the building 9/24/2015
还有另一个常见的错别字:域名中有两个连续的点,或者用逗号代替点。^[^\s@]+@([^\s@.,]+\.)+[^\s@.,]{2,}$
39赞 4 revs, 3 users 61%Peter Mortensen #7

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

简而言之,不要指望一个单一的、可用的正则表达式来做正确的工作。最好的正则表达式将验证语法,而不是电子邮件的有效性([email protected]是正确的,但它可能会退回......

评论

0赞 tchrist 11/8/2010
如果我错了,请纠正我,但我相信PHP使用PCRE模式。如果是这样,您应该能够制作类似于 Abigail 的 RFC 5322 模式的东西。
0赞 PhiLho 11/10/2010
@tchrist:不确定PCRE是否赶上了这个语法(我发现的)。如果是这样,不确定PHP的PCRE是否赶上了这个版本的PCRE......好吧,如果我正确理解了这个语法,你也可以使用 PEG 解析器,无论如何都比正则表达式更清晰、更完整。
0赞 tchrist 11/10/2010
PCRE已经赶上了它,但也许PHP还没有赶上PCRE。☹
46赞 2 revs, 2 users 67%adnam #8

Cal Henderson (Flickr) 写了一篇名为《在 PHP 中解析电子邮件地址》的文章,展示了如何正确解析符合 RFC (2)822 的电子邮件地址。

您还可以获取 PHP、Python 和 Ruby 的源代码,这些源代码已获得 Creative Commons 许可

评论

0赞 dsdsdsdsd 4/16/2014
它告诉我这是有效的a@b
3赞 rink.attendant.6 8/1/2015
@dsdsdsdsd 因为是有效的...在本例中为顶级域。a@bb
0赞 darkdragon 9/16/2023
带有 Python 和 Ruby 版本的原始页面已关闭。人们仍然可以在 Wayback Machine 中找到它们。
612赞 4 revs, 4 users 67%JacquesB #9

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

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

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

评论

125赞 Martin Beckett 8/26/2009
可能值得检查他们是否在客户端验证中something@something输入字段只是为了发现简单的错误 - 但总的来说你是对的。
149赞 nickf 6/2/2010
@olavk:如果有人输入了一个错别字(例如:),他们显然不会收到你的确认电子邮件,然后他们在哪里?他们不再在您的网站上,他们想知道为什么他们无法注册。其实不,他们不是——他们已经完全忘记了你。但是,如果你可以在他们仍然和你在一起的时候用正则表达式做一个基本的健全性检查,那么他们就可以立即捕捉到这个错误,你就得到了一个满意的用户。me@hotmail
5赞 tchrist 11/8/2010
@JacquesB:你说得很有道理。仅仅因为它通过了 RFC 的集合并不意味着它真的是该用户的地址。否则,所有这些地址都表明他是一个非常忙碌的总司令。:)[email protected]
56赞 ninjaneer 2/18/2014
它不一定是黑色或白色的。如果电子邮件看起来有问题,请让用户知道。如果用户仍想继续,请让他继续。不要强迫用户遵守你的正则表达式,而是使用正则表达式作为工具来帮助用户知道可能存在错误。
2赞 Gellweiler 11/5/2021
安全。如果您正确验证电子邮件地址并且只允许安全字符,则电子邮件地址被以某种恶意方式使用的可能性会大大降低。例如,在电子邮件标题漏洞中。
8赞 2 revs, 2 users 78%Joseph Yee #10

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

您也应该允许使用大写字母。电子邮件系统将对本地部分和域部分进行规范化。

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

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

评论

3赞 tchrist 11/8/2010
@Joseph Yee:RFC 822 是不是有点过时了?
1赞 Peter Mortensen 2/13/2022
回复“不能”允许 4 个字符的 TLD“:你指的是什么?
4赞 2 revs, 2 users 64%Peter Mortensen #11

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

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

评论

0赞 Peter Mortensen 2/13/2022
链接已断开(超时)-“无法连接。连接到 www.aspnetmx.com 时出错。
0赞 cbp 2/14/2022
这最初是在 2008 年回答的。:-)时间都去哪儿了......
118赞 2 revs, 2 users 65%davcar #12

我想要验证的电子邮件地址将由使用命名空间的 ASP.NET Web 应用程序使用,以向人员列表发送电子邮件。System.Net.Mail

因此,我没有使用一些非常复杂的正则表达式,而是尝试从地址创建一个实例。如果地址格式不正确,构造函数将引发异常。这样,我知道我至少可以把电子邮件送出去。当然,这是服务器端验证,但至少你还是需要它。MailAddressMailAddress

protected void emailValidator_ServerValidate(object source, ServerValidateEventArgs args)
{
    try
    {
        var a = new MailAddress(txtEmail.Text);
    }
    catch (Exception ex)
    {
        args.IsValid = false;
        emailValidator.ErrorMessage = "email: " + ex.Message;
    }
}

评论

4赞 User 6/16/2009
一个好点子。即使此服务器验证拒绝了某些有效地址,也不是问题,因为无论如何您都无法使用此特定服务器技术发送到此地址。或者,您可以尝试使用您使用的任何第三方电子邮件库而不是默认工具来执行相同的操作。
1赞 Cory House 8/16/2010
我真的很喜欢它如何利用 .Net 框架代码 - 重新发明轮子毫无意义。这太好了。简单、干净,并确保您可以实际发送电子邮件。干得好。
0赞 Tom Carter 9/17/2010
...是的,对于那些对它如何验证感兴趣的人,请查看 Reflector 中的代码 - 它有很多 - 而且它不是一个正则表达式!
2赞 porges 5/31/2011
请注意:MailAddress 类与RFC5322不匹配,如果您只想使用它进行验证(并且不发送,在这种情况下,如上所述,这是一个有争议的问题)。请参阅:stackoverflow.com/questions/6023589/...
0赞 pholpar 8/21/2019
只是一个小问题:如果你想使你的服务器端验证器代码更可重用(在这种情况下或一般情况下),我建议使用而不是像硬编码那样引用字段。后者会将您的验证器绑定到单个控件实例,只要您有一个电子邮件字段,这可能没问题,但不建议这样做。args.ValuetxtEmail.Text
299赞 9 revs, 4 users 74%Dominic Sayers #13

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

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

我整理了来自 Cal Henderson、Dave Child、Phil Haack、Doug Lovell、RFC 5322RFC 3696 的测试用例。总共 275 个测试地址。我针对我能找到的所有免费验证器运行了所有这些测试。

我会尽量让这个页面保持最新,因为人们增强了他们的验证者。感谢 Cal、Michael、Dave、Paul 和 Phil 在编译这些测试时的帮助和合作,以及对我自己的验证者的建设性批评。

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

评论

0赞 tchrist 11/8/2010
这个验证器似乎也是正确的。[...时间流逝...]嗯,看起来它只是 RFC 5322,而不是 3693 或其勘误表。
2赞 bgmCoder 4/10/2013
很好。在这里,我们不仅得到了一篇漂亮的论文,还得到了一个验证测试器以及一个可供下载的库。不错的答案!
2赞 Josef 3/25/2015
您的验证器不支持 punycode (RFC 3492)。name@öäü.at 可以是有效的地址。(翻译为 [email protected])
0赞 Dominic Sayers 4/28/2015
嗨,@Josef。您应该尝试验证,因为此代码是关于验证的,而不是解释的。如果您想添加一个 punycode 翻译器,那么我很乐意接受 github.com/dominicsayers/isemail 的拉取请求[email protected]
376赞 8 revs, 6 users 91%Good Person #14

这取决于你所说的最好的意思: 如果您谈论的是捕获每个有效的电子邮件地址,请使用以下命令:

(?:(?:\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*)

(http://www.ex-parrot.com/~pdw/Mail-RFC822-Address.html) 如果您正在寻找更简单但可以捕获大多数有效电子邮件地址的东西,请尝试以下方法:

"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$"

编辑: 从链接:

此正则表达式将仅验证已剥离任何注释并替换为空格的地址(这是由模块完成的)。

评论

65赞 Lazer 5/16/2010
你能给我举个例子,说明一些错误地通过第二个,但被更长的正则表达式抓住的例子吗?email address
4赞 tchrist 11/8/2010
虽然我曾经很喜欢它,但它是一个 RFC 822 验证器,而不是 RFC 5322 验证器。
28赞 Randal Schwartz 12/7/2011
@Lazer [email protected] 将是一个简单的例子。不允许在局部部分中有两个连续的不带引号的点。
5赞 Good Person 1/9/2013
@Mikhail perl,但你实际上不应该使用它。
3赞 Good Person 5/29/2014
@RSC这是一个 FQDN,这很好
30赞 chaos #15

您可以使用jQuery验证插件所采用的那个:

/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i

评论

0赞 dsdsdsdsd 4/16/2014
这似乎做得很好。它允许: 但能够捕捉到不适当的变化,例如 和a-b'[email protected]a-b'[email protected]a-b'[email protected]
2赞 norok2 9/1/2021
你有什么参考吗?
16赞 3 revs, 2 users 66%Greg Bacon #16

为了生动地演示,下面的怪物相当不错,但它仍然无法正确识别所有语法有效的电子邮件地址:它可以识别最多四级的嵌套注释。

这是解析器的工作,但即使地址在语法上有效,它仍然可能无法交付。有时你不得不求助于乡巴佬的方法,“嘿,你们,看着我们!

// derivative of work with the following copyright and license:
// Copyright (c) 2004 Casey West.  All rights reserved.
// This module is free software; you can redistribute it and/or
// modify it under the same terms as Perl itself.

// see http://search.cpan.org/~cwest/Email-Address-1.80/

private static string gibberish = @"
(?-xism:(?:(?-xism:(?-xism:(?-xism:(?-xism:(?-xism:(?-xism:\
s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^
\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))
|(?-xism:\\(?-xism:[^\x0A\x0D]))|)+)*\s*\)\s*))+)*\s*\)\s*)+
|\s+)*[^\x00-\x1F\x7F()<>\[\]:;@\,.<DQ>\s]+(?-xism:(?-xism:\
s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^
\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))
|(?-xism:\\(?-xism:[^\x0A\x0D]))|)+)*\s*\)\s*))+)*\s*\)\s*)+
|\s+)*)|(?-xism:(?-xism:(?-xism:\s*\((?:\s*(?-xism:(?-xism:(
?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\((?
:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x
0D]))|)+)*\s*\)\s*))+)*\s*\)\s*)+|\s+)*<DQ>(?-xism:(?-xism:[
^\\<DQ>])|(?-xism:\\(?-xism:[^\x0A\x0D])))+<DQ>(?-xism:(?-xi
sm:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xis
m:[^\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\
]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|)+)*\s*\)\s*))+)*\s*\)\
s*)+|\s+)*))+)?(?-xism:(?-xism:(?-xism:\s*\((?:\s*(?-xism:(?
-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:
\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[
^\x0A\x0D]))|)+)*\s*\)\s*))+)*\s*\)\s*)+|\s+)*<(?-xism:(?-xi
sm:(?-xism:(?-xism:(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^(
)\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\((?:\s*(
?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))
|)+)*\s*\)\s*))+)*\s*\)\s*)+|\s+)*(?-xism:[^\x00-\x1F\x7F()<
>\[\]:;@\,.<DQ>\s]+(?:\.[^\x00-\x1F\x7F()<>\[\]:;@\,.<DQ>\s]
+)*)(?-xism:(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))
|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-xism:
(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|)+)*\s
*\)\s*))+)*\s*\)\s*)+|\s+)*)|(?-xism:(?-xism:(?-xism:\s*\((?
:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x
0D]))|(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xi
sm:\\(?-xism:[^\x0A\x0D]))|)+)*\s*\)\s*))+)*\s*\)\s*)+|\s+)*
<DQ>(?-xism:(?-xism:[^\\<DQ>])|(?-xism:\\(?-xism:[^\x0A\x0D]
)))+<DQ>(?-xism:(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\
]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-x
ism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|)+
)*\s*\)\s*))+)*\s*\)\s*)+|\s+)*))\@(?-xism:(?-xism:(?-xism:(
?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?
-xism:[^\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^
()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|)+)*\s*\)\s*))+)*\s
*\)\s*)+|\s+)*(?-xism:[^\x00-\x1F\x7F()<>\[\]:;@\,.<DQ>\s]+(
?:\.[^\x00-\x1F\x7F()<>\[\]:;@\,.<DQ>\s]+)*)(?-xism:(?-xism:
\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[
^\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+)
)|(?-xism:\\(?-xism:[^\x0A\x0D]))|)+)*\s*\)\s*))+)*\s*\)\s*)
+|\s+)*)|(?-xism:(?-xism:(?-xism:\s*\((?:\s*(?-xism:(?-xism:
(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\((
?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\
x0D]))|)+)*\s*\)\s*))+)*\s*\)\s*)+|\s+)*\[(?:\s*(?-xism:(?-x
ism:[^\[\]\\])|(?-xism:\\(?-xism:[^\x0A\x0D])))+)*\s*\](?-xi
sm:(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:
\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-xism:(?-xism:(
?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|)+)*\s*\)\s*))+
)*\s*\)\s*)+|\s+)*)))>(?-xism:(?-xism:\s*\((?:\s*(?-xism:(?-
xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:\
s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^
\x0A\x0D]))|)+)*\s*\)\s*))+)*\s*\)\s*)+|\s+)*))|(?-xism:(?-x
ism:(?-xism:(?-xism:(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^
()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\((?:\s*
(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D])
)|)+)*\s*\)\s*))+)*\s*\)\s*)+|\s+)*(?-xism:[^\x00-\x1F\x7F()
<>\[\]:;@\,.<DQ>\s]+(?:\.[^\x00-\x1F\x7F()<>\[\]:;@\,.<DQ>\s
]+)*)(?-xism:(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+)
)|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-xism
:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|)+)*\
s*\)\s*))+)*\s*\)\s*)+|\s+)*)|(?-xism:(?-xism:(?-xism:\s*\((
?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\
x0D]))|(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-x
ism:\\(?-xism:[^\x0A\x0D]))|)+)*\s*\)\s*))+)*\s*\)\s*)+|\s+)
*<DQ>(?-xism:(?-xism:[^\\<DQ>])|(?-xism:\\(?-xism:[^\x0A\x0D
])))+<DQ>(?-xism:(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\
\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-
xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|)
+)*\s*\)\s*))+)*\s*\)\s*)+|\s+)*))\@(?-xism:(?-xism:(?-xism:
(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(
?-xism:[^\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[
^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|)+)*\s*\)\s*))+)*\
s*\)\s*)+|\s+)*(?-xism:[^\x00-\x1F\x7F()<>\[\]:;@\,.<DQ>\s]+
(?:\.[^\x00-\x1F\x7F()<>\[\]:;@\,.<DQ>\s]+)*)(?-xism:(?-xism
:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:
[^\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+
))|(?-xism:\\(?-xism:[^\x0A\x0D]))|)+)*\s*\)\s*))+)*\s*\)\s*
)+|\s+)*)|(?-xism:(?-xism:(?-xism:\s*\((?:\s*(?-xism:(?-xism
:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\(
(?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A
\x0D]))|)+)*\s*\)\s*))+)*\s*\)\s*)+|\s+)*\[(?:\s*(?-xism:(?-
xism:[^\[\]\\])|(?-xism:\\(?-xism:[^\x0A\x0D])))+)*\s*\](?-x
ism:(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism
:\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-xism:(?-xism:
(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|)+)*\s*\)\s*))
+)*\s*\)\s*)+|\s+)*))))(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?
>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\((?:
\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0
D]))|)+)*\s*\)\s*))+)*\s*\)\s*)*)"
  .Replace("<DQ>", "\"")
  .Replace("\t", "")
  .Replace(" ", "")
  .Replace("\r", "")
  .Replace("\n", "");

private static Regex mailbox =
  new Regex(gibberish, RegexOptions.ExplicitCapture);

评论

1赞 Peter Mortensen 2/13/2022
什么编程语言?C#
4赞 3 revs, 3 users 67%Nazmul Hasan #17

这是电子邮件的正则表达式之一:

^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$

评论

0赞 Peter Mortensen 2/13/2022
它看起来像线路噪声。你有解释和/或参考吗?
6赞 4 revs, 3 users 60%Dimitris Andreou #18

我不相信 bortzmeyer 声称“语法(在 RFC 5322 中指定)太复杂了”(无法由正则表达式处理)。

这是语法(从 3.4.1.Addr-Spec 规范):

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 "\"

假设 dot-atom、quoted-string、obs-local-part、obs-domain 本身就是常规语言,这是一个非常简单的语法。只需将 addr-spec production 中的 local-part 和 domain 替换为它们各自的 production,您就拥有了可直接转换为正则表达式的常规语言。

评论

5赞 rjbs 12/17/2009
在开始在此处做出假设之前,您应该调查 CFWS。这是一场噩梦。
0赞 Dimitris Andreou 1/4/2010
CFWS = (1*([FWS] 注释) [FWS]) / FWS.尽管如此,我还是没有看到任何规则使语言不规则。当然,这很复杂,但复杂的正则表达式仍然可以处理它。
3赞 Luna 12/6/2016
这并不能回答这个问题。这是对另一个答案的回应。
0赞 awwright 9/13/2020
CFWS不是电子邮件地址的一部分,而是MIME语法的一部分。请参阅我的答案 stackoverflow.com/a/63841473/7117939 了解原因。
43赞 5 revs, 3 users 86%spig #19

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

电子邮件 =~/.+@[^@]+\.[^@]{2,}$/

评论

5赞 Josh 11/11/2011
这就是我一直在寻找的。限制性不强,但请确保只有 1 @(因为我们正在解析列表并希望确保没有缺少逗号)。仅供参考,如果它在引号中,您可以在左侧有一个 @:Valid_email_addresses,但它非常边缘。
3赞 Josh 11/11/2011
使用后,意识到它并不完全有效。 实际上检查 1 @ 符号。由于末尾的 .*,您的正则表达式将允许多个通过。/^[^@]+@[^@]+\.[^@]{2}[^@]*$/
2赞 spig 11/15/2011
右。我不是要拒绝所有无效的,只是不要拒绝有效的电子邮件地址。
2赞 FLY 1/14/2013
使用这个会好得多:确保它以 2 到 4 个非 @ 字符结尾。正如@Josh所指出的,它现在允许在最后增加一个@。但您也可以将其更改为:因为所有顶级域都是 a-Z 字符。您可以替换 WITH 或更多,从而允许顶级域名将来也更长。/^[^@]+@[^@]+\.[^@]{2,4}$//^[^@]+@[^@]+\.[^a-z-A-Z]{2,4}$/45
1赞 Artfaith 9/1/2020
如果非 ASCII 字符在仅支持数十台服务器的地方使用怎么办,但是......至少,然后......A-Za-z0-9
11赞 58 revs, 2 users 98%MichaelRushton #20

RFC 5322 标准:

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

'/^(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){255,})(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){65,}@)((?>(?>(?>((?>(?>(?>\x0D\x0A)?[\t ])+|(?>[\t ]*\x0D\x0A)?[\t ]+)?)(\((?>(?2)(?>[\x01-\x08\x0B\x0C\x0E-\'*-\[\]-\x7F]|\\\[\x00-\x7F]|(?3)))*(?2)\)))+(?2))|(?2))?)([!#-\'*+\/-9=?^-~-]+|"(?>(?2)(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\x7F]))*(?2)")(?>(?1)\.(?1)(?4))*(?1)@(?!(?1)[a-z0-9-]{64,})(?1)(?>([a-z0-9](?>[a-z0-9-]*[a-z0-9])?)(?>(?1)\.(?!(?1)[a-z0-9-]{64,})(?1)(?5)){0,126}|\[(?:(?>IPv6:(?>([a-f0-9]{1,4})(?>:(?6)){7}|(?!(?:.*[a-f0-9][:\]]){8,})((?6)(?>:(?6)){0,6})?::(?7)?))|(?>(?>IPv6:(?>(?6)(?>:(?6)){5}:|(?!(?:.*[a-f0-9]:){6,})(?8)?::(?>((?6)(?>:(?6)){0,4}):)?))?(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(?>\.(?9)){3}))\])(?1)$/isD'

RFC 5321 标准:

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

'/^(?!(?>"?(?>\\\[ -~]|[^"])"?){255,})(?!"?(?>\\\[ -~]|[^"]){65,}"?@)(?>([!#-\'*+\/-9=?^-~-]+)(?>\.(?1))*|"(?>[ !#-\[\]-~]|\\\[ -~])*")@(?!.*[^.]{64,})(?>([a-z0-9](?>[a-z0-9-]*[a-z0-9])?)(?>\.(?2)){0,126}|\[(?:(?>IPv6:(?>([a-f0-9]{1,4})(?>:(?3)){7}|(?!(?:.*[a-f0-9][:\]]){8,})((?3)(?>:(?3)){0,6})?::(?4)?))|(?>(?>IPv6:(?>(?3)(?>:(?3)){5}:|(?!(?:.*[a-f0-9]:){6,})(?5)?::(?>((?3)(?>:(?3)){0,4}):)?))?(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(?>\.(?6)){3}))\])$/iD'

基本:

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

"/^(?!.{255,})(?!.{65,}@)([!#-'*+\/-9=?^-~-]+)(?>\.(?1))*@(?!.*[^.]{64,})(?>[a-z0-9](?>[a-z0-9-]*[a-z0-9])?\.){1,126}[a-z]{2,6}$/iD"

评论

1赞 tchrist 11/8/2010
那是什么魔鬼的语言??我看到一个标志,你用单引号引用了它,但也用斜杠来分隔模式?它不是Perl,也不可能是PCRE。因此是PHP吗?我相信这是仅有的三个允许递归的,例如./D(?1)
1赞 Michael 2/20/2011
它在 PHP 中,它使用 PCRE。斜杠仅用于分隔特殊字符,如括号、方括号,当然还有斜杠和单引号。如果您不知道,则 /D 标志是为了防止在字符串末尾添加换行符,否则将允许这样做。
850赞 SLaks 12/15/2009 #21

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

相反,在 C# 中使用 MailAddress 类,如下所示:

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

该类使用 BNF 解析器完全按照 RFC822 验证地址。MailAddress

如果您计划使用 来验证电子邮件地址,请注意,此方法也接受电子邮件地址的显示名称部分,这可能不是您想要实现的。例如,它接受以下字符串作为有效的电子邮件地址:MailAddress

在某些情况下,只有字符串的最后一部分被解析为地址;在此之前的其余部分是显示名称。若要获取没有任何显示名称的纯电子邮件地址,可以根据原始字符串检查规范化地址。

bool isValid = false;

try
{
    MailAddress address = new MailAddress(emailAddress);
    isValid = (address.Address == emailAddress);
    // or
    // isValid = string.IsNullOrEmpty(address.DisplayName);
}
catch (FormatException)
{
    // address is invalid
}

此外,末尾带有点的地址 like 也被 MailAddress 接受。user@company.

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

(?:(?:\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*)

评论

50赞 Jeff Tucker 12/15/2009
您会发现 .NET 4.0 中的 MailAddress 类在验证电子邮件地址方面比以前的版本要好得多。我对它做了一些重大改进。
10赞 Raze 12/15/2009
我认为这有点......不起作用...用于更简单的 ID。a@b不验证。[email protected] 仅在 ar@b 之前匹配,.com不匹配。但是,像“我就是我”@[10.10.10.10]这样的东西确实有效!:)
12赞 Matthew Lock 9/28/2012
请注意,这些符合 RFC 的正则表达式验证器会允许通过许多您可能不想接受的电子邮件地址,例如“a<body/onload=alert('lol.com?+document.cookies) @a.a>“,这是 perl 的 Email::Valid 中的有效电子邮件地址(它使用了巨大的正则表达式),可用于 XSS rt.cpan.org/Public/Bug/Display.html?id=75650
14赞 SLaks 9/29/2012
@MatthewLock:这并不比.您不能依赖电子邮件验证来阻止 XSS。[email protected]
15赞 SLaks 3/2/2016
@MatthewLock:没有。您需要转义 SQL 查询(或者,更好的是,使用参数)。消毒不是一种适当的防御措施。
4赞 2 revs, 2 users 82%Peter Mortensen #22

没有人提到本地化问题(i18n)。如果您有来自世界各地的客户怎么办?

然后,您需要对每个国家/地区的正则表达式进行子分类,我已经看到开发人员最终构建了一个大型字典或配置。检测用户的浏览器语言设置可能是一个很好的起点。

207赞 3 revs, 3 users 69%Abigail #23

在 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

评论

22赞 tdc 12/16/2011
很想在 Python 中看到这一点
4赞 dolmen 12/17/2011
我认为只有一部分与问题真正相关。接受更多,并通过系统的其他部分转发它,而这些部分还没有准备好接受完整的RFC5822地址,就像射击是你自己的脚一样。addrspec
4赞 Rinke 1/4/2013
很棒(+1),但从技术上讲,它当然不是正则表达式......(这是不可能的,因为语法不规则)。
12赞 rjh 3/10/2014
正则表达式在一段时间前不再正常。不过,这是一个有效的 Perl“正则表达式”!
4赞 Mike 7/31/2014
我在IDEone上为这个正则表达式设置了一个测试: ideone.com/2XFecH 但是,它并不“完美”。有人愿意插话吗?我错过了什么吗?
29赞 2 revsBalusC #24

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

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

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

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

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

评论

5赞 PeteT 2/2/2010
我同意发送身份验证消息通常是这种东西的最佳方式,语法正确和有效是不一样的。当我被要求输入两次我的电子邮件地址进行“确认”时,我会感到沮丧,就好像我无法查看我输入的内容一样。无论如何,我只将第一个复制到第二个,它似乎越来越多地被使用。
2赞 CB4 11/9/2017
同意!但我认为这个正则表达式是无效的,因为它允许在 EG 之后。 使用上述正则表达式将电子邮件视为有效的电子邮件,因为它应该返回无效。spaces@.[email protected] com net
64赞 6 revs, 3 users 64%Evan Carroll #25

这个正则表达式来自 Perl 的 Email::Valid 库。我相信它是最准确的,并且它与 RFC 822 的所有内容相匹配。而且,它基于 O'Reilly 书中的正则表达式:

使用 Jeffrey Friedl 在掌握正则表达式 (http://www.ora.com/catalog/regexp/) 中的示例构建的正则表达式

$RFC822PAT = <<'EOF';
[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\
xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xf
f\n\015()]*)*\)[\040\t]*)*(?:(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\x
ff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|"[^\\\x80-\xff\n\015
"]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015"]*)*")[\040\t]*(?:\([^\\\x80-\
xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80
-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*
)*(?:\.[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\
\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\
x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x8
0-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|"[^\\\x80-\xff\n
\015"]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015"]*)*")[\040\t]*(?:\([^\\\x
80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^
\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040
\t]*)*)*@[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([
^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\
\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\
x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-
\xff\n\015\[\]]|\\[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()
]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\
x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:\.[\04
0\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\
n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\
015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?!
[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\
]]|\\[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\
x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\01
5()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*)*|(?:[^(\040)<>@,;:".
\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]
)|"[^\\\x80-\xff\n\015"]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015"]*)*")[^
()<>@,;:".\\\[\]\x80-\xff\000-\010\012-\037]*(?:(?:\([^\\\x80-\xff\n\0
15()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][
^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)|"[^\\\x80-\xff\
n\015"]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015"]*)*")[^()<>@,;:".\\\[\]\
x80-\xff\000-\010\012-\037]*)*<[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?
:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-
\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:@[\040\t]*
(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015
()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()
]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\0
40)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\
[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\
xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*
)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:\.[\040\t]*(?:\([^\\\x80
-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x
80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t
]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\
\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])
*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x
80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80
-\xff\n\015()]*)*\)[\040\t]*)*)*(?:,[\040\t]*(?:\([^\\\x80-\xff\n\015(
)]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\
\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*@[\040\t
]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\0
15()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015
()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(
\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|
\\[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80
-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()
]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:\.[\040\t]*(?:\([^\\\x
80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^
\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040
\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".
\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff
])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\
\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x
80-\xff\n\015()]*)*\)[\040\t]*)*)*)*:[\040\t]*(?:\([^\\\x80-\xff\n\015
()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\
\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*)?(?:[^
(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-
\037\x80-\xff])|"[^\\\x80-\xff\n\015"]*(?:\\[^\x80-\xff][^\\\x80-\xff\
n\015"]*)*")[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|
\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))
[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:\.[\040\t]*(?:\([^\\\x80-\xff
\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\x
ff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(
?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\
000-\037\x80-\xff])|"[^\\\x80-\xff\n\015"]*(?:\\[^\x80-\xff][^\\\x80-\
xff\n\015"]*)*")[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\x
ff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)
*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*)*@[\040\t]*(?:\([^\\\x80-\x
ff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-
\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)
*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\
]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\]
)[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-
\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\x
ff\n\015()]*)*\)[\040\t]*)*(?:\.[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(
?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80
-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<
>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x8
0-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\])[\040\t]*(?:
\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]
*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)
*\)[\040\t]*)*)*>)
EOF

评论

16赞 Chris McGrath 1/31/2013
O_O您还需要成为正则表达式大师才能了解它在做什么
0赞 awwright 9/13/2020
此正则表达式匹配 MIME 语法的某些部分,例如折叠空格和注释;它还允许使用不允许使用的控制字符。
0赞 Peter Mortensen 2/14/2022
O'Reilly 链接已损坏 - “嗯,我们找不到那个页面......很抱歉给您带来不便”
28赞 Eric Schoonover #26

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

以下是当前排名靠前的表达式,仅供参考:

/^([\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*[\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,6})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)$/i

评论

1赞 tchrist 11/8/2010
spoon16:这个链接不太正确。它关于验证电子邮件地址不可能有完美模式的说法显然是错误的。你可以,但你必须确保你严格遵守RFC。您还必须选择正确的 RFC。
1赞 Eric Chen 4/18/2012
现在的“最佳”不适用于 java 正则表达式 - 即使在正确转义和转换字符串之后。
12赞 6 revs, 4 users 66%AZ_ #27

根据官方标准 RFC 2822,有效的电子邮件正则表达式为:

(?:[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])+)\])

如果你想在 Java 中使用它,这真的非常简单:

import java.util.regex.*;

class regexSample
{
    public static void main(String args[])
    {
        //Input the string for validation
        String email = "[email protected]";

        //Set the email pattern string
        Pattern p = Pattern.compile(" (?:[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])+)\\]");

        //Match the given string with the pattern
        Matcher m = p.matcher(email);

        //Check whether match is found
        boolean matchFound = m.matches();

        if (matchFound)
            System.out.println("Valid Email Id.");
        else
            System.out.println("Invalid Email Id.");
    }
}

评论

2赞 Kebab Krabby 7/17/2019
您的正则表达式不包含第一个大写字母,例如 [email protected],这对某些用户来说可能会很烦人。请改用这个:(?:[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[A-Za-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])+)\])
0赞 AZ_ 7/31/2019
@KebabKrabby谢谢,请编辑答案,我会接受更改。
0赞 Kebab Krabby 8/1/2019
如果我将该更改添加到您的答案中,它将不再是 RFC 2822,所以我不知道这是否正确。
2赞 Thomas Weller 9/25/2020
@KebabKrabby:我想我们需要在匹配选项的某个地方应用不区分大小写的模式,而不是更改正则表达式本身。
11赞 2 revs, 2 users 57%Mac #28

这是我使用的PHP代码。我选择这个解决方案是本着“误报比漏报好”的精神,正如另一位评论者在这里所宣称的那样关于保持响应时间和服务器负载下降......实际上没有必要用正则表达式浪费服务器资源,因为这样可以消除大多数简单的用户错误。如果需要,您可以随时通过发送测试电子邮件来跟进。

function validateEmail($email) {
  return (bool) stripos($email,'@');
}

评论

2赞 johnjohn 4/3/2012
a) “浪费服务器资源”是微不足道的,但如果你愿意,你可以用 JS 在客户端做 b) 你需要什么来发送注册邮件,用户输入me@forgotthedotcom?您的“解决方案”失败了,您失去了一个用户。
2赞 auco 12/6/2013
a) 依赖禁用 JavaScript 时会失败的 JS 验证听起来也不是最好的主意(顺便说一句)
0赞 Peter Mortensen 2/14/2022
误报是什么意思?拒绝您不应该拒绝的电子邮件地址?或者接受您不应该接受的电子邮件地址?
7赞 2 revs, 2 users 67%Murthy Jeedigunta #29
public bool ValidateEmail(string sEmail)
{
    if (sEmail == null)
    {
        return false;
    }

    int nFirstAT = sEmail.IndexOf('@');
    int nLastAT = sEmail.LastIndexOf('@');

    if ((nFirstAT > 0) && (nLastAT == nFirstAT) && (nFirstAT < (sEmail.Length - 1)))
    {
        return (Regex.IsMatch(sEmail, @"^[a-z|0-9|A-Z]*([_][a-z|0-9|A-Z]+)*([.][a-z|0-9|A-Z]+)*([.][a-z|0-9|A-Z]+)*(([_][a-z|0-9|A-Z]+)*)?@[a-z][a-z|0-9|A-Z]*\.([a-z][a-z|0-9|A-Z]*(\.[a-z][a-z|0-9|A-Z]*)?)$"));
    }
    else
    {
        return false;
    }
}

评论

0赞 awwright 9/11/2020
这有时会失败;如果电子邮件地址中的用户位于带引号的字符串中,则该用户可能包含“@”字符。
5赞 4 revs, 2 users 58%grosser #30

此规则与我们的 Postfix 服务器无法发送到的内容相匹配。

允许使用字母、数字、-、_、+、.、&、/ 和 !

,[email protected]

,[email protected]

/^([a-z0-9\+\._\/&!][-a-z0-9\+\._\/&!]*)@(([a-z0-9][-a-z0-9]*\.)([-a-z0-9]+\.)*[a-z]{2,})$/i
3赞 Dr. Hans-Peter Störr #31

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

49赞 4 revs, 3 users 55%SimonSimCity #32

当你用PHP写作时,我建议你对电子邮件使用PHP内置的验证。

filter_var($value, FILTER_VALIDATE_EMAIL)

如果您运行的 PHP 版本低于 5.3.6,请注意此问题: 错误 #53091:当我尝试过滤 > 2264 个字符的文本时崩溃

如果您想了解更多有关此内置验证如何工作的信息,请参阅此处:PHP 的filter_var FILTER_VALIDATE_EMAIL实际工作吗?

评论

0赞 Taylor 1/26/2012
得到投票,正是我要说的。不处理 IDN,但事先转换为微不足道的代码可以解决这个问题。PHP>=5.3 为此有 idn_to_ascii()。验证电子邮件的最佳和最简单的方法之一。
341赞 10 revs, 8 users 40%Rory O'Kane #33

根据 W3C HTML5 规范

^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$

上下文:

有效的电子邮件地址是与 ABNF 生产 [...] 匹配的字符串。

注意:此要求是故意违反 RFC 5322 的,RFC 5322 定义了电子邮件地址的语法,该语法同时过于严格(在“@”字符之前)、过于模糊(在“@”字符之后)和过于宽松(允许注释、空格字符和以大多数用户不熟悉的方式引用字符串)在这里没有实际用途。

以下兼容 JavaScript 和 Perl 的正则表达式是上述定义的实现。

/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/

评论

13赞 valentinas 1/16/2013
这很有趣。这是对RFC的违反,但却是故意的,它使sesne。真实世界的例子:gmail忽略了@之前部分的点,所以如果你的电子邮件是[email protected],你可以将电子邮件发送到[email protected]或[email protected],根据RFC,这两个地址都是无效的,但在现实世界中是有效的。
1赞 mmmmmm 1/21/2013
我认为最后一部分应该是“+”而不是“*”:^[a-zA-Z0-9.!#$%&'*+/=?^_'{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)+$
11赞 rabudde 2/1/2013
@mmmmmm是有效的。当然,在现实世界的应用程序(即社区)中,我希望您建议将 * 替换为 +john.doe@localhost
3赞 Rinke 11/17/2014
@valentinas 实际上,RFC 并不排除这些本地部分,但必须引用它们。 根据 RFC 是完全有效的,并且在语义上等同于 。"test...."@gmail.com[email protected]
0赞 ndvo 2/11/2016
如果我尝试发送到带有 .@ 或 . 的地址,则在尝试通过公司的中继使用 python 发送电子邮件时出现错误。@.实际上,_@ 也是如此。我宁愿在发送之前删除它们,也不愿相信收件人会这样做。
8赞 4 revs, 3 users 50%Prasad #34

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

static public function checkEmail($email, $ignore_empty = false) {
    if($ignore_empty && (is_null($email) || $email == ''))
        return true;
    return filter_var($email, FILTER_VALIDATE_EMAIL);
}

评论

1赞 Peter Mortensen 2/14/2022
具有空值的地址示例是什么?请通过编辑(更改)您的答案来回复,而不是在评论中(没有“编辑:”,“更新:”或类似内容 - 答案应该看起来像今天写的一样)。
8赞 9 revs, 3 users 54%TombMedia #35

我已经使用这个 OP 正则表达式的修饰版本有一段时间了,它并没有给我留下太多惊喜。我从未在电子邮件中遇到过撇号,所以它不能验证这一点。它确实验证了 和 ,但不是奇怪的滥用那些非字母数字字符。Jean+Franç[email protected]试@例子.测试.مثال.آزمایشی[email protected]

(?!^[.+&'_-]*@.*$)(^[_\w\d+&'-]+(\.[_\w\d+&'-]*)*@[\w\d-]+(\.[\w\d-]+)*\.(([\d]{1,3})|([\w]{2,}))$)

它确实支持 IP 地址 ,但我还没有对其进行足够的改进来处理虚假的 IP 地址范围,例如 .[email protected]999.999.999.1

它还支持三个字符以上的所有 TLD,这阻止了 [email protected] 我认为原版让它通过。 我被打败了,现在超过 3 个字符的 TLD 太多了。

我知道 OP 已经放弃了他的正则表达式,但这种味道仍然存在。

评论

1赞 Peter Mortensen 2/14/2022
对于所有人:问题中的正则表达式在 2015 年(大约 7 年后)的修订版 10 中删除。
1赞 Peter Mortensen 2/14/2022
删除不应该是必要的。这就是修订历史的用途。如果某些内容不再有效,则应将其删除。答案应该是今天写的。
141赞 43 revs, 3 users 94%Rinke #36

快速回答

使用以下正则表达式进行输入验证:

([-!#-'*+/-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])?)+

与此正则表达式匹配的地址:

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

第二个约束是对 RFC 5321/5322 的限制。

详尽的答案

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

但是,应该注意的是,如果要确定该地址是否实际上是指现有邮箱,则无法替代向该地址发送邮件。如果您只想检查地址在语法上是否正确,则可以使用正则表达式,但请注意,这是一个语法正确的电子邮件地址,当然不是指现有邮箱。""@[]

电子邮件地址的语法已在各种 RFC 中定义,最著名的是 RFC 822 和 RFC 5322RFC 822 应被视为“原始”标准,RFC 5322 应被视为最新标准。RFC 822 中定义的语法是最宽松的,后续标准对语法的限制越来越深,其中较新的系统或服务应该识别过时的语法,但永远不会产生它。

在这个答案中,我将“电子邮件地址”视为 RFC 中定义的含义(即 ,但不是 、 也不是 )。addr-spec[email protected]"John Doe"<[email protected]>some-group:[email protected],[email protected];

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

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

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

我在这个答案中使用了 POSIX“扩展”正则表达式,假设有一个 ASCII 兼容的字符集。

RFC 822

我得出了以下正则表达式。我邀请大家尝试打破它。如果您发现任何误报或漏报,请将它们发布在评论中,我会尽快修复该表达式。

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

我相信它完全符合 RFC 822,包括勘误表。它仅识别规范形式的电子邮件地址。对于识别(折叠)空格的正则表达式,请参阅下面的推导。

推导显示了我是如何得出这个表达式的。我完全按照 RFC 中出现的方式列出了所有相关的语法规则,然后是相应的正则表达式。如果已发布勘误表,我会为更正后的语法规则(标记为“勘误表”)提供单独的表达式,并将更新后的版本用作后续正则表达式中的子表达式。

如第3.1.4段所述。RFC 822 可选的线性空格可以插入词法标记之间。在适用的情况下,我扩展了表达式以适应此规则,并用“opt-lwsp”标记结果。

CHAR        =  <any ASCII character>
            =~ .

CTL         =  <any ASCII control character and DEL>
            =~ [\x00-\x1F\x7F]

CR          =  <ASCII CR, carriage return>
            =~ \r

LF          =  <ASCII LF, linefeed>
            =~ \n

SPACE       =  <ASCII SP, space>
            =~  

HTAB        =  <ASCII HT, horizontal-tab>
            =~ \t

<">         =  <ASCII quote mark>
            =~ "

CRLF        =  CR LF
            =~ \r\n

LWSP-char   =  SPACE / HTAB
            =~ [ \t]

linear-white-space =  1*([CRLF] LWSP-char)
                   =~ ((\r\n)?[ \t])+

specials    =  "(" / ")" / "<" / ">" / "@" /  "," / ";" / ":" / "\" / <"> /  "." / "[" / "]"
            =~ [][()<>@,;:\\".]

quoted-pair =  "\" CHAR
            =~ \\.

qtext       =  <any CHAR excepting <">, "\" & CR, and including linear-white-space>
            =~ [^"\\\r]|((\r\n)?[ \t])+

dtext       =  <any CHAR excluding "[", "]", "\" & CR, & including linear-white-space>
            =~ [^][\\\r]|((\r\n)?[ \t])+

quoted-string  =  <"> *(qtext|quoted-pair) <">
               =~ "([^"\\\r]|((\r\n)?[ \t])|\\.)*"
(erratum)      =~ "(\n|(\\\r)*([^"\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*"

domain-literal =  "[" *(dtext|quoted-pair) "]"
               =~ \[([^][\\\r]|((\r\n)?[ \t])|\\.)*]
(erratum)      =~ \[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*]

atom        =  1*<any CHAR except specials, SPACE and CTLs>
            =~ [^][()<>@,;:\\". \x00-\x1F\x7F]+

word        =  atom / quoted-string
            =~ [^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*"

domain-ref  =  atom

sub-domain  =  domain-ref / domain-literal
            =~ [^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*]

local-part  =  word *("." word)
            =~ ([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*")(\.([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*"))*
(opt-lwsp)  =~ ([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*")(((\r\n)?[ \t])*\.((\r\n)?[ \t])*([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*"))*

domain      =  sub-domain *("." sub-domain)
            =~ ([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*])(\.([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*]))*
(opt-lwsp)  =~ ([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*])(((\r\n)?[ \t])*\.((\r\n)?[ \t])*([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*]))*

addr-spec   =  local-part "@" domain
            =~ ([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*")(\.([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*"))*@([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*])(\.([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*]))*
(opt-lwsp)  =~ ([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*")((\r\n)?[ \t])*(\.((\r\n)?[ \t])*([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*")((\r\n)?[ \t])*)*@((\r\n)?[ \t])*([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*])(((\r\n)?[ \t])*\.((\r\n)?[ \t])*([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*]))*
(canonical) =~ ([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]))*(\\\r)*")(\.([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]))*(\\\r)*"))*@([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]))*(\\\r)*])(\.([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]))*(\\\r)*]))*

RFC 5322

我得出了以下正则表达式。我邀请大家尝试打破它。如果您发现任何误报或漏报,请将它们发布在评论中,我会尽快修复该表达式。

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

我相信它完全符合 RFC 5322,包括勘误表。它仅识别规范形式的电子邮件地址。对于识别(折叠)空格的正则表达式,请参阅下面的推导。

推导显示了我是如何得出这个表达式的。我完全按照 RFC 中出现的方式列出了所有相关的语法规则,然后是相应的正则表达式。对于包含语义上不相关的(折叠)空格的规则,我给出了一个标记为“(规范化)”的单独正则表达式,它不接受此空格。

我忽略了 RFC 中的所有“obs-”规则。这意味着正则表达式仅匹配严格符合 RFC 5322 的电子邮件地址。如果您必须匹配“旧”地址(就像包括“obs-”规则在内的较宽松语法一样),则可以使用上一段中的 RFC 822 正则表达式之一。

VCHAR           =   %x21-7E
                =~  [!-~]

ALPHA           =   %x41-5A / %x61-7A
                =~  [A-Za-z]

DIGIT           =   %x30-39
                =~  [0-9]

HTAB            =   %x09
                =~  \t

CR              =   %x0D
                =~  \r

LF              =   %x0A
                =~  \n

SP              =   %x20
                =~  

DQUOTE          =   %x22
                =~  "

CRLF            =   CR LF
                =~  \r\n

WSP             =   SP / HTAB
                =~  [\t ]

quoted-pair     =   "\" (VCHAR / WSP)
                =~  \\[\t -~]

FWS             =   ([*WSP CRLF] 1*WSP)
                =~  ([\t ]*\r\n)?[\t ]+

ctext           =   %d33-39 / %d42-91 / %d93-126
                =~  []!-'*-[^-~]

("comment" is left out in the regex)
ccontent        =   ctext / quoted-pair / comment
                =~  []!-'*-[^-~]|(\\[\t -~])

(not regular)
comment         =   "(" *([FWS] ccontent) [FWS] ")"

(is equivalent to FWS when leaving out comments)
CFWS            =   (1*([FWS] comment) [FWS]) / FWS
                =~  ([\t ]*\r\n)?[\t ]+

atext           =   ALPHA / DIGIT / "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "/" / "=" / "?" / "^" / "_" / "`" / "{" / "|" / "}" / "~"
                =~  [-!#-'*+/-9=?A-Z^-~]

dot-atom-text   =   1*atext *("." 1*atext)
                =~  [-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*

dot-atom        =   [CFWS] dot-atom-text [CFWS]
                =~  (([\t ]*\r\n)?[\t ]+)?[-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*(([\t ]*\r\n)?[\t ]+)?
(normalized)    =~  [-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*

qtext           =   %d33 / %d35-91 / %d93-126
                =~  []!#-[^-~]

qcontent        =   qtext / quoted-pair
                =~  []!#-[^-~]|(\\[\t -~])

(erratum)
quoted-string   =   [CFWS] DQUOTE ((1*([FWS] qcontent) [FWS]) / FWS) DQUOTE [CFWS]
                =~  (([\t ]*\r\n)?[\t ]+)?"(((([\t ]*\r\n)?[\t ]+)?([]!#-[^-~]|(\\[\t -~])))+(([\t ]*\r\n)?[\t ]+)?|(([\t ]*\r\n)?[\t ]+)?)"(([\t ]*\r\n)?[\t ]+)?
(normalized)    =~  "([]!#-[^-~ \t]|(\\[\t -~]))+"

dtext           =   %d33-90 / %d94-126
                =~  [!-Z^-~]

domain-literal  =   [CFWS] "[" *([FWS] dtext) [FWS] "]" [CFWS]
                =~  (([\t ]*\r\n)?[\t ]+)?\[((([\t ]*\r\n)?[\t ]+)?[!-Z^-~])*(([\t ]*\r\n)?[\t ]+)?](([\t ]*\r\n)?[\t ]+)?
(normalized)    =~  \[[\t -Z^-~]*]

local-part      =   dot-atom / quoted-string
                =~  (([\t ]*\r\n)?[\t ]+)?[-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*(([\t ]*\r\n)?[\t ]+)?|(([\t ]*\r\n)?[\t ]+)?"(((([\t ]*\r\n)?[\t ]+)?([]!#-[^-~]|(\\[\t -~])))+(([\t ]*\r\n)?[\t ]+)?|(([\t ]*\r\n)?[\t ]+)?)"(([\t ]*\r\n)?[\t ]+)?
(normalized)    =~  [-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|"([]!#-[^-~ \t]|(\\[\t -~]))+"

domain          =   dot-atom / domain-literal
                =~  (([\t ]*\r\n)?[\t ]+)?[-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*(([\t ]*\r\n)?[\t ]+)?|(([\t ]*\r\n)?[\t ]+)?\[((([\t ]*\r\n)?[\t ]+)?[!-Z^-~])*(([\t ]*\r\n)?[\t ]+)?](([\t ]*\r\n)?[\t ]+)?
(normalized)    =~  [-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|\[[\t -Z^-~]*]

addr-spec       =   local-part "@" domain
                =~  ((([\t ]*\r\n)?[\t ]+)?[-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*(([\t ]*\r\n)?[\t ]+)?|(([\t ]*\r\n)?[\t ]+)?"(((([\t ]*\r\n)?[\t ]+)?([]!#-[^-~]|(\\[\t -~])))+(([\t ]*\r\n)?[\t ]+)?|(([\t ]*\r\n)?[\t ]+)?)"(([\t ]*\r\n)?[\t ]+)?)@((([\t ]*\r\n)?[\t ]+)?[-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*(([\t ]*\r\n)?[\t ]+)?|(([\t ]*\r\n)?[\t ]+)?\[((([\t ]*\r\n)?[\t ]+)?[!-Z^-~])*(([\t ]*\r\n)?[\t ]+)?](([\t ]*\r\n)?[\t ]+)?)
(normalized)    =~  ([-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|"([]!#-[^-~ \t]|(\\[\t -~]))+")@([-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|\[[\t -Z^-~]*])

请注意,一些来源(特别是 W3C)声称 RFC 5322 对本地部分(即 @ 符号之前的部分)过于严格。这是因为“..”、“a..b“和”a.“不是有效的点原子,但它们可以用作邮箱名称。然而,RFC确实允许像这样的本地部分,只是它们必须被引用。所以你应该写,而不是你应该写,这在语义上是等价的。[email protected]"a..b"@example.net

进一步的限制

SMTP(如 RFC 5321 中定义)进一步限制了有效电子邮件地址(或实际:邮箱名称)的集。强加这种更严格的语法似乎是合理的,这样匹配的电子邮件地址实际上就可以用来发送电子邮件。

RFC 5321 基本上只保留了“本地”部分(即 @ 符号之前的部分),但对域部分(即 @ 符号之后的部分)更严格。它只允许主机名代替点原子,只允许用地址文字代替域文字。

RFC 5321 中提供的语法在主机名和 IP 地址方面都过于宽松。我冒昧地“纠正”了相关规则,使用这个草案RFC 1034 作为指导方针。下面是生成的正则表达式。

([-!#-'*+/-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^-~]+)])

请注意,根据用例,您可能不希望在正则表达式中使用“General-address-literal”。另请注意,我在最终的正则表达式中使用了否定前瞻,以防止“General-address-literal”部分匹配格式错误的 IPv6 地址。某些正则表达式处理器不支持负前瞻。如果要删除整个“General-address-literal”部分,请从正则表达式中删除子字符串。(?!IPv6:)|(?!IPv6:)[0-9A-Za-z-]*[0-9A-Za-z]:[!-Z^-~]+

推导如下:

Let-dig         =   ALPHA / DIGIT
                =~  [0-9A-Za-z]

Ldh-str         =   *( ALPHA / DIGIT / "-" ) Let-dig
                =~  [0-9A-Za-z-]*[0-9A-Za-z]

(regex is updated to make sure sub-domains are max. 63 characters long - RFC 1034 section 3.5)
sub-domain      =   Let-dig [Ldh-str]
                =~  [0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?

Domain          =   sub-domain *("." sub-domain)
                =~  [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])?)*

Snum            =   1*3DIGIT
                =~  [0-9]{1,3}

(suggested replacement for "Snum")
ip4-octet       =   DIGIT / %x31-39 DIGIT / "1" 2DIGIT / "2" %x30-34 DIGIT / "25" %x30-35
                =~  25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9]

IPv4-address-literal    =   Snum 3("."  Snum)
                        =~  [0-9]{1,3}(\.[0-9]{1,3}){3}

(suggested replacement for "IPv4-address-literal")
ip4-address     =   ip4-octet 3("." ip4-octet)
                =~  (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}

(suggested replacement for "IPv6-hex")
ip6-h16         =   "0" / ( (%x49-57 / %x65-70 /%x97-102) 0*3(%x48-57 / %x65-70 /%x97-102) )
                =~  0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}

(not from RFC)
ls32            =   ip6-h16 ":" ip6-h16 / ip4-address
                =~  (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}

(suggested replacement of "IPv6-addr")
ip6-address     =                                      6(ip6-h16 ":") ls32
                    /                             "::" 5(ip6-h16 ":") ls32
                    / [                 ip6-h16 ] "::" 4(ip6-h16 ":") ls32
                    / [ *1(ip6-h16 ":") ip6-h16 ] "::" 3(ip6-h16 ":") ls32
                    / [ *2(ip6-h16 ":") ip6-h16 ] "::" 2(ip6-h16 ":") ls32
                    / [ *3(ip6-h16 ":") ip6-h16 ] "::"   ip6-h16 ":"  ls32
                    / [ *4(ip6-h16 ":") ip6-h16 ] "::"                ls32
                    / [ *5(ip6-h16 ":") ip6-h16 ] "::"   ip6-h16
                    / [ *6(ip6-h16 ":") ip6-h16 ] "::"
                =~  (((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-address-literal    =   "IPv6:" ip6-address
                        =~  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}))?::)

Standardized-tag        =   Ldh-str
                        =~  [0-9A-Za-z-]*[0-9A-Za-z]

dcontent        =   %d33-90 / %d94-126
                =~  [!-Z^-~]

General-address-literal =   Standardized-tag ":" 1*dcontent
                        =~  [0-9A-Za-z-]*[0-9A-Za-z]:[!-Z^-~]+

address-literal =   "[" ( IPv4-address-literal / IPv6-address-literal / General-address-literal ) "]"
                =~  \[((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^-~]+)]

Mailbox         =   Local-part "@" ( Domain / address-literal )
                =~  ([-!#-'*+/-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^-~]+)])

用户输入验证

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

([-!#-'*+/-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|等。。。)

如果您决定走显式顶级域验证的道路,请确保使您的正则表达式保持最新状态。

其他注意事项

当仅接受域部分(@ 符号之后)中的主机名时,上面的正则表达式只接受最多 63 个字符的标签,因为它们应该接受。但是,它们不强制要求整个主机名的长度最多为 253 个字符(包括点)。尽管严格来说,此约束仍然是常规的,但要创建一个包含此规则的正则表达式是不可行的。

另一个考虑因素,尤其是在使用正则表达式进行输入验证时,是对用户的反馈。如果用户输入了错误的地址,最好提供比简单的“语法不正确的地址”更多的反馈。对于“vanilla”正则表达式,这是不可能的。

这两个注意事项可以通过解析地址来解决。在某些情况下,还可以通过使用额外的正则表达式来检查主机名,并将地址与两个表达式进行匹配来解决。

此答案中的任何正则表达式均未针对性能进行优化。如果性能是一个问题,你应该看看你选择的正则表达式是否可以(以及如何)优化。

评论

3赞 6/27/2015
RFC 6532 更新 5322 以允许并包含完整、干净的 UTF-8。更多细节在这里
0赞 Xavi Montero 5/22/2017
根据维基百科,似乎局部部分在点线时,每个部分有 64 个字符的限制,并且 RFC 5322 也指的是要根据域的限制来解释的虚线局部部分。例如,不应验证。我建议将第一组(可选点前的名称)和第二组(以下点后的名称)中的“+”符号更改为arbitrary-long-email-address-should-be-invalid-arbitrary-long-email-address-should-be-invalid.and-the-second-group-also-should-not-be-so-[email protected]{1,64}
0赞 Xavi Montero 5/22/2017
由于注释的大小有限,这是我计划使用的结果正则表达式,这是本答案开头的正则表达式,加上限制本地部分的大小,以及根据 PHP 和 regex101.com 的要求在“/”符号之前添加一个反斜杠: 在PHP中,我使用:$emailRegex = '/^([-!#-\'*+\/-9=?A-Z^-~]{1,64}(\.[-!#-\'*+\/-9=?A-Z^-~]{1,64})*|"([]!#-[^-~ \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])?)+$/';
0赞 Xavi Montero 5/22/2017
注意:出于某种原因,StackOverflow 在从呈现的 Markdown 复制时会添加隐藏字符。将其复制到 regex101.com 中,您会在那里看到黑点。您必须删除它们并更正字符串...也许如果集成到答案中,它们就可以正确复制。对此造成的不便,我们深表歉意。我不想添加新的答案,因为这个答案是正确的。此外,我不想直接编辑,除非社区认为这应该集成到其中。
0赞 Rinke 5/22/2017
@XaviMontero感谢 Thaks 为 Xavi 做出了贡献!您是否参考了 RFC,其中规定了本地零件标签的 64 个字符限制?如果是这样,我很乐意调整答案。
2赞 3 revs, 3 users 57%Mohit Gupta #37

据我了解,它很可能会被...

/^([a-z0-9_-]+)(@[a-z0-9-]+)(\.[a-z]+|\.[a-z]+\.[a-z]+)?$/is

评论

0赞 Mohit Gupta 12/31/2012
改进/建议总是起到催化剂的作用,所以请催化和催化我。
0赞 Cees Timmerman 1/18/2013
Gmail 用户经常使用 .和 + 在他们的电子邮件昵称中,此页面上的一些评论提到了 ' 和 !.
1赞 awwright 9/15/2020
这限制性太强,不允许域名中的数字、用户部分中的字符、、 和 都是有效的电子邮件地址,但不会进行验证。o'[email protected][email protected][email protected]
3赞 3 revs, 2 users 73%FLY #38

这是我构建的那个。它不是一个防弹版本,但它是“简单”的,几乎可以检查所有内容。

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

我认为有一个解释,所以如果你愿意,你可以修改它:

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

(m) 匹配 a-z、A-Z、_、+、- 零次或多次,但需要以 .(点)(?:\.[\w+-]+)*

@ = @

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

(l) 匹配 a-z、A-Z、_、+、- 零次或多次,但需要以 .(点)(?:\.[\w+-]+)*

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

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

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

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

评论

0赞 Mr. Developerdude 6/17/2013
谢谢!这对我有用。这是与Qt5一起使用的经过测试的C / C++转义版本:QRegExp rx(“[\\w+-]+(?:\\.[\\w+-]+)*@[\\w+-]+(?:\\.[\\w+-]+)*(?:\\.[a-zA-Z]{2,})“);
7赞 5 revs, 2 users 81%Cees Timmerman #39

我仍在使用:

^[A-Za-z0-9._+\-\']+@[A-Za-z0-9.\-]+\.[A-Za-z]{2,}$

但随着 IPv6 和 Unicode 的出现,也许这是最好的:

console.log(/^[\p{L}!#-'*+\-/\d=?^-~]+(.[\p{L}!#-'*+\-/\d=?^-~])*@[^@\s]{2,}$/u.test("תה.בועות@😀.fm"))

Gmail允许连续点,但Microsoft Exchange Server 2007拒绝它们,它遵循最新的标准afaik。

评论

0赞 David Conrad 2/13/2013
不允许 ."John Smith"@example.com
0赞 Cees Timmerman 2/20/2013
没错,但什么时候真正需要呢?
2赞 David Conrad 2/21/2013
任何电子邮件地址中是否有空格吗?
0赞 Cees Timmerman 2/21/2013
我从未见过其中一种被实际使用,我认为官方规范说它只是为了向后兼容。
1赞 Cees Timmerman 11/21/2022
@DavidConrad 你的意思是根据这个评论"John\ Smith"@example.com
1赞 2 revs, 2 users 71%PrivateUser #40

世界上最受欢迎的博客平台WordPress使用此功能来验证电子邮件地址...

但他们正在通过多个步骤来做到这一点。

使用此函数中提到的正则表达式时,您不必再担心了......

这是功能...

/**
 * Verifies that an email is valid.
 *
 * Does not grok i18n domains. Not RFC compliant.
 *
 * @since 0.71
 *
 * @param string $email Email address to verify.
 * @param boolean $deprecated Deprecated.
 * @return string|bool Either false or the valid email address.
 */
function is_email( $email, $deprecated = false ) {
    if ( ! empty( $deprecated ) )
        _deprecated_argument( __FUNCTION__, '3.0' );

    // Test for the minimum length the email can be
    if ( strlen( $email ) < 3 ) {
        return apply_filters( 'is_email', false, $email, 'email_too_short' );
    }

    // Test for an @ character after the first position
    if ( strpos( $email, '@', 1 ) === false ) {
        return apply_filters( 'is_email', false, $email, 'email_no_at' );
    }

    // Split out the local and domain parts
    list( $local, $domain ) = explode( '@', $email, 2 );

    // LOCAL PART
    // Test for invalid characters
    if ( !preg_match( '/^[a-zA-Z0-9!#$%&\'*+\/=?^_`{|}~\.-]+$/', $local ) ) {
        return apply_filters( 'is_email', false, $email, 'local_invalid_chars' );
    }

    // DOMAIN PART
    // Test for sequences of periods
    if ( preg_match( '/\.{2,}/', $domain ) ) {
        return apply_filters( 'is_email', false, $email, 'domain_period_sequence' );
    }

    // Test for leading and trailing periods and whitespace
    if ( trim( $domain, " \t\n\r\0\x0B." ) !== $domain ) {
        return apply_filters( 'is_email', false, $email, 'domain_period_limits' );
    }

    // Split the domain into subs
    $subs = explode( '.', $domain );

    // Assume the domain will have at least two subs
    if ( 2 > count( $subs ) ) {
        return apply_filters( 'is_email', false, $email, 'domain_no_periods' );
    }

    // Loop through each sub
    foreach ( $subs as $sub ) {
        // Test for leading and trailing hyphens and whitespace
        if ( trim( $sub, " \t\n\r\0\x0B-" ) !== $sub ) {
            return apply_filters( 'is_email', false, $email, 'sub_hyphen_limits' );
        }

        // Test for invalid characters
        if ( !preg_match('/^[a-z0-9-]+$/i', $sub ) ) {
            return apply_filters( 'is_email', false, $email, 'sub_invalid_chars' );
        }
    }

    // Congratulations your email made it!
    return apply_filters( 'is_email', $email, $email, null );
}

评论

0赞 awwright 9/13/2020
这限制性太强,它不允许使用带引号的用户组件,并且不支持国际化的电子邮件地址。此外,该函数未定义。_deprecated_argument
2赞 6 revs, 2 users 53%mrswadge #41

我找到了一个符合 RFC 2822正则表达式RFC 5322 的上述标准。这个正则表达式似乎表现得相当不错,可以覆盖大多数情况,但是随着 RFC 5322 成为标准,可能有一些漏洞需要填补。

^(?:[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])+)\])$

文档说你不应该使用上面的正则表达式,而是应该偏爱这种风格,它更易于管理。

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

我注意到这是区分大小写的,所以我实际上对这个着陆进行了更改。

^[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?$
0赞 2 revs, 2 users 67%Francisco Costa #42
^[_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)*@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.(([0-9]{1,3})|([a-zA-Z]{2,3})|(aero|coop|info|museum|name))$

这匹配了 99.99% 的电子邮件地址,包括一些较新的顶级域名后缀,例如 info、museum、name 等。它还允许将电子邮件直接绑定到 IP 地址。

3赞 4 revs, 2 users 52%Peter Mortensen #43

我也有类似的愿望:想要快速检查电子邮件地址中的语法,而不会过度使用电子邮件发送实用程序(答案显然是正确的)。我选择了这个(我是一个 POSIX 正则表达式的人,所以我通常不会使用 PCRE 中的 such such ,因为它们使事情对我来说不那么清晰):Mail::RFC822::Address\d

preg_match("_^[-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*@[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])?)*\$_", $adr)

这是 RFC 正确的,但它明确排除了过时的形式以及直接 IP 地址(IP 地址和传统 IP 地址),该实用程序的目标组中的某个人(主要是:在 IRC 上 #sendmail 打扰我们的人)通常不需要或不需要。

IDN(国际化域名)明确不在电子邮件的范围内:像“foo@cäcilienchor-bonn.de”这样的地址必须在网络上写成“[email protected]”(这包括 mailto:HTML 中的链接等等),只有 GUI 被允许向用户(和从)用户显示(并接受然后转换)此类名称。

评论

0赞 Peter Mortensen 2/14/2022
关于“传统 IP 地址”:您是指 IPv4 IP 地址吗?
0赞 mirabilos 2/14/2022
@PeterMortensen:(感谢您的语法突出显示和英文修复,但现在似乎有些东西坏了,它说社区维基以您为作者? 是的,传统 IP 地址是 IPv4 地址几年来一直被称为 IPv4 地址,IP 地址是 IPv6 地址。
6赞 2 revs, 2 users 75%auco #44

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

如果是这种情况,我建议查看新的 HTML5 表单元素:<input type="email">

HTML5的:

 <input type="email" required />

CSS 3:

 input:required {
      background-color: rgba(255, 0, 0, 0.2);
 }

 input:focus:invalid {
     box-shadow: 0 0 1em red;
     border-color: red;
 }

 input:focus:valid {
     box-shadow: 0 0 1em green;
     border-color: green;
 }

它位于 HTML5 Form Validation Without JS - JSFiddle - Code Playground.

这有几个优点:

  1. 自动验证,无需定制解决方案:简单易实施
  2. 没有 JavaScript,如果 JavaScript 被禁用也没有问题
  3. 没有服务器必须为此计算任何东西
  4. 用户有即时反馈
  5. 旧浏览器应自动回退到输入类型“text”
  6. 移动浏览器可以显示专用键盘 (@-Keyboard)
  7. 使用 CSS 3 可以非常轻松地进行表单验证反馈

明显的缺点可能是缺少对旧浏览器的验证,但这种情况会随着时间的推移而改变。我更喜欢这个,而不是这些疯狂的正则表达式杰作。

另请参阅:

评论

0赞 acrosman 1/22/2014
另一个缺点是,这仅是客户端。有利于提供流畅的用户体验,不利于验证数据。
0赞 Joeytje50 6/7/2014
默认电子邮件验证的问题在于它有很多误报。您需要使用我的完整模式来消除所有误报,同时防止误报潜入。该模式可以通过 pattern 属性添加。有关更多信息,请参阅我的帖子
4赞 5 revs, 3 users 73%Suhaib Janjua #45

我总是使用下面的正则表达式来验证电子邮件地址。它涵盖了基于英语字符的所有格式的电子邮件地址。

"\A(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)\Z";

下面给出了一个 C# 示例:

添加程序集引用:

using System.Text.RegularExpressions;

并使用以下方法传递电子邮件地址并获取布尔值作为回报

private bool IsValidEmail(string email) {
    bool isValid = false;
    const string pattern = @"\A(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)\Z";

    isValid = email != "" && Regex.IsMatch(email, pattern);

    // Same above approach in multiple lines
    //
    //if (!email) {
    //    isValid = false;
    //} else {
    //    // email param contains a value; Pass it to the isMatch method
    //    isValid = Regex.IsMatch(email, pattern);
    //}
    return isValid;
}

此方法验证参数中传递的电子邮件字符串。 对于 param 为 null、空字符串、undefined 或 param 值不是有效电子邮件地址的所有情况,它将返回 false。 仅当参数包含有效的电子邮件地址字符串时,它才会返回 true。

评论

2赞 Ivan Z 3/28/2014
此代码是否接受“Håkan.Söderström@malmö.se”或“试@例子.测试.مثال.آزمایشی”电子邮件?
3赞 Suhaib Janjua 3/28/2014
它适用于具有标准字符的标准电子邮件服务器。如果是非英语语言,则应制作自己的定制ReGex。
0赞 rob2d 11/30/2019
正则表达式和电子邮件规范包括 UTF-8,因此响应不合逻辑。
1赞 Peter Mortensen 2/15/2022
它在什么方面是最好的正则表达式?最全面?简单?假阴性最少?误报最少?最快的?在实际使用中,用户投诉的数量最少?这些属性的某种组合?别的?请通过编辑(更改)您的答案来回复,而不是在评论中(没有“编辑:”,“更新:”或类似内容 - 答案应该看起来像今天写的一样)。
7赞 4 revs, 3 users 59%Coder12345 #46

我使用多步骤验证。由于没有任何完美的方法来验证电子邮件地址,因此无法制作完美的电子邮件地址,但至少您可以通知用户他/她做错了什么 - 这是我的方法:

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

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

  3. 如果通过,则根据更严格的正则表达式进行验证 - 这可能会禁止有效的电子邮件。如果未通过,系统将警告用户可能出现的错误,但允许用户继续。与步骤(1)不同,在步骤(1)中,由于这是一个明显的错误,因此不允许用户继续。

因此,换句话说,第一个自由验证只是剥离明显的错误,并将其视为“错误”。用户键入空白地址、不带 @ 符号的地址等。这应被视为错误。第二个更严格,但它被视为“警告”,允许用户继续输入,但警告至少要检查他/她输入的条目是否有效。这里的关键在于错误/警告方法 - 错误是在 99.99% 的情况下不可能是有效的电子邮件。

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

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

评论

0赞 Allan Deamon 4/19/2022
从技术上讲,电子邮件可以包含 1 个以上的 @。这是我最近发现的一个令人惊讶的奇怪发现。EG:“非常。(),:;<>[]\".VERY.\“very@\\ \”very\“.unusual”@strange.example.com
1赞 Coder12345 4/19/2022
同意,但我从未声称我的方法是 100% 万无一失的。它在大多数情况下都有效。你必须在某个时候现实一点,摒弃非常不可能的情况。大多数电子邮件地址是 [email protected]。如果有人实际上选择使用使用最自由语法的电子邮件地址,那么他/她将真正解决各种服务器/客户端程序未正确验证或允许此类电子邮件的问题,或者在发送/接收时根本无法工作。这样一来,这样的用户将被迫使用更“标准”的语法来确保它在任何地方都能正常工作。
2赞 4 revsJoeytje50 #47

根据我所看到的,一个完全按照标准所说的方式执行的正则表达式是这样的:

/^(?!(^[.-].*|.*[.-]@|.*\.{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}.+@)

对以 .、以 1 结尾、包含 .. 或超过 254 个字符最大长度的地址进行否定展望


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

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


(?!.{253}.+$)

域名部分的负面展望,将其限制为总共 253 个字符


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

每个域名的否定前瞻,不允许开头或结尾


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

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


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

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


(([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 个数字与后面 a 匹配,然后匹配 IP 地址中的第四个数字,而不在其后面。..

评论

3赞 Albin 3/5/2018
不要使用它。它将拒绝像“öåüñ”这样的国际域名。blog.cloudflare.com/non-latinutf8-domains-now-fully-supported
3赞 3 revs, 3 users 72%Alexey Ossikine #48

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

  • 如果您的应用程序涉及技术性很强的东西(或组织内部的东西),那么您可能需要支持 IP 地址而不是域名,或者在电子邮件地址的“本地”部分添加注释。
  • 如果您的应用程序是跨国的,我会考虑专注于 UnicodeUTF-8 支持。

您的问题的主要答案目前链接到“完全符合 RFC-822 的正则表达式”。然而,尽管该正则表达式很复杂,并且假定它关注 RFC 规则中的细节,但在 Unicode 支持方面却完全失败了。

我为大多数应用程序编写的正则表达式侧重于 Unicode 支持,以及 RFC 标准的总体遵守:

/^(?!\.)((?!.*\.{2})[a-zA-Z0-9\u0080-\u00FF\u0100-\u017F\u0180-\u024F\u0250-\u02AF\u0300-\u036F\u0370-\u03FF\u0400-\u04FF\u0500-\u052F\u0530-\u058F\u0590-\u05FF\u0600-\u06FF\u0700-\u074F\u0750-\u077F\u0780-\u07BF\u07C0-\u07FF\u0900-\u097F\u0980-\u09FF\u0A00-\u0A7F\u0A80-\u0AFF\u0B00-\u0B7F\u0B80-\u0BFF\u0C00-\u0C7F\u0C80-\u0CFF\u0D00-\u0D7F\u0D80-\u0DFF\u0E00-\u0E7F\u0E80-\u0EFF\u0F00-\u0FFF\u1000-\u109F\u10A0-\u10FF\u1100-\u11FF\u1200-\u137F\u1380-\u139F\u13A0-\u13FF\u1400-\u167F\u1680-\u169F\u16A0-\u16FF\u1700-\u171F\u1720-\u173F\u1740-\u175F\u1760-\u177F\u1780-\u17FF\u1800-\u18AF\u1900-\u194F\u1950-\u197F\u1980-\u19DF\u19E0-\u19FF\u1A00-\u1A1F\u1B00-\u1B7F\u1D00-\u1D7F\u1D80-\u1DBF\u1DC0-\u1DFF\u1E00-\u1EFF\u1F00-\u1FFFu20D0-\u20FF\u2100-\u214F\u2C00-\u2C5F\u2C60-\u2C7F\u2C80-\u2CFF\u2D00-\u2D2F\u2D30-\u2D7F\u2D80-\u2DDF\u2F00-\u2FDF\u2FF0-\u2FFF\u3040-\u309F\u30A0-\u30FF\u3100-\u312F\u3130-\u318F\u3190-\u319F\u31C0-\u31EF\u31F0-\u31FF\u3200-\u32FF\u3300-\u33FF\u3400-\u4DBF\u4DC0-\u4DFF\u4E00-\u9FFF\uA000-\uA48F\uA490-\uA4CF\uA700-\uA71F\uA800-\uA82F\uA840-\uA87F\uAC00-\uD7AF\uF900-\uFAFF\.!#$%&'*+-/=?^_`{|}~\-\d]+)@(?!\.)([a-zA-Z0-9\u0080-\u00FF\u0100-\u017F\u0180-\u024F\u0250-\u02AF\u0300-\u036F\u0370-\u03FF\u0400-\u04FF\u0500-\u052F\u0530-\u058F\u0590-\u05FF\u0600-\u06FF\u0700-\u074F\u0750-\u077F\u0780-\u07BF\u07C0-\u07FF\u0900-\u097F\u0980-\u09FF\u0A00-\u0A7F\u0A80-\u0AFF\u0B00-\u0B7F\u0B80-\u0BFF\u0C00-\u0C7F\u0C80-\u0CFF\u0D00-\u0D7F\u0D80-\u0DFF\u0E00-\u0E7F\u0E80-\u0EFF\u0F00-\u0FFF\u1000-\u109F\u10A0-\u10FF\u1100-\u11FF\u1200-\u137F\u1380-\u139F\u13A0-\u13FF\u1400-\u167F\u1680-\u169F\u16A0-\u16FF\u1700-\u171F\u1720-\u173F\u1740-\u175F\u1760-\u177F\u1780-\u17FF\u1800-\u18AF\u1900-\u194F\u1950-\u197F\u1980-\u19DF\u19E0-\u19FF\u1A00-\u1A1F\u1B00-\u1B7F\u1D00-\u1D7F\u1D80-\u1DBF\u1DC0-\u1DFF\u1E00-\u1EFF\u1F00-\u1FFF\u20D0-\u20FF\u2100-\u214F\u2C00-\u2C5F\u2C60-\u2C7F\u2C80-\u2CFF\u2D00-\u2D2F\u2D30-\u2D7F\u2D80-\u2DDF\u2F00-\u2FDF\u2FF0-\u2FFF\u3040-\u309F\u30A0-\u30FF\u3100-\u312F\u3130-\u318F\u3190-\u319F\u31C0-\u31EF\u31F0-\u31FF\u3200-\u32FF\u3300-\u33FF\u3400-\u4DBF\u4DC0-\u4DFF\u4E00-\u9FFF\uA000-\uA48F\uA490-\uA4CF\uA700-\uA71F\uA800-\uA82F\uA840-\uA87F\uAC00-\uD7AF\uF900-\uFAFF\-\.\d]+)((\.([a-zA-Z\u0080-\u00FF\u0100-\u017F\u0180-\u024F\u0250-\u02AF\u0300-\u036F\u0370-\u03FF\u0400-\u04FF\u0500-\u052F\u0530-\u058F\u0590-\u05FF\u0600-\u06FF\u0700-\u074F\u0750-\u077F\u0780-\u07BF\u07C0-\u07FF\u0900-\u097F\u0980-\u09FF\u0A00-\u0A7F\u0A80-\u0AFF\u0B00-\u0B7F\u0B80-\u0BFF\u0C00-\u0C7F\u0C80-\u0CFF\u0D00-\u0D7F\u0D80-\u0DFF\u0E00-\u0E7F\u0E80-\u0EFF\u0F00-\u0FFF\u1000-\u109F\u10A0-\u10FF\u1100-\u11FF\u1200-\u137F\u1380-\u139F\u13A0-\u13FF\u1400-\u167F\u1680-\u169F\u16A0-\u16FF\u1700-\u171F\u1720-\u173F\u1740-\u175F\u1760-\u177F\u1780-\u17FF\u1800-\u18AF\u1900-\u194F\u1950-\u197F\u1980-\u19DF\u19E0-\u19FF\u1A00-\u1A1F\u1B00-\u1B7F\u1D00-\u1D7F\u1D80-\u1DBF\u1DC0-\u1DFF\u1E00-\u1EFF\u1F00-\u1FFF\u20D0-\u20FF\u2100-\u214F\u2C00-\u2C5F\u2C60-\u2C7F\u2C80-\u2CFF\u2D00-\u2D2F\u2D30-\u2D7F\u2D80-\u2DDF\u2F00-\u2FDF\u2FF0-\u2FFF\u3040-\u309F\u30A0-\u30FF\u3100-\u312F\u3130-\u318F\u3190-\u319F\u31C0-\u31EF\u31F0-\u31FF\u3200-\u32FF\u3300-\u33FF\u3400-\u4DBF\u4DC0-\u4DFF\u4E00-\u9FFF\uA000-\uA48F\uA490-\uA4CF\uA700-\uA71F\uA800-\uA82F\uA840-\uA87F\uAC00-\uD7AF\uF900-\uFAFF]){2,63})+)$/i

我将避免复制粘贴完整的答案,因此我将仅将其链接到我在此处提供的类似答案:如何验证 unicode 电子邮件?

上面的正则表达式也有一个现场演示,网址为:http://jsfiddle.net/aossikine/qCLVH/3/

2赞 4 revs, 3 users 50%Peter Mortensen #49

几乎增加了一个新域名“yandex”。可能的电子邮件:[email protected]。并且还支持大写字母,因此 acrosman 解决方案的修改版本是:

^[_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)*@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*(\.[a-zA-Z]{2,6})$

评论

2赞 awwright 9/13/2020
这太严格了,并且不允许有效的电子邮件地址,例如o'[email protected]
0赞 Peter Mortensen 2/15/2022
回复“acrosman's solution”:用户acrosman没有发布解决方案或答案,只有一个问题。这指的是什么答案?
3赞 3 revs, 3 users 58%McGaz #50

针对此问题发布的正则表达式现在已经过时,因为新的通用顶级域 (gTLD) 即将到来(例如 .london、.basketball、.通販)。要验证电子邮件地址,有两个答案(与绝大多数人相关)。

  1. 正如主要答案所说 - 不要使用正则表达式。只需通过向该地址发送电子邮件来验证它(捕获无效地址的异常)
  2. 使用一个非常通用的正则表达式,至少确保他们使用的是电子邮件结构,如 .使用详细的正则表达式是没有意义的,因为您不会全部捕获它们,并且几年后会有新的一批,您将不得不再次更新正则表达式。{something}@{something}.{something}

我决定使用正则表达式,因为不幸的是,有些用户不阅读表单并将错误的数据放在错误的字段中。当他们尝试将不是电子邮件的内容放入电子邮件输入字段时,这至少会提醒他们,并且应该为您节省一些时间来支持用户处理电子邮件问题。

(.+)@(.+){2,}\.(.+){2,}

评论

0赞 Peter Mortensen 2/15/2022
gTLD 和 TLD 有什么区别?
0赞 McGaz 2/16/2022
它们实际上都是一样的,只是分类不同。主要有国家代码顶级域名(ccTLD),如.co.uk 或.fr。这些被分配给每个国家,并作为搜索引擎了解位置/目标受众的一个因素。赞助顶级域名(sTLD)分配给组织或政府,例如.gov通用(gTLD)涵盖通用扩展名,例如.com,.london,.mail等。您可以使用哪些限制,价格可能非常不同,但谷歌也表示,无论您是使用 .com 还是 .whatever,都无关紧要。
2赞 2 revs, 2 users 71%sunleo #51

Java Mail API 为我们带来了魔力。

try
{
    InternetAddress internetAddress = new InternetAddress(email);
    internetAddress.validate();
    return true;
}
catch(Exception ex)
{
    return false;
}

我是从这里得到的。

评论

1赞 Developer Marius Žilėnas 12/11/2014
Java Mail API 是用于 Java SE 平台的可选包,包含在 Java EE 平台中。
1赞 3 revs, 2 users 56%Peter Mortensen #52

如前所述,您不能使用正则表达式验证电子邮件。但是,以下是我们目前用来确保用户输入不完全是虚假的(忘记 TLD 等)的方法。

此正则表达式将允许在 @ 符号之前和之后使用 IDN 域和特殊字符(如变音符号)。

/^[\w.+-_]+@[^.][\w.-]*\.[\w-]{2,63}$/iu

评论

0赞 Peter Mortensen 2/15/2022
什么正则表达式风格和/或编程语言?Perl?别的?
3赞 3 revs, 2 users 58%Prasad Bhosale #53

以下是用于验证电子邮件地址的正则表达式:

^.+@\w+(\.\w+)+$

评论

0赞 Peter Mortensen 2/15/2022
鉴于前面的所有答案,这样一个简单的正则表达式需要解释(例如,为什么前面的答案中的巨大复杂性没有必要?它有什么特性?它失败了什么?它确实适用于哪些示例?它不适用于哪些示例?请通过编辑(更改)您的答案来回复,而不是在评论中(没有“编辑:”,“更新:”或类似内容 - 答案应该看起来像今天写的一样)。
0赞 2 revs, 2 users 63%Ramesh Kotkar #54

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

^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$

对于PHP

function checkEmailValidation($email)
{
    $expression = '/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/';
    if(preg_match($expression, $email))
    {
        return true;
    }
    else
    {
        return false;
    }
}

对于 JavaScript

function checkEmailValidation(email)
{
    var pattern = '/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/';
    if(pattern.test(email))
    {
        return true;
    }
    else
    {
        return false;
    }
}

评论

1赞 Luna 8/14/2015
if(preg_match($expression, $email)) { return true; } else { return false; }可以简化为return (bool) preg_match($expression, $email);
5赞 3 revs, 2 users 59%Peter Mortensen #55

对于 PHP,我使用的是 Nette 框架中的电子邮件地址验证器

/* public static */ function isEmail($value)
{
    $atom = "[-a-z0-9!#$%&'*+/=?^_`{|}~]"; // RFC 5322 unquoted characters in local-part
    $localPart = "(?:\"(?:[ !\\x23-\\x5B\\x5D-\\x7E]*|\\\\[ -~])+\"|$atom+(?:\\.$atom+)*)"; // Quoted or unquoted
    $alpha = "a-z\x80-\xFF"; // Superset of IDN
    $domain = "[0-9$alpha](?:[-0-9$alpha]{0,61}[0-9$alpha])?"; // RFC 1034 one domain component
    $topDomain = "[$alpha](?:[-0-9$alpha]{0,17}[$alpha])?";
    return (bool) preg_match("(^$localPart@(?:$domain\\.)+$topDomain\\z)i", $value);
}
25赞 6 revs, 2 users 48%Peter Mortensen #56

HTML5 规范建议使用一个简单的正则表达式来验证电子邮件地址:

/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/

这故意不符合 RFC 5322

注意:此要求故意违反了 RFC 5322,该语法定义了电子邮件地址的语法,该语法同时过于严格(在字符之前)、过于模糊(在字符之后)和过于宽松(允许注释、空格字符和以大多数用户不熟悉的方式引用字符串)在这里没有实际用处。@@

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

评论

2赞 Ryan Taylor 11/7/2017
最佳答案!以下是 w3 建议的链接: w3.org/TR/html5/forms.html#valid-e-mail-address 此正则表达式被许多浏览器采用。
6赞 Sheridan 3/21/2018
这不是最好的答案!此模式与以下完全无效的地址匹配: 。我敦促您在使用它之前谨慎并进行大量测试!invalid@emailaddress
1赞 Luna 3/21/2018
@Sheridan,如果您认为 HTML5 规范存在问题,可以在此处提出问题:github.com/w3c/html/issues
2赞 Mitch Satchwell 5/16/2018
example@localhost是有效的,但对于现实世界的应用程序,您可能希望强制执行域扩展,您需要做的就是将最后的 * 更改为 + 来实现此目的(将模式的该部分从 0+ 更改为 1+)
4赞 awwright 9/1/2020
invalid@emailaddress是有效的电子邮件地址...它只是不存在。(实际上,根据您的网络配置,它甚至可以在您的本地网络内交付。判断地址是否存在的唯一方法是向其发送电子邮件。
2赞 6 revs, 2 users 57%SIslam #57

我没有找到任何涉及顶级域名的内容,但应该考虑一下。

所以对我来说,以下工作是有效的:

[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+(?:[A-Z]{2}AAA|AARP|ABB|ABBOTT|ABOGADO|AC|ACADEMY|ACCENTURE|ACCOUNTANT|ACCOUNTANTS|ACO|ACTIVE|ACTOR|AD|ADAC|ADS|ADULT|AE|AEG|AERO|AF|AFL|AG|AGENCY|AI|AIG|AIRFORCE|AIRTEL|AL|ALIBABA|ALIPAY|ALLFINANZ|ALSACE|AM|AMICA|AMSTERDAM|ANALYTICS|ANDROID|AO|APARTMENTS|APP|APPLE|AQ|AQUARELLE|AR|ARAMCO|ARCHI|ARMY|ARPA|ARTE|AS|ASIA|ASSOCIATES|AT|ATTORNEY|AU|AUCTION|AUDI|AUDIO|AUTHOR|AUTO|AUTOS|AW|AX|AXA|AZ|AZURE|BA|BAIDU|BAND|BANK|BAR|BARCELONA|BARCLAYCARD|BARCLAYS|BARGAINS|BAUHAUS|BAYERN|BB|BBC|BBVA|BCN|BD|BE|BEATS|BEER|BENTLEY|BERLIN|BEST|BET|BF|BG|BH|BHARTI|BI|BIBLE|BID|BIKE|BING|BINGO|BIO|BIZ|BJ|BLACK|BLACKFRIDAY|BLOOMBERG|BLUE|BM|BMS|BMW|BN|BNL|BNPPARIBAS|BO|BOATS|BOEHRINGER|BOM|BOND|BOO|BOOK|BOOTS|BOSCH|BOSTIK|BOT|BOUTIQUE|BR|BRADESCO|BRIDGESTONE|BROADWAY|BROKER|BROTHER|BRUSSELS|BS|BT|BUDAPEST|BUGATTI|BUILD|BUILDERS|BUSINESS|BUY|BUZZ|BV|BW|BY|BZ|BZH|CA|CAB|CAFE|CAL|CALL|CAMERA|CAMP|CANCERRESEARCH|CANON|CAPETOWN|CAPITAL|CAR|CARAVAN|CARDS|CARE|CAREER|CAREERS|CARS|CARTIER|CASA|CASH|CASINO|CAT|CATERING|CBA|CBN|CC|CD|CEB|CENTER|CEO|CERN|CF|CFA|CFD|CG|CH|CHANEL|CHANNEL|CHAT|CHEAP|CHLOE|CHRISTMAS|CHROME|CHURCH|CI|CIPRIANI|CIRCLE|CISCO|CITIC|CITY|CITYEATS|CK|CL|CLAIMS|CLEANING|CLICK|CLINIC|CLINIQUE|CLOTHING|CLOUD|CLUB|CLUBMED|CM|CN|CO|COACH|CODES|COFFEE|COLLEGE|COLOGNE|COM|COMMBANK|COMMUNITY|COMPANY|COMPARE|COMPUTER|COMSEC|CONDOS|CONSTRUCTION|CONSULTING|CONTACT|CONTRACTORS|COOKING|COOL|COOP|CORSICA|COUNTRY|COUPONS|COURSES|CR|CREDIT|CREDITCARD|CREDITUNION|CRICKET|CROWN|CRS|CRUISES|CSC|CU|CUISINELLA|CV|CW|CX|CY|CYMRU|CYOU|CZ|DABUR|DAD|DANCE|DATE|DATING|DATSUN|DAY|DCLK|DE|DEALER|DEALS|DEGREE|DELIVERY|DELL|DELTA|DEMOCRAT|DENTAL|DENTIST|DESI|DESIGN|DEV|DIAMONDS|DIET|DIGITAL|DIRECT|DIRECTORY|DISCOUNT|DJ|DK|DM|DNP|DO|DOCS|DOG|DOHA|DOMAINS|DOOSAN|DOWNLOAD|DRIVE|DUBAI|DURBAN|DVAG|DZ|EARTH|EAT|EC|EDEKA|EDU|EDUCATION|EE|EG|EMAIL|EMERCK|ENERGY|ENGINEER|ENGINEERING|ENTERPRISES|EPSON|EQUIPMENT|ER|ERNI|ES|ESQ|ESTATE|ET|EU|EUROVISION|EUS|EVENTS|EVERBANK|EXCHANGE|EXPERT|EXPOSED|EXPRESS|FAGE|FAIL|FAIRWINDS|FAITH|FAMILY|FAN|FANS|FARM|FASHION|FAST|FEEDBACK|FERRERO|FI|FILM|FINAL|FINANCE|FINANCIAL|FIRESTONE|FIRMDALE|FISH|FISHING|FIT|FITNESS|FJ|FK|FLIGHTS|FLORIST|FLOWERS|FLSMIDTH|FLY|FM|FO|FOO|FOOTBALL|FORD|FOREX|FORSALE|FORUM|FOUNDATION|FOX|FR|FRESENIUS|FRL|FROGANS|FUND|FURNITURE|FUTBOL|FYI|GA|GAL|GALLERY|GAME|GARDEN|GB|GBIZ|GD|GDN|GE|GEA|GENT|GENTING|GF|GG|GGEE|GH|GI|GIFT|GIFTS|GIVES|GIVING|GL|GLASS|GLE|GLOBAL|GLOBO|GM|GMAIL|GMO|GMX|GN|GOLD|GOLDPOINT|GOLF|GOO|GOOG|GOOGLE|GOP|GOT|GOV|GP|GQ|GR|GRAINGER|GRAPHICS|GRATIS|GREEN|GRIPE|GROUP|GS|GT|GU|GUCCI|GUGE|GUIDE|GUITARS|GURU|GW|GY|HAMBURG|HANGOUT|HAUS|HEALTH|HEALTHCARE|HELP|HELSINKI|HERE|HERMES|HIPHOP|HITACHI|HIV|HK|HM|HN|HOCKEY|HOLDINGS|HOLIDAY|HOMEDEPOT|HOMES|HONDA|HORSE|HOST|HOSTING|HOTELES|HOTMAIL|HOUSE|HOW|HR|HSBC|HT|HU|HYUNDAI|IBM|ICBC|ICE|ICU|ID|IE|IFM|IINET|IL|IM|IMMO|IMMOBILIEN|IN|INDUSTRIES|INFINITI|INFO|ING|INK|INSTITUTE|INSURANCE|INSURE|INT|INTERNATIONAL|INVESTMENTS|IO|IPIRANGA|IQ|IR|IRISH|IS|ISELECT|IST|ISTANBUL|IT|ITAU|IWC|JAGUAR|JAVA|JCB|JE|JETZT|JEWELRY|JLC|JLL|JM|JMP|JO|JOBS|JOBURG|JOT|JOY|JP|JPRS|JUEGOS|KAUFEN|KDDI|KE|KFH|KG|KH|KI|KIA|KIM|KINDER|KITCHEN|KIWI|KM|KN|KOELN|KOMATSU|KP|KPN|KR|KRD|KRED|KW|KY|KYOTO|KZ|LA|LACAIXA|LAMBORGHINI|LAMER|LANCASTER|LAND|LANDROVER|LANXESS|LASALLE|LAT|LATROBE|LAW|LAWYER|LB|LC|LDS|LEASE|LECLERC|LEGAL|LEXUS|LGBT|LI|LIAISON|LIDL|LIFE|LIFEINSURANCE|LIFESTYLE|LIGHTING|LIKE|LIMITED|LIMO|LINCOLN|LINDE|LINK|LIVE|LIVING|LIXIL|LK|LOAN|LOANS|LOL|LONDON|LOTTE|LOTTO|LOVE|LR|LS|LT|LTD|LTDA|LU|LUPIN|LUXE|LUXURY|LV|LY|MA|MADRID|MAIF|MAISON|MAKEUP|MAN|MANAGEMENT|MANGO|MARKET|MARKETING|MARKETS|MARRIOTT|MBA|MC|MD|ME|MED|MEDIA|MEET|MELBOURNE|MEME|MEMORIAL|MEN|MENU|MEO|MG|MH|MIAMI|MICROSOFT|MIL|MINI|MK|ML|MM|MMA|MN|MO|MOBI|MOBILY|MODA|MOE|MOI|MOM|MONASH|MONEY|MONTBLANC|MORMON|MORTGAGE|MOSCOW|MOTORCYCLES|MOV|MOVIE|MOVISTAR|MP|MQ|MR|MS|MT|MTN|MTPC|MTR|MU|MUSEUM|MUTUELLE|MV|MW|MX|MY|MZ|NA|NADEX|NAGOYA|NAME|NAVY|NC|NE|NEC|NET|NETBANK|NETWORK|NEUSTAR|NEW|NEWS|NEXUS|NF|NG|NGO|NHK|NI|NICO|NINJA|NISSAN|NL|NO|NOKIA|NORTON|NOWRUZ|NP|NR|NRA|NRW|NTT|NU|NYC|NZ|OBI|OFFICE|OKINAWA|OM|OMEGA|ONE|ONG|ONL|ONLINE|OOO|ORACLE|ORANGE|ORG|ORGANIC|ORIGINS|OSAKA|OTSUKA|OVH|PA|PAGE|PAMPEREDCHEF|PANERAI|PARIS|PARS|PARTNERS|PARTS|PARTY|PE|PET|PF|PG|PH|PHARMACY|PHILIPS|PHOTO|PHOTOGRAPHY|PHOTOS|PHYSIO|PIAGET|PICS|PICTET|PICTURES|PID|PIN|PING|PINK|PIZZA|PK|PL|PLACE|PLAY|PLAYSTATION|PLUMBING|PLUS|PM|PN|POHL|POKER|PORN|POST|PR|PRAXI|PRESS|PRO|PROD|PRODUCTIONS|PROF|PROMO|PROPERTIES|PROPERTY|PROTECTION|PS|PT|PUB|PW|PY|QA|QPON|QUEBEC|RACING|RE|READ|REALTOR|REALTY|RECIPES|RED|REDSTONE|REDUMBRELLA|REHAB|REISE|REISEN|REIT|REN|RENT|RENTALS|REPAIR|REPORT|REPUBLICAN|REST|RESTAURANT|REVIEW|REVIEWS|REXROTH|RICH|RICOH|RIO|RIP|RO|ROCHER|ROCKS|RODEO|ROOM|RS|RSVP|RU|RUHR|RUN|RW|RWE|RYUKYU|SA|SAARLAND|SAFE|SAFETY|SAKURA|SALE|SALON|SAMSUNG|SANDVIK|SANDVIKCOROMANT|SANOFI|SAP|SAPO|SARL|SAS|SAXO|SB|SBS|SC|SCA|SCB|SCHAEFFLER|SCHMIDT|SCHOLARSHIPS|SCHOOL|SCHULE|SCHWARZ|SCIENCE|SCOR|SCOT|SD|SE|SEAT|SECURITY|SEEK|SELECT|SENER|SERVICES|SEVEN|SEW|SEX|SEXY|SFR|SG|SH|SHARP|SHELL|SHIA|SHIKSHA|SHOES|SHOW|SHRIRAM|SI|SINGLES|SITE|SJ|SK|SKI|SKIN|SKY|SKYPE|SL|SM|SMILE|SN|SNCF|SO|SOCCER|SOCIAL|SOFTBANK|SOFTWARE|SOHU|SOLAR|SOLUTIONS|SONY|SOY|SPACE|SPIEGEL|SPREADBETTING|SR|SRL|ST|STADA|STAR|STARHUB|STATEFARM|STATOIL|STC|STCGROUP|STOCKHOLM|STORAGE|STUDIO|STUDY|STYLE|SU|SUCKS|SUPPLIES|SUPPLY|SUPPORT|SURF|SURGERY|SUZUKI|SV|SWATCH|SWISS|SX|SY|SYDNEY|SYMANTEC|SYSTEMS|SZ|TAB|TAIPEI|TAOBAO|TATAMOTORS|TATAR|TATTOO|TAX|TAXI|TC|TCI|TD|TEAM|TECH|TECHNOLOGY|TEL|TELEFONICA|TEMASEK|TENNIS|TF|TG|TH|THD|THEATER|THEATRE|TICKETS|TIENDA|TIFFANY|TIPS|TIRES|TIROL|TJ|TK|TL|TM|TMALL|TN|TO|TODAY|TOKYO|TOOLS|TOP|TORAY|TOSHIBA|TOURS|TOWN|TOYOTA|TOYS|TR|TRADE|TRADING|TRAINING|TRAVEL|TRAVELERS|TRAVELERSINSURANCE|TRUST|TRV|TT|TUBE|TUI|TUSHU|TV|TW|TZ|UA|UBS|UG|UK|UNIVERSITY|UNO|UOL|US|UY|UZ|VA|VACATIONS|VANA|VC|VE|VEGAS|VENTURES|VERISIGN|VERSICHERUNG|VET|VG|VI|VIAJES|VIDEO|VILLAS|VIN|VIP|VIRGIN|VISION|VISTA|VISTAPRINT|VIVA|VLAANDEREN|VN|VODKA|VOLKSWAGEN|VOTE|VOTING|VOTO|VOYAGE|VU|WALES|WALTER|WANG|WANGGOU|WATCH|WATCHES|WEATHER|WEBCAM|WEBER|WEBSITE|WED|WEDDING|WEIR|WF|WHOSWHO|WIEN|WIKI|WILLIAMHILL|WIN|WINDOWS|WINE|WME|WORK|WORKS|WORLD|WS|WTC|WTF|XBOX|XEROX|XIN|XN--11B4C3D|XN--1QQW23A|XN--30RR7Y|XN--3BST00M|XN--3DS443G|XN--3E0B707E|XN--3PXU8K|XN--42C2D9A|XN--45BRJ9C|XN--45Q11C|XN--4GBRIM|XN--55QW42G|XN--55QX5D|XN--6FRZ82G|XN--6QQ986B3XL|XN--80ADXHKS|XN--80AO21A|XN--80ASEHDB|XN--80ASWG|XN--90A3AC|XN--90AIS|XN--9DBQ2A|XN--9ET52U|XN--B4W605FERD|XN--C1AVG|XN--C2BR7G|XN--CG4BKI|XN--CLCHC0EA0B2G2A9GCD|XN--CZR694B|XN--CZRS0T|XN--CZRU2D|XN--D1ACJ3B|XN--D1ALF|XN--ECKVDTC9D|XN--EFVY88H|XN--ESTV75G|XN--FHBEI|XN--FIQ228C5HS|XN--FIQ64B|XN--FIQS8S|XN--FIQZ9S|XN--FJQ720A|XN--FLW351E|XN--FPCRJ9C3D|XN--FZC2C9E2C|XN--G2XX48C|XN--GECRJ9C|XN--H2BRJ9C|XN--HXT814E|XN--I1B6B1A6A2E|XN--IMR513N|XN--IO0A7I|XN--J1AEF|XN--J1AMH|XN--J6W193G|XN--JLQ61U9W7B|XN--KCRX77D1X4A|XN--KPRW13D|XN--KPRY57D|XN--KPU716F|XN--KPUT3I|XN--L1ACC|XN--LGBBAT1AD8J|XN--MGB9AWBF|XN--MGBA3A3EJT|XN--MGBA3A4F16A|XN--MGBAAM7A8H|XN--MGBAB2BD|XN--MGBAYH7GPA|XN--MGBB9FBPOB|XN--MGBBH1A71E|XN--MGBC0A9AZCG|XN--MGBERP4A5D4AR|XN--MGBPL2FH|XN--MGBT3DHD|XN--MGBTX2B|XN--MGBX4CD0AB|XN--MK1BU44C|XN--MXTQ1M|XN--NGBC5AZD|XN--NGBE9E0A|XN--NODE|XN--NQV7F|XN--NQV7FS00EMA|XN--NYQY26A|XN--O3CW4H|XN--OGBPF8FL|XN--P1ACF|XN--P1AI|XN--PBT977C|XN--PGBS0DH|XN--PSSY2U|XN--Q9JYB4C|XN--QCKA1PMC|XN--QXAM|XN--RHQV96G|XN--S9BRJ9C|XN--SES554G|XN--T60B56A|XN--TCKWE|XN--UNUP4Y|XN--VERMGENSBERATER-CTB|XN--VERMGENSBERATUNG-PWB|XN--VHQUV|XN--VUQ861B|XN--WGBH1C|XN--WGBL6A|XN--XHQ521B|XN--XKC2AL3HYE2A|XN--XKC2DL3A5EE0H|XN--Y9A3AQ|XN--YFRO4I67O|XN--YGBI2AMMX|XN--ZFR164B|XPERIA|XXX|XYZ|YACHTS|YAMAXUN|YANDEX|YE|YODOBASHI|YOGA|YOKOHAMA|YOUTUBE|YT|ZA|ZARA|ZERO|ZIP|ZM|ZONE|ZUERICH|ZW)\b

这很容易丢弃电子邮件,例如等。[email protected], [email protected]

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

另一个经常更新的顶级域名列表

评论

0赞 tripleee 9/15/2015
正如这里已经对其他答案的多条评论所指出的那样,有效 TLD 列表正在迅速增长。您的“2 个字母的 ccTLD 或 big-6、info、mobi 等之一”在五年前是合理的,但现在已经完全不可靠了。
1赞 user2366842 1/28/2016
即使在最初撰写时,这已经被几百个顶级域名无效。截至目前,您错过了不到 1200 种可能性(并且以相当规律的速度增长) 当前有效域列表: data.iana.org/TLD/tlds-alpha-by-domain.txt
2赞 Peter Mortensen 2/15/2022
正则表达式中有近 8,000 个字符?有严重的问题。难道它不能分层、重构、拆分成几个部分或类似而不是一个大的正则表达式吗?其中大概有很多冗余。
1赞 2 revs, 2 users 57%syp_dino #58

我找到了一篇不错的文章,其中说验证电子邮件地址的最佳方法是正则表达式。/.+@.+\..+/i

评论

4赞 Toto 9/25/2015
它与有效地址不匹配,例如:me@localhost
3赞 chukko 2/3/2016
它还匹配无效地址,如 john doe@his domain.com。
5赞 3 revs, 2 users 72%FlameStorm #59

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

  1. 检查符号 @ 是否存在,在它之前和之后有一些非 @ 符号: /^[^@]+@[^@]+$/
  2. 尝试向此地址发送一封带有一些“激活码”的电子邮件。
  3. 当用户“激活”他/她的电子邮件地址时,我们将看到一切正常。

当然,当用户输入“奇怪”的电子邮件时,您可以在前端显示一些警告或工具提示,以帮助他/她避免常见错误,例如域部分没有点或名称中没有空格而没有引用等。但是,如果用户真的需要,则必须接受地址“hello@world”。

此外,您必须记住,电子邮件地址标准过去和现在都可以发展,因此您不能一劳永逸地输入一些“标准有效”的正则表达式。而且您必须记住,一些具体的互联网服务器可能会无法满足通用标准的某些细节,并且实际上可以使用自己的“修改后的标准”。

因此,只需选中@,在前端提示用户并在给定地址发送验证电子邮件即可。

2赞 5 revs, 3 users 41%Prassd Nidode #60

列表项

我使用这个函数

function checkmail($value) {
    $value = trim($value);
    if (stristr($value,"@") &&
        stristr($value,".") &&
        (strrpos($value, ".") - stripos($value, "@") > 2) &&
        (stripos($value, "@") > 1) &&
        (strlen($value) - strrpos($value, ".") < 6) &&
        (strlen($value) - strrpos($value, ".") > 2) &&
        ($value == preg_replace('/[ ]/', '', $value)) &&
        ($value == preg_replace('/[^A-Za-z0-9\-_.@!*]/', '', $value))
    )
    {

    }
    else {
        return "Invalid Mail-Id";
    }
}
4赞 2 revs, 2 users 67%Simon_Weaver #61

我见过的几乎所有正则表达式 - 包括 Microsoft 使用的一些表达式都不允许以下有效电子邮件通过:[email protected]

我刚刚有一个真正的客户,他的电子邮件地址是这种格式,但无法下订单。

这是我决定的:

  • 不会有漏报的最小正则表达式。或者,将构造函数与一些额外的检查一起使用(见下文):MailAddress
  • 检查常见的错别字或要求确认“您确定这是您的正确电子邮件地址吗?看来可能有错误。如果确定,允许用户接受他们键入的内容。.cmo.gmial.com
  • 在实际发送电子邮件时处理退回邮件,并手动验证它们以检查明显的错误。

try
{
    var email = new MailAddress(str);

    if (email.Host.EndsWith(".cmo"))
    {
        return EmailValidation.PossibleTypo;
    }

    if (!email.Host.EndsWith(".") && email.Host.Contains("."))
    {
        return EmailValidation.OK;
    }
}
catch
{
    return EmailValidation.Invalid;
}

评论

1赞 Kerem Demirer 3/24/2017
这个答案具有误导性,与问题无关。允许用户输入错误的电子邮件是一个商业决策,问题在于如何使用正则表达式进行验证。
1赞 Michael Sims 6/3/2021
这篇文章的第一个答案确实通过了 [email protected] 就好了。
0赞 Peter Mortensen 2/15/2022
什么编程语言?C#爪哇?别的?
0赞 Peter Mortensen 2/15/2022
示例代码中未包含该示例。.gmial.com
0赞 Peter Mortensen 2/15/2022
从未见过“Gmail”拼写错误为“Gmial”。
1赞 3 revs, 2 users 69%Peter Mortensen #62

我将代码转换为 Java 以匹配编译器:

String pattern = "(?:[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-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-zA-Z0-9-]*[a-zA-Z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])";
4赞 3 revs, 2 users 76%Dave Black #63

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

  1. 大写和小写字母
  2. 数字 0 到 9
  3. 字符 !#$%&'*+-/=?^_'{|}~
  4. 字符“.”,前提是它不是本地部分中的第一个或最后一个字符。

比赛:

非匹配项:

对于符合 RFC 2821 和 2822 的,可以使用:

^((([!#$%&'*+\-/=?^_`{|}~\w])|([!#$%&'*+\-/=?^_`{|}~\w][!#$%&'*+\-/=?^_`{|}~\.\w]{0,}[!#$%&'*+\-/=?^_`{|}~\w]))[@]\w+([-.]\w+)*\.\w+([-.]\w+)*)$

电子邮件 - 符合 RFC 2821、2822 标准

评论

0赞 Cees Timmerman 11/19/2022
为什么它不适用于 Håkan.Söderström@malmö.se?
2赞 2 revs, 2 users 93%partoftheorigin #64

为所有事物编写正则表达式将花费大量精力。相反,您可以使用 pyIsEmail 包。

以下文字摘自pyIsEmail网站。

pyIsEmail 是一种严肃的方法,用于检查用户提供的电子邮件地址是否真实。

正则表达式的编写成本很低,但当新的顶级域名出现或不符合重新流行的电子邮件寻址功能时,通常需要维护。pyIsEmail 允许您通过一个简单的调用来验证电子邮件地址——如果您愿意,甚至可以检查域,从而使您的代码更具可读性和编写速度。当您想知道为什么电子邮件地址无法验证时,他们甚至会为您提供诊断。

用法

为了最简单的用法,导入并使用 is_email 函数:

from pyisemail import is_email

address = "[email protected]"
bool_result = is_email(address)
detailed_result = is_email(address, diagnose=True)

您还可以检查电子邮件中使用的域是否为有效域,以及它是否具有有效的 MX 记录

from pyisemail import is_email

address = "[email protected]"
bool_result_with_dns = is_email(address, check_dns=True)
detailed_result_with_dns = is_email(address, check_dns=True, diagnose=True)

这些是是否可以在该域中颁发电子邮件地址的主要指标。但是,此处的有效响应并不能保证电子邮件存在,而只能保证电子邮件存在。

除了基本的is_email功能外,您还可以单独使用验证器。查看验证器源文档,了解其工作原理。

评论

0赞 Peter Mortensen 2/15/2022
回复“......当新的顶级域名出现时“:现在不是真的有数千个吗?
0赞 Peter Mortensen 2/15/2022
这听起来更像是广告。它到底有什么作用?要点是什么?它是否通过互联网上线进行一些查找或检查(涉及一些DNS内容)?有效地尝试发送电子邮件以查看会发生什么?还是别的什么?
4赞 4 revs, 3 users 67%Asad Ali Choudhry #65

虽然已经添加了非常详细的答案,但我认为对于正在寻找一种简单的方法来验证电子邮件地址或从 Java 中的字符串中获取所有电子邮件地址的开发人员来说,这些答案已经足够复杂了。

public static boolean isEmailValid(@NonNull String email) {
    return android.util.Patterns.EMAIL_ADDRESS.matcher(email).matches();
}

就正则表达式而言,我总是使用这个正则表达式,它适用于我的问题。

"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}"

如果您希望通过匹配电子邮件正则表达式从字符串中查找所有电子邮件地址。您可以在此链接中找到一种方法。

评论

0赞 Peter Mortensen 2/15/2022
回复“哪个对我的问题有用”:这些问题会是什么?假阳性和漏报的例子有哪些?你如何处理这些?
0赞 Peter Mortensen 2/15/2022
什么编程语言?爪哇?这是第2条评论和第2个问题。
7赞 8 revs, 2 users 81%awwright #66

电子邮件地址的正则表达式为:

/^("(?:[!#-\[\]-\u{10FFFF}]|\\[\t -\u{10FFFF}])*"|[!#-'*+\-/-9=?A-Z\^-\u{10FFFF}](?:\.?[!#-'*+\-/-9=?A-Z\^-\u{10FFFF}])*)@([!#-'*+\-/-9=?A-Z\^-\u{10FFFF}](?:\.?[!#-'*+\-/-9=?A-Z\^-\u{10FFFF}])*|\[[!-Z\^-\u{10FFFF}]*\])$/u

此正则表达式与 RFC 5321、RFC 5322RFC 6532 中指定的非过时电子邮件地址的 ABNF 100% 相同。addr-spec

此外,还必须验证:

  • 电子邮件地址格式为 UTF-8(或 ASCII,如果您无法发送到国际化电子邮件地址)
  • 地址不超过 320 个 UTF-8 字节
  • 用户部分(第一个匹配组)不超过 64 个 UTF-8 字节
  • 域部分(第二个匹配组)不超过 255 个 UTF-8 字节

完成所有这些操作的最简单方法是使用现有函数。在 PHP 中,请参阅 filter_var 函数 using 和 (如果可以发送到国际化的电子邮件地址):FILTER_VALIDATE_EMAILFILTER_FLAG_EMAIL_UNICODE

$email_valid = filter_var($email_input, FILTER_VALIDATE_EMAIL, FILTER_FLAG_EMAIL_UNICODE);

但是,也许您正在构建这样的函数,实际上,实现此函数的最简单方法是使用正则表达式。

请记住,这仅验证电子邮件地址不会导致语法错误。验证该地址是否可以接收电子邮件的唯一方法是实际发送电子邮件。

接下来,我将介绍如何生成此正则表达式。


我写了一个新的答案,因为这里的大多数答案都犯了一个错误,要么指定了一个限制性太强的模式(所以没有很好地老化);或者它们显示一个正则表达式,该表达式实际上与 MIME 邮件的标头匹配,而不是电子邮件地址本身。

只要没有递归部分,就完全可以从 ABNF 创建正则表达式。

RFC 5322 指定在 MIME 邮件中发送的合法内容;将此视为合法电子邮件地址的上限。

但是,完全遵循此 ABNF 将是一个错误:从技术上讲,此模式表示您在 MIME 邮件中对电子邮件地址进行编码的方式,并允许不属于电子邮件地址的字符串,例如折叠空格和注释;它包括对过时表单的支持,这些表单是不合法的(但服务器出于历史原因读取)。电子邮件地址不包括这些内容。

RFC 5322 解释:

原子和点原子都被解释为一个单一的单元,包括 构成它的字符串。从语义上讲,可选的 围绕其余角色的评论和 FWS 不是一部分 的原子;Atom 只是一个 Atom 中 atext 字符的运行, 或点原子中的 atext 和 “.” 字符。

在某些定义中,会有一些非终端的名称 以“obs-”开头。这些“obs-”元素是指 第 4 节中的过时语法。在所有情况下,这些作品 为了生成合法的互联网而忽略 消息,并且不得用作此类消息的一部分。

如果从 RFC 5322 中删除 、 和规则,并对结果进行一些优化(我使用了“greenery”),则可以生成此正则表达式,用斜杠引用并锚定(适用于ECMAScript和兼容的方言,为了清楚起见,添加了换行符):CFWSBWSobs-*addr-spec

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

这仅支持 ASCII 电子邮件地址。要支持 RFC 6532 国际化电子邮件地址,请将字符替换为 (PHP, ECMAScript with the flag),或者(对于 UTF-16 实现,如 .NET 和更早的 ECMAScript/JavaScript):~\u{10FFFF}u\uFFFF

/^("(?:[!#-\[\]-\u{10FFFF}]|\\[\t -\u{10FFFF}])*"|[!#-'*+\-/-9=?A-Z\^-\u{10FFFF}](?:\.?[!#-'*+\-/-9=?A-Z\^-\u{10FFFF}])*)@([!#-'*+\-/-9=?A-Z\^-\u{10FFFF}](?:\.?[!#-'*+\-/-9=?A-Z\^-\u{10FFFF}])*|\[[!-Z\^-\u{10FFFF}]*\])$/u

这是可行的,因为我们使用的 ABNF 不是递归的,因此形成了一种可以转换为正则表达式的非递归正则语法。

它分解如下:

  • 用户部分(在 之前)可以是点原子或带引号的字符串@
  • "([!#-\[\]-~]|\\[\t -~])*"指定用户的带引号的字符串形式,例如 .它允许在双引号内使用任何非控制字符;但空格、制表符、双引号和反斜杠必须进行反斜杠转义。"root@home"@example.com
  • [!#-'*+\-/-9=?A-Z\^-~]是用户点原子的第一个字符。
  • (\.?[!#-'*+\-/-9=?A-Z\^-~])*匹配点原子的其余部分,允许点(除非在另一个点之后,或作为最后一个字符)。
  • @表示域。
  • 域部分可以是点原子或域文字。
  • [!#-'*+\-/-9=?A-Z\^-~](\.?[!#-'*+\-/-9=?A-Z\^-~])*与上面的点原子形式相同,但这里代表域名和 IPv4 地址。
  • \[[!-Z\^-~]*\]将匹配 IPv6 地址和主机名的未来定义。

此正则表达式允许所有符合规范的电子邮件地址,并且可以在 MIME 邮件中逐字使用(行长度限制除外,在这种情况下,必须添加折叠空格)。

这还会设置非捕获组,以便将成为用户,将成为主机。(但是,如果以双引号开头,则过滤掉反斜杠转义符以及开始和结束双引号:,并标识相同的收件箱。match[1]match[2]match[1]"root"@example.com[email protected]

最后,请注意,RFC 5321 对电子邮件地址的长度设置了限制。用户部分最多可达 64 个字节,域部分最多可达 255 个字节。包括字符在内,整个地址的限制为 320 个字节。这是在地址进行 UTF-8 编码后以字节为单位测量的;不是字符。@

请注意,RFC 5322 ABNF 为域名定义了一种宽松的语法,允许当前已知的名称无效。这也允许将来可能合法化的域名。这应该不是问题,因为这应该像不存在的域名一样处理。

始终考虑用户键入的电子邮件地址有效,但他们无权访问的可能性。验证电子邮件地址的唯一万无一失的方法是发送电子邮件。

本文改编自我的文章E-Mail Addresses & Syntax

评论

1赞 Post Impatica 5/13/2021
我可以在 javascript 中使用它,但无法将其格式化以供 C# 使用。我试过把它放到regex101网站,它说它无效
1赞 awwright 5/17/2021
@PostImpatica 错误到底是什么?Regex101 需要斜杠分隔的正则表达式。我不知道 C# 期望哪种方言。如果您的方言是斜杠分隔的,则需要使用反斜杠对斜杠进行转义。
1赞 Cees Timmerman 11/19/2022
"John Smith"@example.com不适用于这些 regexr.com
2赞 awwright 11/20/2022
@CeesTimmerman 空格必须以引号形式转义,请参阅 rfc-editor.org/rfc/rfc5322#section-3.2.4 这在我的帖子中提到:“它允许在双引号内使用任何非控制字符;但空格、制表符、双引号和反斜杠必须进行反斜杠转义。请注意,空格在 ASCII 中不被视为“打印”,请参阅 rfc-editor.org/rfc/rfc5234#appendix-B.1 中的 VCHAR 生产
-3赞 3 revs, 2 users 56%Peter Mortensen #67

这个简单的模式对我有用:

^(?<name>[^<>#()\.,;\s@\"]{1,})@(?<domain>[^<>#()\.,;\s@\"]{2,}\.(?<top>[^<>#()\.,;:\s@\"]{2,}))$

评论

2赞 Jonathan Leffler 10/2/2020
欢迎使用 Stack Overflow。如果您决定回答一个已经确定且正确答案的旧问题,那么在当天晚些时候添加新答案可能不会给您带来任何积分。如果你有一些独特的新信息,或者你确信其他答案都是错误的,一定要添加一个新答案,但是在问题被问到很久之后,“另一个答案”给出相同的基本信息通常不会为你赢得太多的信任。也不完全清楚您使用的是正则表达式的哪种方言。
2赞 3 revs, 3 users 73%OXiGEN #68

如果需要一个简单的表单来验证,可以使用答案 https://regexr.com/3e48o

^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$

let r = new RegExp(String.raw `^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$`);

//should be true
console.log(r.test('[email protected]'));
console.log(r.test('[email protected]'));
console.log(r.test('[email protected]'));

//should be false
console.log(r.test('@domain.tld'));
console.log(r.test('[email protected]'));
console.log(r.test('name@domain.'));
console.log(r.test('namedomain.tld'));
console.log(r.test(''));

//now that basic client-side validation is done, send a token from the server side to validate the user actually has access to the email

评论

7赞 doppelgreener 4/15/2021
这个正则表达式太简单了,拒绝了普通的有效电子邮件。它错误地拒绝了局部部分 () 中的加号助词,并错误地拒绝了具有四个以上字母 () 的通用顶级域。[email protected][email protected]
0赞 Pavindu 4/23/2022
例如,这会对验证域进行故障转移.academy
-3赞 2 revs, 2 users 57%Peter Mortensen #69

我使用的正则表达式:

[\w-+]+([.][\w]+)?@[\w-+]+([.][a-z]{2,})+
0赞 Craig #70

我们还有另一种选择是使用具有 .这不仅可以应用于类的属性,还可以在运行时利用。DataAnnotationsEmailAddressAttribute

using System.ComponentModel.DataAnnotations;

典型用法

public class Person
{
    public int Id { get; set; }

    [EmailAddress]
    public string Email { get; set; }
}

在运行时

var emailAddressAttribute = new EmailAddressAttribute();

if (emailAddressAttribute.IsValid("[email protected]"))
{
    //email is valid
}
else
{
    //email is invalid
}
0赞 2 revs, 2 users 85%Tim Wißmann #71

出于我的目的,我需要一种方法来提取显示名称(如果提供)。
多亏了其他答案和 https://emailregex.com/ 上提供的正则表达式,我想出了以下解决方案:

/^(?:([^<]*?)\s*<)?((?:[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])+)\]))>?$/gi

这与显示名称 (=组 1) + 电子邮件地址 (=组 2) 匹配。

比赛示例:

[email protected]
john.o'[email protected]
John <[email protected]>
<[email protected]>
This is <[email protected]>

https://regex101.com/ 测试

当然,正如其他答案中提到的,需要对显示名称和电子邮件地址的长度进行额外验证(不应超过 320 个 UTF-8 字节)。

0赞 2 revsThinkTrans #72

问题标题相当通用,但问题的正文表明它是关于基于 PHP 的解决方案的。将尝试解决这两个问题。

一般来说,对于所有编程语言:通常,任何基于互联网的服务提供商都应该停止使用正则表达式验证电子邮件地址。各种域名和电子邮件地址的可能性在种类方面已经大大增加,任何未经深思熟虑的验证尝试最终都可能拒绝一些有效用户进入您的系统。为避免这种情况,最好的方法之一是向用户发送电子邮件并验证它是否被接收。“普遍适用性指导小组”的好人编制了一份语言库列表,这些库被发现符合/不符合各种参数,涉及对国际化域名和国际化电子邮件地址的验证。请在此处此处找到这些文档的链接。

具体说到PHP:

PHP 中有一个很好的库,即 EmailValidator。它是一个电子邮件地址验证器,包括许多验证方法,例如 DNS 验证。特别推荐的验证程序称为 RFCValidator,它根据多个 RFC 验证电子邮件地址。在对 IDN 和国际化电子邮件地址的包容性方面,它具有良好的合规性。

1赞 Eggon #73

我想提出我的方法,这种方法相对简单,同时确保正确的电子邮件结构并限制禁止的字符。对拉丁字符有效。

/^(?![\w\.@]*\.\.)(?![\w\.@]*\.@)(?![\w\.]*@\.)\w+[\w\.]*@[\w\.]+\.\w{2,}$/

评论

0赞 Epic Speedy 5/20/2022
这是迄今为止最好的一个。
0赞 San 7/11/2022
你能用 golang 做到这一点吗?