X-Git-Url: https://git.openstreetmap.org/rails.git/blobdiff_plain/14ba9f0a37dbf491a0a125a29b50848edf6dc3fe..63862d008e85a0d492393122eddfd01f717f6bcb:/vendor/plugins/validates_email_format_of/lib/validates_email_format_of.rb?ds=inline diff --git a/vendor/plugins/validates_email_format_of/lib/validates_email_format_of.rb b/vendor/plugins/validates_email_format_of/lib/validates_email_format_of.rb index 48017e37b..78977fb5b 100644 --- a/vendor/plugins/validates_email_format_of/lib/validates_email_format_of.rb +++ b/vendor/plugins/validates_email_format_of/lib/validates_email_format_of.rb @@ -1,10 +1,52 @@ -# encoding: utf-8 - module ValidatesEmailFormatOf + require 'resolv' + LocalPartSpecialChars = Regexp.escape('!#$%&\'*-/=?+-^_`{|}~') LocalPartUnquoted = '(([[:alnum:]' + LocalPartSpecialChars + ']+[\.\+]+))*[[:alnum:]' + LocalPartSpecialChars + '+]+' - LocalPartQuoted = '\"(([[:alnum:]' + LocalPartSpecialChars + '\.\+]*|(\\\\[\u0001-\uFFFF]))*)\"' - Regex = Regexp.new('^((' + LocalPartUnquoted + ')|(' + LocalPartQuoted + ')+)@(((\w+\-+)|(\w+\.))*\w{1,63}\.[a-z]{2,6}$)', Regexp::EXTENDED | Regexp::IGNORECASE) + LocalPartQuoted = '\"(([[:alnum:]' + LocalPartSpecialChars + '\.\+]*|(\\\\[\x00-\xFF]))*)\"' + Regex = Regexp.new('^((' + LocalPartUnquoted + ')|(' + LocalPartQuoted + ')+)@(((\w+\-+[^_])|(\w+\.[^_]))*([a-z0-9-]{1,63})\.[a-z]{2,6}$)', Regexp::EXTENDED | Regexp::IGNORECASE, 'n') + + def self.validate_email_domain(email) + domain = email.match(/\@(.+)/)[1] + Resolv::DNS.open do |dns| + @mx = dns.getresources(domain, Resolv::DNS::Resource::IN::MX) + dns.getresources(domain, Resolv::DNS::Resource::IN::A) + end + @mx.size > 0 ? true : false + end + + # Validates whether the specified value is a valid email address. Returns nil if the value is valid, otherwise returns an array + # containing one or more validation error messages. + # + # Configuration options: + # * message - A custom error message (default is: "does not appear to be a valid e-mail address") + # * check_mx - Check for MX records (default is false) + # * mx_message - A custom error message when an MX record validation fails (default is: "is not routable.") + # * with The regex to use for validating the format of the email address (default is ValidatesEmailFormatOf::Regex) + def self.validate_email_format(email, options={}) + default_options = { :message => I18n.t(:invalid_email_address, :scope => [:activerecord, :errors, :messages], :default => 'does not appear to be a valid e-mail address'), + :check_mx => false, + :mx_message => I18n.t(:email_address_not_routable, :scope => [:activerecord, :errors, :messages], :default => 'is not routable'), + :with => ValidatesEmailFormatOf::Regex } + options.merge!(default_options) {|key, old, new| old} # merge the default options into the specified options, retaining all specified options + + # local part max is 64 chars, domain part max is 255 chars + # TODO: should this decode escaped entities before counting? + begin + domain, local = email.reverse.split('@', 2) + rescue + return [ options[:message] ] + end + + unless email =~ options[:with] and not email =~ /\.\./ and domain.length <= 255 and local.length <= 64 + return [ options[:message] ] + end + + if options[:check_mx] and !ValidatesEmailFormatOf::validate_email_domain(email) + return [ options[:mx_message] ] + end + + return nil # represents no validation errors + end end module ActiveRecord @@ -17,38 +59,28 @@ module ActiveRecord # end # # Configuration options: - # * message - A custom error message (default is: " does not appear to be a valid e-mail address") + # * message - A custom error message (default is: "does not appear to be a valid e-mail address") # * on - Specifies when this validation is active (default is :save, other options :create, :update) # * allow_nil - Allow nil values (default is false) # * allow_blank - Allow blank values (default is false) + # * check_mx - Check for MX records (default is false) + # * mx_message - A custom error message when an MX record validation fails (default is: "is not routable.") # * if - Specifies a method, proc or string to call to determine if the validation should # occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The # method, proc or string should return or evaluate to a true or false value. # * unless - See :if def validates_email_format_of(*attr_names) - options = { :message => ' does not appear to be a valid e-mail address', - :on => :save, + options = { :on => :save, :allow_nil => false, - :allow_blank => false, - :with => ValidatesEmailFormatOf::Regex } - + :allow_blank => false } options.update(attr_names.pop) if attr_names.last.is_a?(Hash) validates_each(attr_names, options) do |record, attr_name, value| v = 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 = v.reverse.split('@', 2) - rescue - record.errors.add(attr_name, options[:message]) - next - end - - unless v =~ options[:with] and not v =~ /\.\./ and domain.length <= 255 and local.length <= 64 - record.errors.add(attr_name, options[:message]) - end + errors = ValidatesEmailFormatOf::validate_email_format(v, options) + errors.each do |error| + record.errors.add(attr_name, error) + end unless errors.nil? end end end