使用正则表达式进行 Ruby 电子邮件验证

我有一个很大的电子邮件清单,我正在运行。很多邮件都有打字错误。我试图建立一个字符串,将检查有效的电子邮件。

这是我为正则表达式准备的。

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

谁能帮我重写一下正则表达式?

78581 次浏览

译者:

点击@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 的轨道书

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

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

正如柯斯汀所提到的,还有许多其他的解决方案。

编辑:

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

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

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

摘自文章:

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

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

但你猜怎么着,你可以用 几乎任何你想要的角色,如果你通过包围它来逃避它 例如,“看看这些空格!”@example.com 是一个 有效的邮箱地址,很好。

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

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

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

例如:

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

这个更短更安全:

/\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中的 regexp

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

Email Validator

这对我有好处:

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

现在,Ruby 在其标准库中提供了电子邮件验证 regexp。你可以在 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/

但我只用常数本身。

你的确很复杂。

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

以上代码应该足够了。

解释上述表达的每一个部分,以便澄清:

正则表达式的开始:

/

匹配字符串的开头:

\A

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

[\w+\-.]+

字面上的“ at sign”:

@

字面上的圆点:

\.

至少一个字母:

[a-z]+

匹配字符串的末尾:

\z

正则表达式结束:

/

不区分大小写:

i

重新组装:

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

检查 粗鲁,以便在编写表达式时方便地测试它们。

试试这个!

/\[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

至少从2.2.1开始,这个标准库就已经内置了

URI::MailTo::EMAIL_REGEXP

如果你正在使用 Devise,你也可以通过以下方式使用它们:

Devise.email_regexp

返回:

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

使用

/\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匹配。

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 在对约书亚 · 亨特的回答的评论中指出了这一点,但我认为它应该有自己的答案,使其更加明显。

接受的答案建议使用 URI::MailTo::EMAIL_REGEXP

然而 ,regexp 将 1234@1234视为一个有效的电子邮件地址,这可能是您在现实生活中不希望看到的(例如,如果您尝试向这样的地址发送电子邮件,AWS SES 将抛出异常)。

正如 Darpan 在注释中指出的那样,您只需用 +更改 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/

由于最初的 URI::MailTo regexp,虽然根据规范在技术上是有效的,但是对我们的需要是无用的,我们在 Devise 初始化程序中“修复”它。

# in config/initializers/devise.rb, put this at the beginning of the file
URI::MailTo.send(:remove_const, :EMAIL_REGEXP)
URI::MailTo.const_set(: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/)


# And then find `config.email_regexp` (it will already be there in the file) and change it to:
config.email_regexp = URI::MailTo::EMAIL_REGEXP

如果您想知道为什么这个 monkeypatch 没有放在一个单独的初始化器文件中,您必须将初始化器文件命名为 00_xxx.rb,以便在设计初始化器之前加载它。这违背了 Rails docs 的建议,实际上 暗示对于这样的情况使用一个初始化器:

如果一个初始值设定项的代码依赖于另一个初始值设定项中的代码,则可以将它们组合成单个初始值设定项。这使依赖关系更加明确,并有助于在应用程序中表现出新的概念。Rails 还支持初始化程序文件名的编号,但这可能导致文件名的改变。

控制器中使用正则表达式的 Ruby 多封电子邮件验证

emails = testcontroller@gmail.com,testregex@gmail.com,etc...
unless emails =~ /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i
flash[:error] = "Invalid emails"
else
Here send invitation and create users
end