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

4125
多年来,我已经逐渐开发出一种正则表达式,可以正确验证大多数电子邮件地址(假设它们没有使用IP地址作为服务器部分)。我在几个PHP程序中使用它,大多数情况下都有效。但是,不时有人联系我,称使用该表达式的站点出现问题,我最近意识到我没有允许四个字符的TLDs,因此不得不进行一些调整。你认为验证电子邮件的最佳正则表达式是什么?我看过几种解决方案,它们使用函数,这些函数使用几个较短的表达式,但我宁愿在一个简单的函数中使用一个长且复杂的表达式,而不是在一个更复杂的函数中使用几个短的表达式。

10
可以验证 IDNA 格式是否正确的正则表达式太长了,无法在 StackExchange 中使用。(规范化的规则非常复杂,特别不适合使用正则表达式处理。) - Jasen
正则表达式可能是可变的,因为在某些情况下,电子邮件内容可能包含空格,而在其他情况下,则不能包含任何空格。 - Ṃųỻịgǻňạcểơửṩ
我建议您查看这篇文章:https://debounce.io/blog/articles/email-syntax-error-explained/ - Iman
显示剩余7条评论
80个回答

3341

完全符合RFC 822的正则表达式由于长度而低效且晦涩。幸运的是,RFC 822已经被替代了两次,当前电子邮件地址的规范是RFC 5322。 RFC 5322导致了一个正则表达式,如果学习几分钟就可以理解,并且足够高效以实际使用。

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

修正IP模式中的00错误后,我们获得了一个工作且相当快速的正则表达式。(获取实际代码时,请爬取渲染版本,而不是markdown。)

(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])

或者:

(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])

这是一个有限状态机图示, 比正则表达式本身更加清晰明了。enter image description here

Perl和PCRE(在PHP中使用的正则表达式库)中更复杂的模式可以毫不费力地正确解析RFC 5322。Python和C#也可以做到,但它们使用与前两者不同的语法。然而,如果你被迫使用许多功能较弱的模式匹配语言之一,则最好使用真正的解析器。
还要了解,按照RFC验证它绝对不能告诉您该地址是否实际存在于提供的域中,或者输入该地址的人是否是其真正所有者。人们经常以这种方式向其他人注册邮件列表。修复这个问题需要一种更高级的验证方式,其中包括向该地址发送包含确认令牌的消息,该令牌意味着必须在与地址相同的网页上输入。
确认令牌是唯一的方法,可以知道您获得了输入人员的地址。这就是为什么大多数邮件列表现在使用该机制来确认注册。毕竟,任何人都可以写下president@whitehouse.gov,即使它合法,但那不太可能是另一端的人。
对于PHP,您不应该使用用PHP正确验证电子邮件地址中给出的模式,我引用如下:

有一些危险,常见用法和普遍的粗糙编码将建立一个电子邮件地址的事实标准,该标准比记录的正式标准更为严格。

这种方法不比其他非RFC模式更好。 它甚至无法智能处理RFC 822,更别提RFC 5322了。 然而这个可以。

如果你想变得花哨和学究一点,实现一个完整的状态引擎。 正则表达式只能作为基本过滤器。 正则表达式的问题在于,从用户的角度来看,告诉他们他们完全有效的电子邮件地址无效(误报)是粗鲁和不礼貌的。 专门用于此目的的状态引擎可以验证甚至纠正否则将被认为无效的电子邮件地址,因为它根据每个RFC拆分电子邮件地址。 这可以实现更令人愉悦的体验,例如

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

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

Regular expression visualization

Debuggex演示


259
你说过“没有好的正则表达式。”这是针对电子邮件地址验证还是一般性的说法? - Tomalak
59
@Tomalak指的仅是电子邮件地址。正如bortzmeyer所说,该RFC非常复杂。 - Luk
46
您提到的Linux Journal文章在几个方面事实上是错误的。特别是Lovell显然没有阅读RFC3696的勘误表,并重复了RFC已发布版本中的一些错误。更多信息请参见:http://www.dominicsayers.com/isemail - Dominic Sayers
8
请注意,当前的HTML5规范中包含了一个正则表达式和ABNF来验证电子邮件类型的输入,这种验证方式比原始的RFC更加严格。 - Synchro
18
RFC 822第6.2.4节明确允许使用大写字母,但是这个答案没有使用。 https://www.w3.org/Protocols/rfc822/#z26 或许这个答案的作者打算让他们的正则表达式不区分大小写。如果是这样,那么应该在答案正文中明确说明。 - Jared Beck
显示剩余25条评论

