Skip to content

Instantly share code, notes, and snippets.

@jimsynz
Created December 19, 2011 07:37
Show Gist options
  • Save jimsynz/1495920 to your computer and use it in GitHub Desktop.
Save jimsynz/1495920 to your computer and use it in GitHub Desktop.
Validate email addresses.
class User
# pathetic
validates_length_of :email, minimum: 6 # "x@x.cc"
# minimum
validates_format_of :email, with: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,6}$/i, message: "is not a valid email adress."
# legitimate
validate :email do |user|
# MTA's will attempt delivery to MX, then AAAA, then A records if present.
local_part, domain = user.email.split('@')
if Resolver(domain, Net::DNS::ANY).answer.select { |rr| [ 'MX', 'AAAA', 'A' ].member? rr.type }.size == 0
errors[:email] = 'email domain is not valid.'
end
end
# extreme
validate :email do |user|
local_part, domain = user.email.split('@')
answers = Resolver(domain, Net::DNS::ANY).answer
# Grab all the MX's and sort them in reverse order.
servers_to_try = answers.select { |rr| rr.type == 'MX' }.sort { |a,b| b.preference <=> a.preference }.map(&:exchange)
# Next add any IPv6 hosts, if we have IPv6 connectivity.
if local_ipv6_address
servers_to_try += answers.select { |rr| rr.type == 'AAAA' }.map(&:address)
end
# Next add any IPv4 hosts.
servers_to_try += answers.select { |rr| rr.type == 'A' }.map(&:address)
accepted = false
servers_to_try.each do |server|
begin
Net::SMTP.start(server, 25) do |smtp|
smtp.open_message_stream('bot@kimonoapp.com', [ user.email ])
end
rescue Exception => e
if (e.is_a? ArgumentError) && (e.message == 'message or block is required')
accepted = true
break
end
end
end
errors[:email] = 'is undeliverable.' unless accepted == true
end
private
def local_ipv6_interface
# turn off reverse DNS resolution temporarily
orig, Socket.do_not_reverse_lookup = Socket.do_not_reverse_lookup, true
begin
UDPSocket.open(Socket::AF_INET6) do |s|
#s.connect '2404:6800:4006:802::1012', 1 # ipv6.google.com
s.connect 'ipv6.google.com', 1
s.addr.last
end
rescue
nil
ensure
Socket.do_not_reverse_lookup = orig
end
end
end
@SebastianEdwards
Copy link

Awesome, thanks!

@jimsynz
Copy link
Author

jimsynz commented Jul 17, 2012

It's okay. I should mention that this can be a bit brittle if your network connectivity is less than stellar.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment