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

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

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

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

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

2203609 次浏览

我使用

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

这是ASP.NET中使用的一个。

我不知道最好的,但这一个至少是正确的,只要地址的注释被剥离并替换为空白。

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

互联网上有很多这样的例子(我认为即使是一个完全验证RFC的例子——但如果内存可用,它也有几十/几百行)。

人们在验证这种东西时往往会忘乎所以。为什么不检查它有一个@和至少一个.,并满足一些简单的最小长度呢?输入一封假电子邮件并仍然匹配任何有效的正则表达式是微不足道的。我想误报比误报要好。

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

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

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

纠正IP模式中的00bug,我们获得了一个工作且相当快的正则表达式。(对于实际代码,请删除渲染版本,而不是降价。)

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

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

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

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

确认令牌是知道你有进入它的人的地址的唯一方法。这就是为什么大多数邮件列表现在使用这种机制来确认注册。毕竟,任何人都可以输入president@whitehouse.gov,这甚至会被解析为合法的,但不太可能是另一端的人。

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

常见的用法和广泛的草率编码有可能为电子邮件地址建立一个事实上的标准,该标准比记录的正式标准更具限制性。

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

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

指定的电子邮件地址myemail@address. com无效。您是说myemail@address.com吗?

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

正则表达式可视化

Debuggex Demo

这完全取决于你想要的准确程度。出于我的目的,我只是试图排除bob @ aol.com(电子邮件中的空格)或steve(根本没有域)或mary@aolcom(在. com之前没有句点)之类的东西,我使用

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

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

可以对该正则表达式进行许多更改(有些在本答案的注释中),但它很简单,易于理解,并且是很好的第一次尝试。

没有一个是真正可用的。我在我的正则表达式识别电子邮件地址难吗?61582" title="Is there a PHP library for email address validation?">是否有用于电子邮件地址验证的PHP库?中讨论了一些问题,它也在正则表达式识别电子邮件地址难吗?中讨论。

简而言之,不要指望一个可用的正则表达式能正常工作。最好的正则表达式将验证语法,而不是电子邮件的有效性(jhohn@example.com是正确的,但它可能会反弹…)。

卡尔·亨德森(Flickr)写了一篇名为在PHP中解析电子邮件地址的文章,展示了如何进行正确的符合RFC(2)822的电子邮件地址解析。

您还可以在php、Python和知识共享许可的Ruby中获取源代码。

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

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

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

奇怪的是,您“不能”允许4个字符的顶级域名。您禁止人们使用. info. name,长度限制停止.旅行.博物馆,但是,是的,它们不如2个字符的顶级域名和3个字符的顶级域名常见。

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

对于域名部分的正则表达式,域名不能以“-”开头,也不能以“-”结尾。破折号只能停留在两者之间。

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

我们已经使用http://www.aspnetmx.com/取得了一定程度的成功。您可以选择要验证的级别(例如语法检查、检查域、mx记录或实际的电子邮件)。

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

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

所以,与其使用一些非常复杂的正则表达式,我只是尝试从地址创建一个MailAddress实例。如果地址格式不正确,MailAddress构造函数将抛出异常。这样,我知道我至少可以把电子邮件弄出门。当然这是服务器端验证,但至少你需要它。

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;}}

[更新]我已经整理了我所知道的关于电子邮件地址验证的一切,现在不仅验证,而且还诊断电子邮件地址的问题。我同意这里的许多评论,即验证只是答案的一部分;见我的文章什么是有效的电子邮件地址?

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

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

随着人们增强他们的验证器,我会尽量保持这个页面的最新状态。感谢Cal,Michael,Dave,Paul和Phil在编译这些测试和对我自己的验证器的建设性批评方面的帮助和合作。

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

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

