module ActiveRecord
module Validations
module ClassMethods
# Validates the form of an email address and verifies it's domain by checking if there are any
# mail exchange or address servers associated with it.
#
# ==== Options
# * message
# - Changes the default error message.
# * domain_check
# - Skips server lookup unless true.
# * timeout
# - Time (in seconds) before the domain lookup is skipped. Default is 2.
# * fail_on_timeout
# - Causes validation to fail if a timeout occurs.
# * timeout_message
# - Changes the default timeout error message.
# * mx_only
# - When set, only mail exchange servers (MX) are looked up and the address server (A)
# lookup is skipped.
# * invalid_domains
# - An array of domain names that are not to be used. Useful for stuff like dodgeit.com
# and other services.
# * invalid_domain_message
# - Changes the default invalid domain error message.
#
# ==== Examples
# * validates_email_veracity_of :email, :message => 'is not correct.'
# - Changes the default error message from 'is invalid.' to 'is not correct.'
# * validates_email_veracity_of :email, :domain_check => false
# - Domain lookup is skipped.
# * validates_email_veracity_of :email, :timeout => 0.5
# - Causes the domain lookup to timeout if it does not complete within half a second.
# * validates_email_veracity_of :email, :fail_on_timeout => true, :timeout_message => 'is invalid.'
# - Causes the validation to fail on timeout and changes the error message to 'is invalid.'
# to obfuscate it.
# * validates_email_veracity_of :email, :mx_only => true
# - The validator will only check the domain for mail exchange (MX) servers, ignoring address
# servers (A) records.
# * validates_email_veracity_of :email, :invalid_domains => %w[dodgeit.com harvard.edu]
# - Any email addresses @dodgeit.com or @harvard.edu will be rejected.
def validates_email_veracity_of(*attr_names)
configuration = {
:message => 'is invalid.',
:timeout_message => 'domain is currently unreachable, try again later.',
:invalid_domain_message => 'provider is not supported, try another email address.',
:timeout => 2,
:domain_check => true,
:invalid_domains => [],
:mx_only => false,
:fail_on_timeout => false
}
configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
validates_each(attr_names, configuration) do |record, attr_name, value|
next if value.blank?
email = ValidatesEmailVeracityOf::EmailAddress.new(value)
message = :message unless email.pattern_is_valid?
message = :invalid_domain_message unless email.domain_is_valid?(configuration)
if configuration[:domain_check] && !message
message = case email.domain_has_servers?(configuration)
when nil then :timeout_message
when false then :message
end
end
record.errors.add(attr_name, configuration[message]) if message
end
end
end
end
end