Luk*_*ncl 95 email validation ruby-on-rails
你用什么来验证用户的电子邮件地址,为什么?
我一直在使用validates_email_veracity_of它实际查询MX服务器.但由于各种原因,这种情况充满了失败,主要与网络流量和可靠性有关.
我环顾四周,找不到很多人用来对电子邮件地址进行健全检查的明显事实.是否有一个维护的,相当准确的插件或宝石?
PS:请不要告诉我发送带有链接的电子邮件,看看电子邮件是否有效.我正在开发一个"发送给朋友"的功能,所以这是不切实际的.
SFE*_*ley 106
不要让它比它需要的更难.您的功能非关键; 验证只是一个基本的理智步骤来捕捉拼写错误.我会用一个简单的正则表达式来做,而不是浪费CPU周期的任何太复杂:
/\A[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]+\z/
Run Code Online (Sandbox Code Playgroud)
这是改编自http://www.regular-expressions.info/email.html - 如果你真的想知道所有的权衡,你应该阅读.如果你想要一个更正确,更复杂的完全符合RFC822的正则表达式,那也就是在那个页面上.但问题是:你不必完全正确.
如果地址通过验证,您将发送电子邮件.如果电子邮件失败,您将收到错误消息.此时你可以告诉用户"抱歉,你的朋友没有收到,你想再试一次吗?" 或者标记它以供人工审查,或者只是忽略它,或者其他什么.
如果地址确实通过验证,则这些选项与您必须处理的选项相同.因为即使您的验证是完美的并且您获得了地址存在的绝对证据,发送仍然可能失败.
验证的误报成本很低.更好的验证的好处也很低.慷慨地验证,并在发生错误时担心错误.
bal*_*and 12
我在Rails 3中为电子邮件验证创建了一个gem.我很惊讶Rails默认情况下不包含这样的东西.
http://github.com/balexand/email_validator
Bri*_*ong 10
这个项目目前似乎在github上拥有最多的观察者(对于rails中的电子邮件验证):
https://github.com/alexdunae/validates_email_format_of
来自Rails 4文档:
class EmailValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
unless value =~ /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i
record.errors[attribute] << (options[:message] || "is not an email")
end
end
end
class Person < ActiveRecord::Base
validates :email, presence: true, email: true
end
Run Code Online (Sandbox Code Playgroud)
在Rails 4中,只需添加validates :email, email:true(假设您的字段被调用email)到您的模型,然后编写一个简单(或复杂†)EmailValidator以满足您的需求.
例如: - 你的型号:
class TestUser
include Mongoid::Document
field :email, type: String
validates :email, email: true
end
Run Code Online (Sandbox Code Playgroud)
您的验证员(进入app/validators/email_validator.rb)
class EmailValidator < ActiveModel::EachValidator
EMAIL_ADDRESS_QTEXT = Regexp.new '[^\\x0d\\x22\\x5c\\x80-\\xff]', nil, 'n'
EMAIL_ADDRESS_DTEXT = Regexp.new '[^\\x0d\\x5b-\\x5d\\x80-\\xff]', nil, 'n'
EMAIL_ADDRESS_ATOM = Regexp.new '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+', nil, 'n'
EMAIL_ADDRESS_QUOTED_PAIR = Regexp.new '\\x5c[\\x00-\\x7f]', nil, 'n'
EMAIL_ADDRESS_DOMAIN_LITERAL = Regexp.new "\\x5b(?:#{EMAIL_ADDRESS_DTEXT}|#{EMAIL_ADDRESS_QUOTED_PAIR})*\\x5d", nil, 'n'
EMAIL_ADDRESS_QUOTED_STRING = Regexp.new "\\x22(?:#{EMAIL_ADDRESS_QTEXT}|#{EMAIL_ADDRESS_QUOTED_PAIR})*\\x22", nil, 'n'
EMAIL_ADDRESS_DOMAIN_REF = EMAIL_ADDRESS_ATOM
EMAIL_ADDRESS_SUB_DOMAIN = "(?:#{EMAIL_ADDRESS_DOMAIN_REF}|#{EMAIL_ADDRESS_DOMAIN_LITERAL})"
EMAIL_ADDRESS_WORD = "(?:#{EMAIL_ADDRESS_ATOM}|#{EMAIL_ADDRESS_QUOTED_STRING})"
EMAIL_ADDRESS_DOMAIN = "#{EMAIL_ADDRESS_SUB_DOMAIN}(?:\\x2e#{EMAIL_ADDRESS_SUB_DOMAIN})*"
EMAIL_ADDRESS_LOCAL_PART = "#{EMAIL_ADDRESS_WORD}(?:\\x2e#{EMAIL_ADDRESS_WORD})*"
EMAIL_ADDRESS_SPEC = "#{EMAIL_ADDRESS_LOCAL_PART}\\x40#{EMAIL_ADDRESS_DOMAIN}"
EMAIL_ADDRESS_PATTERN = Regexp.new "#{EMAIL_ADDRESS_SPEC}", nil, 'n'
EMAIL_ADDRESS_EXACT_PATTERN = Regexp.new "\\A#{EMAIL_ADDRESS_SPEC}\\z", nil, 'n'
def validate_each(record, attribute, value)
unless value =~ EMAIL_ADDRESS_EXACT_PATTERN
record.errors[attribute] << (options[:message] || 'is not a valid email')
end
end
end
Run Code Online (Sandbox Code Playgroud)
这将允许各种有效的电子邮件,包括标记的电子邮件,如"test+no_really@test.tes"等.
用rspec你的方式测试一下spec/validators/email_validator_spec.rb
require 'spec_helper'
describe "EmailValidator" do
let(:validator) { EmailValidator.new({attributes: [:email]}) }
let(:model) { double('model') }
before :each do
model.stub("errors").and_return([])
model.errors.stub('[]').and_return({})
model.errors[].stub('<<')
end
context "given an invalid email address" do
let(:invalid_email) { 'test test tes' }
it "is rejected as invalid" do
model.errors[].should_receive('<<')
validator.validate_each(model, "email", invalid_email)
end
end
context "given a simple valid address" do
let(:valid_simple_email) { 'test@test.tes' }
it "is accepted as valid" do
model.errors[].should_not_receive('<<')
validator.validate_each(model, "email", valid_simple_email)
end
end
context "given a valid tagged address" do
let(:valid_tagged_email) { 'test+thingo@test.tes' }
it "is accepted as valid" do
model.errors[].should_not_receive('<<')
validator.validate_each(model, "email", valid_tagged_email)
end
end
end
Run Code Online (Sandbox Code Playgroud)
无论如何我就是这样做的.因人而异
†正则表达就像暴力; 如果他们不工作你没有使用足够的.