(?:(?:\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])*)?(?:[^()<>@,;:\\".\[\] \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])*)?(?:[^()<>@,;:\\".\[\] \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*(?:(?:[^()<>@,;:\\".\[\] \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-.]+$"

编辑:链接:

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

您可以使用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

为了进行生动的演示,下面的怪物非常好,但它仍然不能正确识别所有语法上有效的电子邮件地址:它可以识别多达四层的嵌套评论。

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

// 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\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:\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:(?-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+)*<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*\](?-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:\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:(?-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+)*<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*\](?-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:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|)+)*\s*\)\s*))+)*\s*\)\s*)*)".Replace("<DQ>", "\"").Replace("\t", "").Replace(" ", "").Replace("\r", "").Replace("\n", "");
private static Regex mailbox =new Regex(gibberish, RegexOptions.ExplicitCapture);

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

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

我不相信Bortzmeyer提出的索赔“语法(在rfc5322中指定)太复杂了”(由正则表达式处理)。

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

addr-spec       =   local-part "@" domainlocal-part      =   dot-atom / quoted-string / obs-local-partdomain          =   dot-atom / domain-literal / obs-domaindomain-literal  =   [CFWS] "[" *([FWS] dtext) [FWS] "]" [CFWS]dtext           =   %d33-90 /          ; Printable US-ASCII%d94-126 /         ;  characters not includingobs-dtext          ;  "[", "]", or "\"

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

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

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

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"

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

相反,在C#中使用邮箱地址类,如下所示:

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

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

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

  • “user1@hotmail.com;user2@gmail.com”
  • "user1@hotmail.com;user2@gmail.com;user3@company.com"
  • "用户显示名称user3@company.com"
  • "user4@company.com"

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

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

此外,末尾有一个点的地址,如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-\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])*)|(?:[^()<>@,;:\\".\[\] \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])*)?(?:[^()<>@,;:\\".\[\] \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*(?:(?:[^()<>@,;:\\".\[\] \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*)

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

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

在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

自2010年5、互联网上存在非拉丁(中文、阿拉伯文、希腊文、希伯来文、西里尔文等)域名。每个人都要更改使用的email regex,因为那些字符肯定不是[a-z]/i\w所涵盖的。他们都会失败。

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

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

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

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

这个正则表达式来自Perl的电子邮件::有效库。我相信它是最准确的,它与所有rfc822匹配。而且,它基于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-\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-\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-\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]*(?:\([^\\\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]*)*)*|(?:[^(\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\015()]*(?:(?:\\[^\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]+(?![^(\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]*(?:\([^\\\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]*)*)*(?:,[\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]+(?![^(\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]*(?:\([^\\\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]*)*)*)*:[\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-\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-\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]*(?:\([^\\\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]*)*)*>)EOF

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

这是当前的顶部表达式,以供参考:

/^([\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

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

(?:[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 validationString email = "xyz@hotmail.com";
//Set the email pattern stringPattern 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 patternMatcher m = p.matcher(email);
//Check whether match is foundboolean matchFound = m.matches();
if (matchFound)System.out.println("Valid Email Id.");elseSystem.out.println("Invalid Email Id.");}}

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

function validateEmail($email) {return (bool) stripos($email,'@');}
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;}}

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

允许字母、数字、-、_ , +, ., &;、/和!

没有-foo@bar.com

没有asd@-bar.com

/^([a-z0-9\+\._\/&!][-a-z0-9\+\._\/&!]*)@(([a-z0-9][-a-z0-9]*\.)([-a-z0-9]+\.)*[a-z]{2,})$/i

我根本不建议使用正则表达式-电子邮件地址太复杂了。这是一个常见的问题,所以我想有很多库包含验证器-如果您使用Javaapache公共资源验证器邮箱验证是一个很好的库。

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

filter_var($value, FILTER_VALIDATE_EMAIL)

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

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

如果您可以接受空值(这不是无效的电子邮件)并且正在运行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);}

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

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

它确实支持IP地址you@192.168.1.1,但我还没有对它进行足够的改进来处理虚假的IP地址范围,例如999.999.999.1

它还支持超过三个字符的所有顶级域名,这些字符停止#0,我认为原始字符允许通过。我被打败了,现在超过3个字符的顶级域名太多了

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

快速回答

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

([-!#-'*+/-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中定义,最著名的是rfc822rfc5322。RFC 822应该被视为“原始”标准,RFC 5322是最新的标准。RFC 822中定义的语法是最宽松的,随后的标准进一步限制了语法,更新的系统或服务应该识别过时的语法,但永远不会生成它。

在这个答案中,我将使用“电子邮件地址”来表示RFC中定义的addr-spec(即jdoe@example.org,但不是"John Doe"<jdoe@example.org>,也不是some-group:jdoe@example.org,mrx@exampel.org;)。

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

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

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

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

rfc822

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

([^][()<>@,;:\\". \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中所有相关的语法规则,它们看起来完全一样,然后是相应的正则表达式。在发布勘误的地方,我为纠正后的语法规则给出一个单独的表达式(标记为“勘误”),并在随后的正则表达式中使用更新后的版本作为子表达式。

如RFC 822第3.1.4段所述,可以在词法标记之间插入可选的线性空白。在适用的情况下,我扩展了表达式以适应此规则,并将结果标记为“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)*]))*

rfc5322

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

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

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

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

我忽略了RFC中的所有“迷惑”规则。这意味着正则表达式仅匹配严格符合RFC 5322的电子邮件地址。如果您必须匹配“旧”地址(如更宽松的语法,包括“迷惑”规则),您可以使用上一段中的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确实允许像这样的本地部分,只是必须引用它们。所以你应该写"a..b"@example.net,而不是a..b@example.net,这在语义上是等价的。

进一步限制

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

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

RFC 5321中提出的语法在主机名和IP地址方面过于宽松。我冒昧地“纠正”了有问题的规则,使用该草案rfc1034作为指导方针。这是结果正则表达式。

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

请注意,根据使用情况,您可能不想在正则表达式中允许“通用地址文字”。还要注意,我在最终正则表达式中使用了负向前看(?!IPv6:)来防止“通用地址文字”部分匹配格式错误的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)。

我也不建议针对文字顶级域列表显式验证,甚至强加长度约束(请记住“.博物馆”如何使[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”正则表达式,这是不可能的。

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

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

根据我的理解,它很可能会被…

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

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

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

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

e[\w+-]+匹配a-z,A-Z,_ , +, - 至少一次

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

@=@

[\w+-]+匹配a-z,A-Z,_ , +, - 至少一次

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

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

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

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

请注意,这将允许+@-.com,但这是保持简单的妥协。

我还在使用:

^[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 allows sequential dots, but Microsoft Exchange Server 2007 refuses them, which follows the most recent standard afaik.

世界上最受欢迎的博客平台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 beif ( strlen( $email ) < 3 ) {return apply_filters( 'is_email', false, $email, 'email_too_short' );}
// Test for an @ character after the first positionif ( strpos( $email, '@', 1 ) === false ) {return apply_filters( 'is_email', false, $email, 'email_no_at' );}
// Split out the local and domain partslist( $local, $domain ) = explode( '@', $email, 2 );
// LOCAL PART// Test for invalid charactersif ( !preg_match( '/^[a-zA-Z0-9!#$%&\'*+\/=?^_`{|}~\.-]+$/', $local ) ) {return apply_filters( 'is_email', false, $email, 'local_invalid_chars' );}
// DOMAIN PART// Test for sequences of periodsif ( preg_match( '/\.{2,}/', $domain ) ) {return apply_filters( 'is_email', false, $email, 'domain_period_sequence' );}
// Test for leading and trailing periods and whitespaceif ( 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 subsif ( 2 > count( $subs ) ) {return apply_filters( 'is_email', false, $email, 'domain_no_periods' );}
// Loop through each subforeach ( $subs as $sub ) {// Test for leading and trailing hyphens and whitespaceif ( trim( $sub, " \t\n\r\0\x0B-" ) !== $sub ) {return apply_filters( 'is_email', false, $email, 'sub_hyphen_limits' );}
// Test for invalid charactersif ( !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 );}

为了使用JavaScript验证电子邮件地址,使用此功能更方便和有效(根据W3学校):

function validateEmail(){var x = document.f.email.value;var atpos = x.indexOf("@");var dotpos = x.lastIndexOf(".");if (atpos < 1 || dotpos < atpos+2 || dotpos+2 >= x.length){alert("Not a valid e-mail address");return false;}}

我使用它,它是完美的。

I找到一个正则表达式符合rfc2822。前面的标准到rfc5322。这个正则表达式看起来表现得相当好,可以覆盖大多数情况,但是随着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])?$
^[_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、博物馆、名称等。它还允许直接绑定到IP地址的电子邮件。

我有一个类似的愿望:想要快速检查电子邮件地址中的语法,而不会过度(Mail::RFC822::Address的答案显然是正确的)电子邮件发送实用程序。我选择了这个(我是一个POSIX正则表达式的人,所以我通常不使用\dPCRE中的这样的东西,因为它们让我不太清楚):

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”必须这样的地址被写在电线上的“foo@xn--ccilienchor-bonn-vnb.de”上(这包括邮件地址:超文本标记语言的链接和这样的乐趣),只有GUI被允许向用户显示(并接受然后转换)这些名称。

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

如果是这种情况,我建议查看新的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;}

它在没有JS的HTML5表单验证-JSFiddle-Code Playground

这有几个优点:

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

明显的缺点可能是缺少对旧浏览器的验证,但这会随着时间的推移而改变。

另见:

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

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

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

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

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

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

  3. 如果通过,则针对更严格的正则表达式进行验证-这可能会禁止有效的电子邮件。如果不通过,则警告用户可能存在错误,但允许用户继续。与步骤(1)不同,用户不允许继续,因为这是一个明显的错误。

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

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

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

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

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

以#0开头,以1结尾的地址,其中包含#1或超过最大254字符长度进行负前瞻


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

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


(?!.{253}.+$)

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


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

对每个不允许的域名进行负面展望以#0开始或结束


([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个数字,后面是.,然后是IP地址中没有.的第四个数字。

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

  • 如果您的应用程序涉及非常技术性的内容(或组织内部的内容),那么您可能需要支持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/

几乎添加了一个新域“yandex”。可能的电子邮件:test@job.yandex。并且还支持大写字母,所以acrosman的解决方案的有点修改版本是:

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

为这个问题发布的正则表达式现在已经过时了,因为新的通用顶级域名(gTLD)进来了(例如. London、.篮球、.通贩)。要验证电子邮件地址,有两个答案(这与绝大多数相关)。

  1. 正如主要答案所说-不要使用正则表达式。只需通过向地址发送电子邮件来验证它(捕获无效地址的异常)
  2. 使用一个非常通用的正则表达式,至少确保他们使用的是像{something}@{something}.{something}这样的电子邮件结构。没有必要去做一个详细的正则表达式,因为你不会抓住所有的正则表达式,几年后会有一个新的批次,你必须再次更新你的正则表达式。

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

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

Java邮件API为我们带来了魔力。

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

我从这里得到了这个。

如前所述,您无法使用正则表达式验证电子邮件。但是,这是我们目前用来确保用户输入不完全是虚假的(忘记顶级域名等)。

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

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

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

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

根据W3C维基百科的有效正则表达式

[A-Z0-9a-z.!#$%&'*+-/=?^_`{|}~]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}

., ! #$%&'*+-/=? ^ _ `.{|}~ @example.com

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

^(([^<>()[\]\\.,;:\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;}}

对于PHP,我使用来自Nette Framework的电子邮件地址验证器

/* 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);}

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])?)*$/

这不符合rfc5322

备注:这个要求是rfc5322中的故意侵犯,它为电子邮件地址定义了一个语法,该语法同时过于严格(在@字符之前)、过于模糊(在@字符之后)和过于松懈(允许注释、空白字符和引用字符串以大多数用户不熟悉的方式出现),在这里没有实际用途。

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

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

所以对我来说,以下工作:

[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

这很容易丢弃3c296rD3HNEE@d139c.a51, Sd@sd.dox等电子邮件。

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

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

我发现了一个不错的文章,它说验证电子邮件地址的最佳方法是正则表达式/.+@.+\..+/i

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

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

当然,如果用户输入了“奇怪”的邮件,为了避免常见错误(比如域名没有点、名称有空格没有引用等),可以在邮件前端显示提示或工具提示。但是如果用户需要输入“hello@world”这个地址,必须接受。

此外,您必须记住,电子邮件地址标准是并且可以发展的,所以您不能一劳永逸地输入一些“标准有效”的正则表达式。您必须记住,一些具体的互联网服务器可能会失败一些通用标准的细节,实际上可以使用自己的“修改后的标准”。

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

列表项

我使用这个功能

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";}}

几乎我见过的每一个正则表达式——包括微软使用的一些正则表达式——都不允许以下有效电子邮件通过:simon-@hotmail.com

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

这是我决定的:

  • 一个不会有假阴性的最小正则表达式。或者使用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;}

我将代码转换为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])+)\\])";

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

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

匹配:

  • A&d@somedomain.com
  • *d@somedomain.com
  • A/d@somedomain.com

不匹配:

  • .abc@somedomain.com
  • abc.@somedomain.com
  • A>b@somedomain.com

对于符合RFC 2821和2822的应用程序,您可以使用:

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

电子邮件-RFC 2821,2822兼容

我用这个;

^(([^<>()\[\]\\.,;:\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,}))$

对于Angular2/Angular7,我使用这个模式:

emailPattern = '^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+[.]+[a-zA-Z0-9-.]+(\\s)*';
private createForm() {this.form = this.formBuilder.group({email: ['', [Validators.required, Validators.pattern(this.emailPattern)]]});}

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

电子邮件正则表达式(RFC 5322)

(?im)^(?=.{1,64}@)(?:("[^"\\]*(?:\\.[^"\\]*)*"@)|((?:[0-9a-z](?:\.(?!\.)|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)?[0-9a-z]@))(?=.{1,255}$)(?:(\[(?:\d{1,3}\.){3}\d{1,3}\])|((?:(?=.{1,63}\.)[0-9a-z][-\w]*[0-9a-z]*\.)+[a-z0-9][\-a-z0-9]{0,22}[a-z0-9])|((?=.{1,63}$)[0-9a-z][-\w]*))$

演示https://regex101.com/r/ObS3QZ/1

# (?im)^(?=.{1,64}@)(?:("[^"\\]*(?:\\.[^"\\]*)*"@)|((?:[0-9a-z](?:\.(?!\.)|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)?[0-9a-z]@))(?=.{1,255}$)(?:(\[(?:\d{1,3}\.){3}\d{1,3}\])|((?:(?=.{1,63}\.)[0-9a-z][-\w]*[0-9a-z]*\.)+[a-z0-9][\-a-z0-9]{0,22}[a-z0-9])|((?=.{1,63}$)[0-9a-z][-\w]*))$
# Note - remove all comments '(comments)' before running this regex# Find  \([^)]*\)  replace with nothing
(?im)                                     # Case insensitive^                                         # BOS
# Local part(?= .{1,64} @ )                           # 64 max chars(?:(                                         # (1 start), Quoted" [^"\\]*(?: \\ . [^"\\]* )*"@)                                         # (1 end)|                                          # or,(                                         # (2 start), Non-quoted(?:[0-9a-z](?:\.(?! \. )|                                          # or,[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)?[0-9a-z]@)                                         # (2 end))# Domain part(?= .{1,255} $ )                          # 255 max chars(?:(                                         # (3 start), IP\[(?: \d{1,3} \. ){3}\d{1,3} \])                                         # (3 end)|                                          # or,(                                         # (4 start), Others(?:                                       # Labels (63 max chars each)(?= .{1,63} \. )[0-9a-z] [-\w]* [0-9a-z]*\.)+[a-z0-9] [\-a-z0-9]{0,22} [a-z0-9])                                         # (4 end)|                                          # or,(                                         # (5 start), Localdomain(?= .{1,63} $ )[0-9a-z] [-\w]*)                                         # (5 end))$                                         # EOS

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

以下文字摘自pyIsEmail网站。

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

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

用法

对于最简单的用法,导入并使用is_email函数:

from pyisemail import is_email
address = "test@example.com"bool_result = is_email(address)detailed_result = is_email(address, diagnose=True)

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

from pyisemail import is_email
address = "test@example.com"bool_result_with_dns = is_email(address, check_dns=True)detailed_result_with_dns = is_email(address, check_dns=True, diagnose=True)

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

除了基本is_email功能之外,您还可以自己使用验证器。检查验证器源文档以了解它是如何工作的。

虽然已经添加了非常详细的答案,但我认为这些对于开发人员来说已经足够复杂了,他们只是在寻找一种简单的方法来验证电子邮件地址或从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}"

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

也许是最好的:

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

以字母或数字开头。它可以包括“-_”,以“.”结尾,并且少于七个字符(例如.公司)。

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

/^("(?:[!#-\[\]-\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

对于未过时的电子邮件地址,此正则表达式与addr-specABNF 100%相同,如在rfc5321rfc5322rfc6532中指定的。

此外,您必须验证:

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

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

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

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

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

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


我写了一个新的答案,因为这里的大多数答案都犯了一个错误,要么指定了一个过于严格的模式(因此没有很好地老化);或者他们提供了一个正则表达式,实际上匹配了MIME消息的标头,而不是电子邮件地址本身。

从ABNF生成正则表达式是完全可能的,只要没有递归部分。

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

但是,完全遵循此ABNF将是一个错误:此模式在技术上代表了您如何编码电子邮件地址在mime消息,并允许字符串不属于电子邮件地址的一部分,例如折叠空格和注释;它包括对不合法生成的过时表单的支持(但服务器出于历史原因读取)。电子邮件地址不包括这些。

RFC 5322解释说:

原子和点原子都被解释为单个单元,包括组成它的字符串。语义上,可选围绕其余角色的注释和FWS不是一部分原子的;原子只是原子中的下一个字符的运行,或者点原子中的attext和.字符。

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

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

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

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

/^("(?:[!#-\[\]-\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.comroot@example.com标识相同的收件箱。)

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

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

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

这是改编自我的文章电子邮件地址和语法

这个简单的模式适合我:

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

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

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

let r = new RegExp(String.raw `^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$`);
//should be trueconsole.log(r.test('name@domain.tld'));console.log(r.test('name@domain.co.tld'));console.log(r.test('name@domain.co'));
//should be falseconsole.log(r.test('@domain.tld'));console.log(r.test('name@.tld'));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

我使用的正则表达式:

[\w-+]+([.][\w]+)?@[\w-+]+([.][a-z]{2,})+

我们还有另一个选择是使用DataAnnotations,它有一个EmailAddressAttribute。这不仅可以应用于类的属性,还可以在运行时利用。

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("name@email.com")){//email is valid}else{//email is invalid}

为了我的目的,我需要一种方法来提取显示名称(如果提供)。感谢其他答案和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)

比赛示例:

john.doe@example.comjohn.o'doe@example.comJohn <john@doe.com><john@doe.com>This is <john@127.0.0.1>

测试用https://regex101.com/

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

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

一般来说,对于所有编程语言:通常,使用reg-ex验证“电子邮件地址”是任何基于Internet的服务提供商都应该停止的事情。各种域名和电子邮件地址的可能性在种类方面增加了很多,任何验证的尝试,如果考虑不周,最终可能会拒绝一些有效用户进入您的系统。为了避免这种情况,最好的方法之一是向用户发送电子邮件并验证它正在接收中。“普遍接受指导小组”的好人编制了一个语言库列表,发现这些库符合/不符合涉及国际化域名和国际化电子邮件地址验证的各种参数。请在这里这里上找到这些文件的链接。

关于PHP:

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

我想提出我的方法,它相对简单,同时确保适当的电子邮件结构和限制禁止的字符。适用于拉丁字符。

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

这是我找到的最好的正则表达式!

/^((([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