Skip to content

Instantly share code, notes, and snippets.

@rubiii
Created May 16, 2010 13:51
Show Gist options
  • Save rubiii/402890 to your computer and use it in GitHub Desktop.
Save rubiii/402890 to your computer and use it in GitHub Desktop.
require "active_model"
# = EmailValidator
#
# Validates whether the value of the specified attribute is a valid email address.
# Borrowed from http://github.com/dancroak/validates_email_format_of and ported to Rails 3.
#
# ==== Example
#
# class User
# include ActiveModel::Validations
#
# attr_accessor :email
# validate :email, :email => true
# end
#
# ==== Options
#
# [allow_nil] Allow nil values (default is false)
# [allow_blank] Allow blank values (default is false)
# [with] Custom email format (you should stick to the default)
class EmailValidator < ActiveModel::EachValidator
LocalPartSpecialChars = Regexp.escape('!#$%&\'*-/=?+-^_`{|}~')
LocalPartUnquoted = '(([[:alnum:]' + LocalPartSpecialChars + ']+[\.\+]+))*[[:alnum:]' + LocalPartSpecialChars + '+]+'
LocalPartQuoted = '\"(([[:alnum:]' + LocalPartSpecialChars + '\.\+]*|(\\\\[\u0001-\uFFFF]))*)\"'
EmailFormat = Regexp.new('^((' + LocalPartUnquoted + ')|(' + LocalPartQuoted + ')+)@(((\w+\-+)|(\w+\.))*\w{1,63}\.[a-z]{2,6}$)', Regexp::EXTENDED | Regexp::IGNORECASE)
def initialize(options)
super
defaults = { :allow_nil => false, :allow_blank => false, :with => EmailFormat }
@options = defaults.merge options
end
def validate_each(record, attribute, value)
value = value.to_s
# local part max is 64 chars, domain part max is 255 chars
# TODO: should this decode escaped entities before counting?
begin
domain, local = value.reverse.split("@", 2)
rescue
record.errors.add attribute, :invalid_email, :value => value
next
end
unless value =~ options[:with] and not value =~ /\.\./ and domain.length <= 255 and local.length <= 64
record.errors.add attribute, :invalid_email, :value => value
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment