【问题标题】:Ruby Email validation with regex使用正则表达式进行 Ruby 电子邮件验证
【发布时间】:2014-05-24 11:38:07
【问题描述】:

我正在处理大量电子邮件。很多邮件都有错别字。我正在尝试构建一个将检查有效电子邮件的字符串。

这就是我的正则表达式。

def is_a_valid_email?(email)
  (email =~ /^(([A-Za-z0-9]*\.+*_+)|([A-Za-z0-9]+\-+)|([A-Za-z0-9]+\+)|([A-Za-z0-9]+\+))*[A-Z‌​a-z0-9]+@{1}((\w+\-+)|(\w+\.))*\w{1,63}\.[a-zA-Z]{2,4}$/i)
end

如果电子邮件带有下划线且只有一个句点,则通过。我有很多电子邮件的名称本身有一个以上的句点。我如何在正则表达式中检查它。

hello.me_1@email.com # <~~ valid
foo.bar#gmail.co.uk # <~~~ not valid
f.o.o.b.a.r@gmail.com # <~~~valid 
f...bar@gmail.com # <~~ not valid 
get_at_m.e@gmail  #<~~ valid

有人可以帮我重写我的正则表达式吗?

【问题讨论】:

标签: ruby regex validation email


【解决方案1】:

TL;DR:

归功于@joshuahunter(在下方,支持他的回答)。包括在这里,以便人们看到它。

URI::MailTo::EMAIL_REGEXP

旧 TL;DR

VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i

原答案

您似乎使事情复杂化了很多,我会简单地使用:

VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i

取自michael hartl's rails book

由于这不符合您的点要求,因此可以简单地修改如下:

VALID_EMAIL_REGEX = /\A([\w+\-]\.?)+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i

正如 CAustin 所说,还有许多其他解决方案。

编辑:

@installero 指出,对于带有连字符的子域,原始版本失败了,这个版本可以工作(不确定为什么字符类首先缺少数字和连字符)。

VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i

【讨论】:

  • 如何为email_field 添加此验证?目前,它只检查@ 的存在。我希望它也能验证. 的存在。
  • @sshahemail_field 是什么意思?此正则表达式检查电子邮件是否为 something_valid@somewhere.tld,(请参阅正则表达式第二部分中的 \. 部分。)
  • @MikeH-R 嗯,正则表达式(Michael Hartl 的)返回仅对 @ 有效。这是一封有效的电子邮件吗?
  • @Mohamad 正则表达式本身不应该只匹配 @ (尽管下面的 John Carney 可能会认为这样可以更准确地匹配电子邮件)。 + 的所有组都需要一个或多个匹配项。例如。开头的[\w+\-.]+ 将匹配aaaaaa+b.,但不匹配空字符串。见here for a demonstration
  • 'some@email.with-subdomain.com'.match(VALID_EMAIL_REGEX) => nil
【解决方案2】:

这是David Celis 撰写的一篇很棒的文章,解释了为什么您可以找到的用于验证电子邮件地址的每一个正则表达式都是错误的,包括上面 Mike 发布的那些。

来自文章:

本地字符串(电子邮件地址中位于 @) 可以包含以下字符:

    `! $ & * - = ` ^ | ~ # % ' + / ? _ { }` 

但是你猜怎么着?您可以使用 几乎任何你想要的角色,如果你通过包围它来逃避它 在引号中。例如,“看看所有这些空间!”@example.com 是 合法的邮件地址。不错。

如果你需要做一个基本的检查,最好的正则表达式就是/@/

【讨论】:

  • 猜测一下......即使电子邮件中几乎可以包含任何内容,只要其引用正确,实际上 99.99% 的电子邮件都遵循合理的标准格式,并且许多系统在收到他们的地址时会呕吐不认为是有效的(即使是)。如果您有这样的组件,那么确保电子邮件地址合理并且有效很重要 - 特别是如果它是旧系统的一部分或无法更改/更新的东西。
  • 这很公平,但如果您的电子邮件地址中有空格或美元,我不在乎您是否不能使用我的系统。我怀疑你在做的时候知道自己在做什么。
【解决方案3】:

我想书中的示例可以改进以匹配子域中带有- 的电子邮件。

VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i

例如:

> 'some@email.with-subdomain.com' =~ VALID_EMAIL_REGEX
=> 0

【讨论】:

  • 啊,我直到现在才看到你的答案,这是我添加到我的答案中的。
【解决方案4】:

这个更短更安全:

/\A[^@\s]+@[^@\s]+\z/

Devise gem 中使用了正则。 但它对这些值有一些漏洞:

  ".....@a....",
  "david.gilbertson@SOME+THING-ODD!!.com",
  "a.b@example,com",
  "a.b@example,co.de"

我更喜欢使用来自 ruby​​ 库 URI::MailTo::EMAIL_REGEXP 的正则表达式