850

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

相反,在C#中应该使用MailAddress类,像这样:

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" - "User Display Name 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.这样末尾带有句点的地址也被MailAddress接受。
如果您真的想使用正则表达式,可以在这里找到。
(?:(?:\r\n)?[ \t])*(?:(?:(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t]
)+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:
\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(
?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ 
\t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\0
31]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\
](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+
(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:
(?:\r\n)?[ \t])*))*|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z
|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)
?[ \t])*)*\<(?:(?:\r\n)?[ \t])*(?:@(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\
r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[
 \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)
?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t]
)*))*(?:,@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[
 \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*
)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t]
)+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*)
*:(?:(?:\r\n)?[ \t])*)?(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+
|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r
\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t
]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031
]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](
?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?
:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?
:\r\n)?[ \t])*))*\>(?:(?:\r\n)?[ \t])*)|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?
:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?
[ \t]))*"(?:(?:\r\n)?[ \t])*)*:(?:(?:\r\n)?[ \t])*(?:(?:(?:[^()<>@,;:\\".\[\] 
\000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|
\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>
@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|" (?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t] )*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\ ".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(? :[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[ \]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*|(?:[^()<>@,;:\\".\[\] \000- \031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|( ?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)*\<(?:(?:\r\n)?[ \t])*(?:@(?:[^()<>@,; :\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([ ^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\" .\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\ ]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*(?:,@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\ [\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\ r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\] |\\.)*\](?:(?:\r\n)?[ \t])*))*)*:(?:(?:\r\n)?[ \t])*)?(?:[^()<>@,;:\\".\[\] \0 00-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\ .|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@, ;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(? :[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])* (?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\". \[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[ ^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\] ]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*\>(?:(?:\r\n)?[ \t])*)(?:,\s*( ?:(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\ ".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:( ?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[ \["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t ])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t ])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(? :\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+| \Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*|(?: [^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\ ]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)*\<(?:(?:\r\n) ?[ \t])*(?:@(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\[" ()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n) ?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>
@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*(?:,@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@, ;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t] )*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\ ".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*)*:(?:(?:\r\n)?[ \t])*)? (?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\". \[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?: \r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\[ "()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t]) *))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t]) +|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\ .(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z |(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*\>(?:( ?:\r\n)?[ \t])*))*)?;\s*)

50
在.NET 4.0中,您会发现MailAddress类在验证电子邮件地址方面比以前的版本要好得多。我对它进行了一些重大改进。 - Jeff Tucker
10
我认为这种方法对于更简单的ID不起作用。a@b不能通过验证。ar@b.com只匹配到ar@b,而.com没有被匹配上。但是,“I am me”@[10.10.10.10]可以使用! :) - Raze
12
请注意,这些符合RFC的正则表达式验证器将允许通过很多电子邮件地址,您可能不希望接受,例如“a<body/onload=alert('http://lol.com?'+document.cookies)@a.a>”,它是Perl的Email::Valid中的有效电​​子邮件地址(使用了那个巨大的正则表达式),并可被利用进行XSS攻击。https://rt.cpan.org/Public/Bug/Display.html?id=75650 - Matthew Lock
14
这句话的意思是:“那个网址并不比'fake@not-a-real-domain.name'更糟。”你不能依赖电子邮件验证来防止跨站脚本攻击(XSS)。 - SLaks
15
@MatthewLock:不行。你需要对SQL查询进行转义(或者更好的方法是使用参数)。清洗并不是一个合适的防御措施。 - SLaks
显示剩余10条评论

612

这个问题被问得很多,但我认为你应该退一步,问问自己为什么要去验证电子邮件地址的语法正确性?到底有什么好处呢?

  • 它不能捕捉常见的打字错误。
  • 它不能防止人们输入无效或虚构的电子邮件地址,或者干脆输入别人的地址。

