多年来,我慢慢地开发了一个正则表达式,它可以正确验证大多数电子邮件地址,假设它们不使用IP地址作为服务器部分。
我在几个PHP程序中使用它,而且大多数时候都可以使用。然而,不时有人与我联系,他们对使用它的网站有问题,我最终不得不做出一些调整(最近我意识到我不允许四个字符的TLD)。
你有或见过验证电子邮件的最佳正则表达式是什么?
我见过几种使用函数的解决方案,这些函数使用了几个较短的表达式,但我宁愿在简单函数中使用一个长的复杂表达式,而不是在更复杂的函数中使用几个短表达式。
多年来,我慢慢地开发了一个正则表达式,它可以正确验证大多数电子邮件地址,假设它们不使用IP地址作为服务器部分。
我在几个PHP程序中使用它,而且大多数时候都可以使用。然而,不时有人与我联系,他们对使用它的网站有问题,我最终不得不做出一些调整(最近我意识到我不允许四个字符的TLD)。
你有或见过验证电子邮件的最佳正则表达式是什么?
我见过几种使用函数的解决方案,这些函数使用了几个较短的表达式,但我宁愿在简单函数中使用一个长的复杂表达式,而不是在更复杂的函数中使用几个短表达式。
当前回答
这是我做的。它不是防弹版,但它“简单”,几乎可以检查所有内容。
[\w+-]+(?:\.[\w+-]+)*@[\w+-]+(?:\.[\w+-]+)*(?:\.[a-zA-Z]{2,4})
我认为已经有了解释,因此您可以根据需要进行修改:
(e) [\w+-]+匹配a-z、a-z、_、+、-至少一次
(m) (?:\.[\w+-]+)*匹配a-z、a-z、_、+、-0或更多次,但需要以a开头。(点)
@ = @
(i) [\w+-]+匹配a-z、a-z、_、+、-至少一次
(l) (?:\.[\w+-]+)*匹配a-z、a-z、_、+、-0或更多次,但需要以a开头。(点)
(com)(?:\.[a-zA-Z]{2,4})匹配a-Z,a-Z 2到4次,从a开始。(点)
给出e(-m)@i(.l).com,其中(.m)和(.l)是可选的,但也可以重复多次。
我认为这会验证所有有效的电子邮件地址,但会阻止潜在的无效地址,而不使用在大多数情况下不需要的过于复杂的正则表达式。
请注意,这将允许+@-.com,但这是保持简单的折衷方案。
其他回答
当您使用PHP编写时,我建议您使用PHP内置的电子邮件验证。
filter_var($value, FILTER_VALIDATE_EMAIL)
如果您运行的是低于5.3.6的PHP版本,请注意这个问题:错误#53091:当我试图过滤一个大于2264个字符的文本时出现崩溃
如果您想了解此内置验证如何工作的更多信息,请参阅此处:PHP的filter_var filter_VALIDATE_EMAIL实际工作吗?
我们还有另一个选择,就是使用具有EmailAddressAttribute的DataAnnotations。这不仅可以应用于类的属性,还可以在运行时加以利用。
使用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
}
电子邮件正则表达式(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
互联网上有很多这样的例子(我认为甚至有一个完全验证RFC的例子——但如果内存可用的话,它有几十/几百行)。
人们倾向于对这类事情进行验证。为什么不检查它是否有@和至少一个。并且满足一些简单的最小长度?输入一封假电子邮件并仍然匹配任何有效的正则表达式是很简单的。我猜假阳性比假阴性好。
出于我的目的,我需要一种方法来提取显示名称(如果提供)。感谢上提供的其他答案和正则表达式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.com
john.o'doe@example.com
John <john@doe.com>
<john@doe.com>
This is <john@127.0.0.1>
使用测试https://regex101.com/
当然,正如其他答案中提到的,还需要对显示名称和电子邮件地址的长度进行额外验证(不应超过320个UTF-8字节)。