使用正则表达式验证电子邮件地址会造成伤害吗?

时间:2018-01-02 03:59:11

标签: regex validation email

我听说用正则表达式验证电子邮件地址是件坏事,而且它确实会造成伤害。这是为什么?我认为验证数据永远不会是件坏事。如果您正确执行验证,可能不必要,但绝不是坏事。你能解释一下为什么这是对还是错?如果它可能造成伤害,请举个例子。

8 个答案:

答案 0 :(得分:10)

通常,是的 - 使用正则表达式来验证电子邮件地址是有害的。这是因为正则表达式的作者的错误(不正确)假设。

正如@Broman所说,电子邮件地址包含两个部分:local-partdomain。值得注意的是这些部分的一些事情并不是很明显:

  • local-part可以包含转义字符,甚至包含其他@字符。
  • local-part可能区分大小写,但是该特定域的邮件服务器如何区分大小写。
  • domain部分可以包含由句点(.)分隔的零个或多个标签,但实际上没有与根(零标签)或通用顶级域名相对应的MX记录(一个标签)他们自己。

因此,您可以执行一些检查,但不会拒绝与上述内容相对应的有效电子邮件地址:

  • 地址至少包含一个@
  • local-part(最右边@左侧的所有内容)都是非空的
  • domain部分(最右边的@右侧的所有内容)至少包含一个句号(同样,这不是严格正确但务实)

就是这样。正如其他人所指出的那样,最好的做法是测试该地址的可传递性。这将确立两个重要的事情:

  1. 电子邮件目前是否存在;和
  2. 用户有权访问电子邮件地址(是合法用户或所有者)
  3. 如果您在业务流程中构建电子邮件激活流程,则无需担心存在问题的复杂正则表达式。

    进一步阅读以供参考:

    RFC 5321: Simple Mail Transfer Protocol

    OWASP: Input Validation Cheat Sheet

答案 1 :(得分:5)

构建用于验证电子邮件的正则表达式可能是一个很好的有趣的练习,但一般来说,你应该在生产代码中真正避免使用它。

在您想要使用此功能的大多数情况下,只要知道电子邮件地址有效并不意味着什么。你真正想知道的是它是否是正确的电子邮件地址。验证这一点的正确方法是发送带有验证链接的邮件。

如果您使用验证链接验证了电子邮件地址,那么通常无需检查它是否是正确的电子邮件地址,因为您知道它有效。然而,它可以用于基本上检查用户是否在正确的字段中输入电子邮件地址。在这种情况下,我的建议是非常原谅。我会说只要检查它是否是现场的@就足够了。这是一个简单的检查,所有电子邮件地址都包含@。如果你想让它变得更复杂,我建议只是警告用户它可能是地址有问题,但不禁止它。

但更糟糕的是,准确验证电子邮件地址的正则表达式实际上是一个非常复杂的问题。如果你试图自己创建一个正则表达式,你几乎肯定会犯错误。值得一提的是,标准rfc5322允许在括号内进行注释。更糟糕的是,允许使用嵌套注释。标准正则表达式无法匹配嵌套模式。你需要扩展正则表达式。虽然扩展的正则表达并不罕见,但它确实说明了复杂性。即使你做对了,在新标准出现时你会更新正则表达式吗?

还有一件事,即使你100%正确,它仍然可能还不够。电子邮件地址的右侧是@和域部分左侧的本地部分。本地部分中的所有内容都应由服务器处理。当然,RFC 5322非常详细地说明了有效的本地部分是什么样的,但如果某个特定的电子邮件服务器根据rfc5322接受无效的地址会怎么样?您是否确定不希望允许特定的电子邮件地址仅因为它不遵循标准而起作用?您是否因为选择了一个不起眼的电子邮件提供商而想要失去客户的商务?

如果您确实想检查生产代码中的地址是否正确,请使用MailAddress类或类似的东西。但是,如果这真的是你想要的话,首先花点时间思考一下。如果地址不正确,请问自己地址是否有任何价值。如果答案是否定的,则不然。请改用验证链接。

话虽如此,验证输入可能是件好事。重要的是要知道你为什么这样做。使用正则表达式或(最好)类似Mailaddress类的内容验证电子邮件可以提供一些防止恶意输入的保护,例如SQL注入等。但如果这是你必须保护自己免受恶意输入的唯一方法,那么你正在做其他非常错误的事情。

答案 2 :(得分:2)