有一个用于电子邮件验证的 gem

Email Validator

【讨论】:

  • 感谢您将我指向URI::MailTo::EMAIL_REGEXP!感觉是最好的方法,因为这可能比在代码库中的某个地方转储自定义正则表达式更好。
  • /\A[^@\s]+@[^@\s]+\z/.match?("r&lt;&lt;r@r.r.com") 返回true
【解决方案5】:

这对我很有用:

if email.match?('[a-z0-9]+[_a-z0-9\.-]*[a-z0-9]+@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})')
      puts 'matches!'
else
      puts 'it doesn\'t match!'
end

【讨论】:

    【解决方案6】:

    如今,Ruby 在其标准库中提供了电子邮件验证正则表达式。你可以在URI::MailTo 模块中找到它,它是URI::MailTo::EMAIL_REGEXP。 在 Ruby 2.4.1 中,它的计算结果为

    /\A[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])?)*\z/
    

    但我只使用常量本身。

    【讨论】:

    • 这是 3 年前写的,如果我记得,我还在使用 Ruby1.9。可能这就是我不知道的原因吧?不过,谢谢你的 1 班轮。
    • 是的,但是三年后人们仍然使用他们自定义的正则表达式来回答。无论如何,我并没有打算攻击你和其他任何人。我已经相应地改变了我的回答语气。
    • 谢谢。仅在测试正则表达式 1 小时后才发现这一点。
    【解决方案7】:

    你的确实很复杂。

    VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
    

    上面的代码应该足够了。

    为澄清起见,对上面每个表达式的解释:

    正则表达式的开始:

    /
    

    匹配字符串的开头:

    \A
    

    至少一个单词字符、加号、连字符或点:

    [\w+\-.]+
    

    文字“at 符号”:

    @
    

    文字点:

    \.
    

    至少一个字母:

    [a-z]+
    

    匹配字符串的结尾:

    \z
    

    正则表达式结束:

    /
    

    不区分大小写:

    i
    

    重新组合起来:

    /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
    

    查看Rubular,以便在编写表达式时方便地测试您的表达式。

    【讨论】:

      【解决方案8】:

      试试这个!!!

      /\[A-Z0-9._%+-\]+@\[A-Z0-9.-\]+\.\[AZ\]{2,4}/i

      仅选择电子邮件字符串

      "Robert Donhan" <bob@email.com>sadfadf
      Robert Donhan <bob@email.com>
      "Robert Donhan" abc.bob@email.comasdfadf
      Robert Donhan bob@email.comadfd
      

      【讨论】:

      • 这个正则表达式的主要问题是无法解析长的顶级域,例如 .amsterdam 和许多最近添加的域。
      【解决方案9】:

      至少从 2.2.1 开始,它就被内置到标准库中

      URI::MailTo::EMAIL_REGEXP
      

      【讨论】:

      • 'aa@aaa' =~ URI::MailTo::EMAIL_REGEXP 不适用于这种情况。
      • 如果有句点,但后面没有,正则表达式将返回 nil。经期后有事或无经期,则过去。 “此要求是对 RFC 5322 的故意违反,它为电子邮件地址定义了一种同时过于严格(在“@”字符之前)、过于模糊(在“@”字符之后)和过于宽松(允许cmets、空白字符和引用的字符串,以大多数用户不熟悉的方式)在这里实际使用。” html.spec.whatwg.org/multipage/input.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])?)+(我删除了尾随的 ? 并将其替换为 +,然后按预期工作)
      • 谢谢@Benjamin,我需要知道如何实施 Josh Hunter 的回答,但不知道比较电子邮件的正确方法。
      • @JoshuaHunter 是的,代码是正确的。但是,由于人们输入的错误太多,在现实世界中检查该代码似乎是不够的。
      【解决方案10】:

      如果您使用的是 Devise,您还可以通过以下方式使用其包含的正则表达式:

      Devise.email_regexp
      

      返回:

      /\A[^@\s]+@[^@\s]+\z/
      

      【讨论】:

        【解决方案11】:

        使用

        /\A[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])?)+\z/
        

        下面的解释。

        虽然 Joshua Hunter 的回答很好,但我认为 URI::MailTo::EMAIL_REGEXP 存在重大缺陷。

        它与导致Net::SMTPSyntaxError: 501 5.1.3 Bad recipient address syntax 错误的fred@example 匹配。

        URI::MailTo::EMAIL_REGEXP 计算结果为

        /\A[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])?)*\z/
        

        将最后一颗星改为加号会更好。

        注意:Darpan 对 Joshua Hunter 的回答的评论中指出了这一点,但我认为它应该有自己的答案以使其更加明显。

        【讨论】:

          猜你喜欢
          • 2020-07-22
          • 2014-03-03
          • 2020-11-04
          • 1970-01-01
          • 2014-04-14
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多