如果您想验证电子邮件是否正确,那么您只能发送确认电子邮件,并要求用户回复。在许多情况下,出于安全原因或伦理道德原因(例如,您不希望违背他人意愿将其注册到某项服务中),您必须发送确认邮件。


125
在客户端验证中,检查他们是否将something@something输入到字段中可能是值得的,以便捕获简单的错误 - 但总的来说,您是正确的。 - Martin Beckett
149
如果有人输入了错误的内容(例如:me@hotmail),他们显然无法收到您的确认邮件,那么他们会在哪里?他们不再在您的网站上,并且会想知道为什么他们无法注册。实际上,他们并没有 - 他们已经完全忘记了您的网站。但是,如果您可以在他们还在使用您的网站时进行基本的正则表达式检查,那么他们就可以立即捕捉到这个错误,您就拥有了一个快乐的用户。 - nickf
5
@JacquesB:你说得很对。仅仅因为符合RFC标准并不意味着那确实是该用户的地址。否则,所有那些类似于president@whitehouse.gov 的地址都会暗示一个非常忙碌的总司令。 :) - tchrist
56
不必非黑即白。如果电子邮件看起来有问题,让用户知道。如果用户仍然想继续,请让他们自己决定。不要强制用户遵循你的正则表达式,相反,将正则表达式作为工具来帮助用户知道可能存在错误。 - ninjaneer
2
安全性。如果您正确验证电子邮件地址并仅允许安全字符,则电子邮件地址被用于某种恶意方式的可能性会大大降低。例如,在电子邮件头利用中。 - Gellweiler
显示剩余3条评论

552

这一切取决于您想要多准确。对于我的目的,我只是试图防止像bob @ aol.com(电子邮件中的空格)或steve(根本没有域)或mary@aolcom(.com之前没有句号)这样的情况出现,我使用

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

当然,这个正则表达式可能匹配一些不合法的电子邮件地址,但这只是处理常见简单错误的问题。

这个正则表达式可以做出任意数量的更改(一些评论已经提供了建议),但它很简单易懂,并且是一个不错的首选。


9
它与 foobar@dk 不匹配,后者是一个有效且可用的电子邮件地址(尽管大多数邮件服务器可能不会接受它,或者会添加 something.com)。 - bortzmeyer
7
@Richard: .包含在\S中。 - David Thornley
67
JJJ: 是的,它将匹配很多垃圾信息。它也会匹配像“&$#$(@$0(%))$#.)&)(*$”这样的内容。对我而言,我更关注捕捉类似于mary@aolcom这样的手误而不是完全的垃圾信息。个人情况可能有所不同。 - Andy Lester
14
用于控制 "@" 符号的正则表达式为:/^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/。http://jsfiddle.net/b9chris/mXB96/ - Chris Moschini
27
另一个常见的打字错误是在域名中使用两个连续的句点或者用逗号代替句点。正则表达式为^[^\s@]+@([^\s@.,]+\.)+[^\s@.,]{2,}$ - Piskvor left the building
显示剩余11条评论

376

这取决于你所说的“最佳”是什么意思: 如果你想捕获每个有效的电子邮件地址,请使用以下方法:

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