验证电子邮件地址本身并不是坏事。

使用正则表达式来验证电子邮件地址本身并不是很糟糕......尽管可以说有更好的方法来验证它们。

真正的问题是验证电子邮件地址(基于语法):

  • 不会告诉您地址是否与有效的工作邮箱相对应,并且
  • 不会告诉您它是否是正确用户(或代理人)的地址。

由于用户出于各种目的而意外(或故意)使用不正确的电子邮件地址,如果您需要知道地址是否正确,则需要其他;例如发送某种“激活”电子邮件到该地址。

因此,假设您要实施第二阶段的检查,第一阶段相对不重要。可能甚至没必要。

答案 3 :(得分:2)

  

我听说用正则表达式验证电子邮件地址是件坏事,而且它确实会造成伤害。那是为什么?

这是对的。正则表达式解决方案很有吸引力,因为电子邮件地址是结构化字符串,而正则表达式用于查找字符串中的结构。

这也是错误的解决方案,因为当您向用户询问电子邮件地址时,通常可以联系他们。

验证不正确,因为:

  • 地址可能有效,但不是用户有权访问的地址。我可以填写地址billgates@microsoft.com到任何表格,它可能会被接受为有效的电子邮件地址(免责声明:我不是比尔盖茨:)。

  • 电子邮件地址的语法非常难以正确获取(请参阅the examples here) - 通过定义自己的电子邮件验证正则表达式,您最终会拒绝有效地址,并接受无效地址。

  

我认为验证数据永远不会是件坏事。

验证数据并不错。但在这种情况下,您将在应用程序中提供一个功能,该功能在设计上是有缺陷的:

您的应用程序将您的开发人员视为验证输入,但验证是不必要的,可能是不完整的,并且在验证结束时,您不知道是否有允许您联系的地址用户。

  

可能没必要,但如果您正确执行验证,那绝不是坏事。

没有必要,这是必要的。只是正则表达式是错误的工具。

在一天结束时,检查地址对用户有效的最佳方法是该地址的唯一令牌交换:

  • 向该地址发送电子邮件,其中包含唯一的随机令牌(包含用户数据的商店令牌)
  • 在电子邮件中询问用户“点击链接/按钮”,有效地向您发送令牌。
  • 验证令牌。

答案 4 :(得分:2)

除了其他答案,我想指出我们的Regex引擎容易受到 ReDOS - 正则表达式拒绝服务攻击。攻击的基础是许多非平凡的正则表达式具有可能需要非常大量的CPU周期才能产生不匹配的输入。

即使使用小型僵尸网络,制作此类输入也可能会对网站的可用性造成麻烦。

有关详细信息“正则表达式拒绝服务(ReDOS)攻击”:https://dzone.com/articles/regular-expressions-denial

答案 5 :(得分:1)

如果您的正则表达式格式不正确,那么您可能会拒绝有效的电子邮件地址。这适用于任何"电子邮件验证"规则。

我知道一个电子邮件地址经常被不包含任何电子邮件奇怪的表格拒绝;它只是很长。它真的让它所属的人烦恼,因为@之前的部分是他们的合法名称 - 显然是电子邮件地址的选择。

这是错误地完成电子邮件验证的潜在危害的一部分:通过拒绝有效的电子邮件地址进入系统来烦扰用户。

答案 6 :(得分:1)

正则表达式无害。

使用好的电子邮件正则表达式来过滤不耐烦的虚假用户。

如果您向该人出售,可能需要与他们联系 虽然卖家不太关心电子邮件,但需要进一步验证 只是验证信用卡对他们来说已经足够了。

否则,唯一需要验证的地方是 有人想要访问您的论坛并与之互动,并且出于某种原因 你想通过向大众广告商出售他们的电子邮件获得报酬,
即使你说你不会那样做。

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

http://www.w3.org/TR/html5/forms.html#valid-e-mail-address

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

答案 7 :(得分:0)

正则表达式可能是验证电子邮件地址的最佳方法;只要您使用正确的一个。使用正则表达式检查地址后,只需检查一些其他要求(地址不要太长,并且它是有效的UTF-8)。

这是因为定义电子邮件地址形式的ABNF语法是“常规”的,这意味着可以将其准确描述为正则表达式;没有回溯,递归或任何非常规功能。

这只是了解规格的问题;但是,一旦这样做,事实证明电子邮件地址的正则表达式实际上非常简单:How to validate an email address using a regular expression?