Skip to content

Instantly share code, notes, and snippets.

@bf4
Forked from andywenk/email_address_validator.rb
Last active August 29, 2015 14:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bf4/c0a28ecfd32b87e9022e to your computer and use it in GitHub Desktop.
Save bf4/c0a28ecfd32b87e9022e to your computer and use it in GitHub Desktop.
require 'mail'
require 'resolv'
require 'net/telnet'
class EmailAddressValidator < ActiveModel::EachValidator
attr_reader :mail
def validate_each(record, attribute, value)
return if options[:allow_nil] && value.nil?
return if options[:allow_blank] && value.blank?
begin
@mail = Mail::Address.new(value)
ok = has_correct_syntax?(value)
ok &&= is_not_banned_domain?
ok &&= has_top_level_domain?
ok &&= is_valid_domain?
rescue Exception => e
ok = false
end
record.errors.add attribute, (options[:message] || :email_address) unless ok
end
private
def domain
mail.domain
end
def address
mail.address
end
def has_correct_syntax?(value)
domain && address == value
end
def is_not_banned_domain?
options[:banned_domains] ? !options[:banned_domains].include?(domain) : true
end
def has_top_level_domain?
mail.__send__(:tree).domain.dot_atom_text.elements.size > 1
end
def is_valid_domain?
has_domain_record(Resolv::DNS::Resource::IN::MX) || (has_domain_record(Resolv::DNS::Resource::IN::A) && is_port_open?)
end
def has_domain_record(type)
Resolv::DNS.open.getresources(domain, type).size > 0
end
def is_port_open?
unless (options[:no_port_check])
telnet = Net::Telnet::new(
'Host' => domain,
'Port' => '25',
'Timeout' => 5,
'Telnetmode' => false
)
telnet.close
true
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment