我最近在某个地方读到,编写匹配电子邮件地址的正则表达式,考虑标准的所有变化和可能性是极其困难的,明显比人们最初想象的要复杂得多。
为什么会这样呢?
是否有已知且经过验证的正则表达式可以完全实现这一点?
有哪些很好的替代方法可以用于匹配电子邮件地址而不使用正则表达式?
我最近在某个地方读到,编写匹配电子邮件地址的正则表达式,考虑标准的所有变化和可能性是极其困难的,明显比人们最初想象的要复杂得多。
为什么会这样呢?
是否有已知且经过验证的正则表达式可以完全实现这一点?
有哪些很好的替代方法可以用于匹配电子邮件地址而不使用正则表达式?
补充一个比@mmaibaum列出的正则表达式更简单的正则表达式:
^[a-zA-Z]([.]?([a-zA-Z0-9_-]+)*)?@([a-zA-Z0-9\-_]+\.)+[a-zA-Z]{2,4}$
它并不是绝对可靠的,当然也不能覆盖整个电子邮件规范,但它确实可以很好地满足大多数基本要求。更好的是,它相当易懂,并且可以进行编辑。
这段内容摘自HouseOfFusion.com的讨论,这是一个世界级的ColdFusion资源。
MailAddress
对象并捕获FormatException
(如果它失败),或者提取Address
(如果成功)。不要陷入关于捕获异常的性能问题(真的,如果这只是一个单独的Web窗体,它不会产生太大的影响),.NET框架中的MailAddress
类经过了相当完整的解析过程(它没有使用RegEx)。打开Reflector并搜索MailAddress
和MailBnfHelper.ReadMailAddress()
,以查看所有它所做的花式操作。比我聪明的人在微软花了很多时间构建该解析器,我将在实际发送电子邮件到该地址时使用它,因此我也可以使用它来验证传入的地址。这个Java类中有一个验证器: http://www.leshazlewood.com/?p=23
这是由Shiro的创建者(以前是Ki,以前是JSecurity)编写的。
测试电子邮件地址有效性的优缺点:
有两种验证电子邮件的正则表达式:
由于某些字符串可能看起来像有效的电子邮件地址,但实际上并不会发送到任何人的收件箱,因此正则表达式无法匹配所有有效的电子邮件地址和没有有效的电子邮件地址。唯一测试电子邮件是否真正有效的方法是向该地址发送电子邮件并查看是否收到某种响应。考虑到这一点,过于严格匹配电子邮件的正则表达式似乎没有什么意义。
我认为大多数要求电子邮件正则表达式的人都是在寻找第一种选项,即过于宽松的正则表达式。他们想测试一个字符串并查看它是否像电子邮件,如果它绝对不是电子邮件,则可以告诉用户:“嘿,您应该在这里输入电子邮件,而这绝对不是有效的电子邮件。也许您没有意识到这个字段是用来输入电子邮件的,或者可能有错别字”。
如果用户输入的字符串看起来很像有效的电子邮件,但实际上不是,则应由应用程序的其他部分处理此问题。
许多人尝试过,也有很多人接近成功。你可能想阅读wikipedia文章和其他一些资源。
具体来说,你需要记住许多网站和电子邮件服务器对电子邮件地址的验证进行了放宽,因此它们并没有完全实现标准。不过这已经足够保证电子邮件始终能正常工作了。
试试这个:
"(?:[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])+)\])"
请在这里查看详细信息。
然而,与其实现RFC822标准,也许从另一个角度来看会更好。如果邮件服务器不遵循标准,标准的内容就不是那么重要了。因此,我认为最好模仿最流行的邮件服务器在验证电子邮件地址时所做的事情。
有人能提供一些关于这个的见解吗?
是的,这是一个非常复杂的标准,允许很多今天没有人真正使用的东西。 :)
是否有任何已知和经过验证的正则表达式可以完全实现这一点?
这里是一个尝试完全解析整个标准的方法...
http://ex-parrot.com/~pdw/Mail-RFC822-Address.html
除了使用正则表达式匹配电子邮件地址,还有哪些好的替代方法?
我猜想可以在你正在使用的任何语言中使用现有框架来完成这个任务?但是那些框架内部可能会使用正则表达式。它是一个复杂的字符串。正则表达式被设计用于解析复杂的字符串,所以这确实是您最好的选择。
编辑:我应该补充说,我链接到的正则表达式只是为了好玩而已。 我不赞成使用像那样复杂的正则表达式-有些人说“如果你的正则表达式超过一行,那么它肯定有错误”。 我链接它是为了说明标准有多么复杂。
var_dump(filter_var('bob@example.com', FILTER_VALIDATE_EMAIL));
(?:[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])+)\])
变量2:
\A(?:[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-][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])+)\])\z
仅仅因为一封电子邮件在语法上是正确的,并不意味着它是有效的。
一封电子邮件可以遵循 RFC 5322 并通过正则表达式,但对于电子邮件实际的可投递性没有真正的洞察力。如果您想知道这封电子邮件是否是虚假邮件、一次性邮件或无法投递的邮件,或者是否是已知的机器人呢?如果您想排除粗俗或有问题的电子邮件怎么办?顺便说一下,我在一家数据验证公司工作,我希望说明清楚我工作的单位是Service Objects。但作为电子邮件验证领域的专业人士,我认为我们提供的解决方案比正则表达式提供更好的验证。请随意查看,我认为它会有很大帮助。您可以在我们的开发指南中了解更多信息。它实际上进行了许多酷炫的电子邮件检查和验证。
以下是一个例子:
电子邮件:mickeyMouse@gmail.com
{
"ValidateEmailInfo":{
"Score":4,
"IsDeliverable":"false",
"EmailAddressIn":"mickeyMouse@gmail.com",
"EmailAddressOut":"mickeyMouse@gmail.com",
"EmailCorrected":false,
"Box":"mickeyMouse",
"Domain":"gmail.com",
"TopLevelDomain":".com",
"TopLevelDomainDescription":"commercial",
"IsSMTPServerGood":"true",
"IsCatchAllDomain":"false",
"IsSMTPMailBoxGood":"false",
"WarningCodes":"22",
"WarningDescriptions":"Email is Bad - Subsequent checks halted.",
"NotesCodes":"16",
"NotesDescriptions":"TLS"
}
}