(http://www.ex-parrot.com/~pdw/Mail-RFC822-Address.html) 如果你想寻找更简单的方法来捕获大部分有效的电子邮件地址,请尝试类似下面的方法:

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

编辑: 来自链接:
此正则表达式仅验证已删除任何注释并用空格替换的地址(模块执行此操作)。

65
你能给我一个例子,说明哪些“电子邮件地址”会通过第二个正则表达式但实际上是错误的,而会被更长的正则表达式捕获? - Lazer
4
尽管我曾经喜欢它,但那是一个RFC 822验证器,而不是RFC 5322验证器。这里有更好的RFC 5322验证器。 - tchrist
28
"@Lazer in..valid@example.com" 是一个简单的例子。在本地部分中,不允许有两个连续未用引号括起来的句点。 - Randal Schwartz
5
@Mikhail提到了Perl,但实际上你不应该使用它。 - Good Person
3
@RSC是一个FQDN,这很好。 - Good Person
显示剩余13条评论

340

根据W3C HTML5规范

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

上下文:

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

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

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

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

13
很有趣。这是RFC的违规行为,但是是故意的,并且很有道理。现实世界的例子:gmail忽略@之前部分的句点,因此如果你的电子邮件是test@gmail.com,你可以向test.@gmail.comtest....@gmail.com发送电子邮件,尽管这两个地址在RFC中是无效的,但在现实世界中是有效的。 - valentinas
1
我认为最后一部分应该是“+”而不是“”:^[a-zA-Z0-9.!#$%&'+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:.[a-zA-Z0-9-]+)+$ - mmmmmm
11
@mmmmmm john.doe@localhost 是有效的电子邮件地址。当然,在实际的应用中(如社区),我建议将*替换为+。 - rabudde
3
@valentinas 实际上,RFC并没有排除这些本地部分,但它们必须要用引号引起来。根据RFC标准,"test...."@gmail.com 是完全有效的,并且在语义上等同于 test....@gmail.com - Rinke
当我尝试通过我的公司中继使用Python发送电子邮件时,如果我尝试发送到一个带有.@或..@的地址,则会出现错误。实际上,对于_@也是如此。我宁愿在发送之前删除这些字符,而不是相信收件人会这样做。 - ndvo
显示剩余3条评论

299
[更新] 我已经整理了关于电子邮件地址验证的所有知识,网址为http://isemail.info,它不仅能够验证电子邮件地址,还可以诊断电子邮件地址的问题。我同意这里的许多评论,即验证只是答案的一部分;请参阅我的文章什么是有效的电子邮件地址?
据我所知,is_email()仍然是唯一一个可以明确告诉您给定字符串是否为有效电子邮件地址的验证器。我已经在http://isemail.info/上传了一个新版本。
我从Cal Henderson、Dave Child、Phil Haack、Doug Lovell、RFC 5322RFC 3696中收集了测试用例。总共有275个测试地址。我对我能找到的所有免费验证器运行了所有这些测试。
我将尝试使此页面保持最新状态,因为人们增强其验证器。感谢Cal、Michael、Dave、Paul和Phil在编译这些测试和对我的验证器提出建设性批评方面的帮助和合作。

人们应该特别注意RFC 3696中的勘误。其中三个典型示例实际上是无效地址。电子邮件地址的最大长度为254或256个字符,而不是320个。


这个验证器看起来也是正确的。[...时间过去了...] 嗯,看起来只是RFC 5322,而不是3693或其勘误。 - tchrist
2
非常好。在这里,我们不仅得到了一篇好的文章,还得到了一个验证测试器以及一个可以下载的库。回答很棒! - bgmCoder
2
您的验证器不支持punycode(RFC 3492)。name@öäü.at可能是一个有效的地址。(它被翻译为name@xn--4ca9at.at - Josef
嗨@Josef。由于此代码是关于验证而不是解释,请尝试验证name@xn--4ca9at.at。如果您想添加一个punycode翻译器,那么我很乐意接受https://github.com/dominicsayers/isemail的拉取请求。 - Dominic Sayers

207

在 Perl 5.10 或更新版本中很容易实现:

/(?(DEFINE)
   (?<address>         (?&mailbox) | (?&group))
   (?<mailbox>         (?&name_addr) | (?&addr_spec))
   (?<name_addr>       (?&display_name)? (?&angle_addr))
   (?<angle_addr>      (?&CFWS)? < (?&addr_spec) > (?&CFWS)?)
   (?<group>           (?&display_name) : (?:(?&mailbox_list) | (?&CFWS))? ;
                                          (?&CFWS)?)
   (?<display_name>    (?&phrase))
   (?<mailbox_list>    (?&mailbox) (?: , (?&mailbox))*)

   (?<addr_spec>       (?&local_part) \@ (?&domain))
   (?<local_part>      (?&dot_atom) | (?&quoted_string))
   (?<domain>          (?&dot_atom) | (?&domain_literal))
   (?<domain_literal>  (?&CFWS)? \[ (?: (?&FWS)? (?&dcontent))* (?&FWS)?
                                 \] (?&CFWS)?)
   (?<dcontent>        (?&dtext) | (?&quoted_pair))
   (?<dtext>           (?&NO_WS_CTL) | [\x21-\x5a\x5e-\x7e])

   (?<atext>           (?&ALPHA) | (?&DIGIT) | [!#\$%&'*+-/=?^_`{|}~])
   (?<atom>            (?&CFWS)? (?&atext)+ (?&CFWS)?)
   (?<dot_atom>        (?&CFWS)? (?&dot_atom_text) (?&CFWS)?)
   (?<dot_atom_text>   (?&atext)+ (?: \. (?&atext)+)*)

   (?<text>            [\x01-\x09\x0b\x0c\x0e-\x7f])
   (?<quoted_pair>     \\ (?&text))

   (?<qtext>           (?&NO_WS_CTL) | [\x21\x23-\x5b\x5d-\x7e])
   (?<qcontent>        (?&qtext) | (?&quoted_pair))
   (?<quoted_string>   (?&CFWS)? (?&DQUOTE) (?:(?&FWS)? (?&qcontent))*
                        (?&FWS)? (?&DQUOTE) (?&CFWS)?)

   (?<word>            (?&atom) | (?&quoted_string))
   (?<phrase>          (?&word)+)

   # Folding white space
   (?<FWS>             (?: (?&WSP)* (?&CRLF))? (?&WSP)+)
   (?<ctext>           (?&NO_WS_CTL) | [\x21-\x27\x2a-\x5b\x5d-\x7e])
   (?<ccontent>        (?&ctext) | (?&quoted_pair) | (?&comment))
   (?<comment>         \( (?: (?&FWS)? (?&ccontent))* (?&FWS)? \) )
   (?<CFWS>            (?: (?&FWS)? (?&comment))*
                       (?: (?:(?&FWS)? (?&comment)) | (?&FWS)))

   # No whitespace control
   (?<NO_WS_CTL>       [\x01-\x08\x0b\x0c\x0e-\x1f\x7f])

   (?<ALPHA>           [A-Za-z])
   (?<DIGIT>           [0-9])
   (?<CRLF>            \x0d \x0a)
   (?<DQUOTE>          ")
   (?<WSP>             [\x20\x09])
 )

 (?&address)/x

22
非常乐意在Python中看到这个。 - tdc
4
我认为只有 addrspec 部分的子集与问题真正相关。接受更多内容并将其转发到系统的其他部分,而该部分尚未准备好接受完整的 RFC5822 地址,就像是自己开枪打自己的脚一样。 - dolmen
4
不错 (+1),但从技术上讲,它当然不是正则表达式...(因为语法不是正则的,所以这是不可能的)。 - Rinke
12
正则表达式已经不再是“规则”的了,尽管这是Perl中一个有效的“regex”! - rjh
4
我在IDEone上为这个正则表达式设置了一个测试:http://ideone.com/2XFecH。然而,它并不完美。有人可以发表意见吗?我是不是漏掉了什么? - Mike
显示剩余8条评论

199

我使用

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

ASP.NET中RegularExpressionValidator所使用的正则表达式是哪个。


37
呀!我的(不明智的)邮箱地址!@mydomain.net被拒绝了。请问您需要什么样的邮箱地址? - Phrogz
6
@Wayne Whitty。您触及了一个根本问题,即是否要为绝大多数地址提供服务,还是包括所有地址,即使这些地址除了用于测试电子邮件验证外,没有人会使用它们。 - Patanjali
2
我们想要解释一下这个 :)。人们来到这里是为了看看为什么会是这样的。请考虑正则表达式的解释!并不是每个人都足够高级,能够在没有解释的情况下理解你所写的内容。谢谢。 - Pratik Joshi
3
这在 "simon-@hotmail.com" 上失败了,而该地址实际上是有效的(我们的一个客户有一个类似的地址)。 - Simon_Weaver
显示剩余4条评论

149

我不知道最好的方法是什么,但是这个至少是正确的,只要地址中的注释被去除并替换为空格。

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


3
据我所知,有些库也存在问题。我依稀记得 PHP PEAR 曾经存在过这样的一个 bug。 - bortzmeyer
该页面底部还有一份免责声明,说明正则表达式不支持规范中的某些内容。 - Chris Vest
7
这是RFC 822规范,而不是RFC 5322规范。 - tchrist
14
最终,他的观点正确,真正验证电子邮件地址的唯一方法是发送电子邮件并等待回复。 - Blazemonger

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接