@ -4,22 +4,38 @@ require 'resolv'
class EmailMxValidator < ActiveModel :: Validator
class EmailMxValidator < ActiveModel :: Validator
def validate ( user )
def validate ( user )
user . errors . add ( :email , I18n . t ( 'users.invalid_email' ) ) if invalid_mx? ( user . email )
domain = get_domain ( user . email )
if domain . nil?
user . errors . add ( :email , I18n . t ( 'users.invalid_email' ) )
else
ips , hostnames = resolve_mx ( domain )
if ips . empty?
user . errors . add ( :email , I18n . t ( 'users.invalid_email_mx' ) )
elsif on_blacklist? ( hostnames + ips )
user . errors . add ( :email , I18n . t ( 'users.blocked_email_provider' ) )
end
end
end
end
private
private
def invalid_mx? ( value )
def get_doma in( value )
_ , domain = value . split ( '@' , 2 )
_ , domain = value . split ( '@' , 2 )
return true if domain . nil?
return nil if domain . nil?
TagManager . instance . normalize_domain ( domain )
rescue Addressable :: URI :: InvalidURIError
nil
end
domain = TagManager . instance . normalize_domain ( domain )
def resolve_mx ( domain )
hostnames = [ ]
hostnames = [ ]
ips = [ ]
ips = [ ]
Resolv :: DNS . open do | dns |
Resolv :: DNS . open do | dns |
dns . timeouts = 1
dns . timeouts = 5
hostnames = dns . getresources ( domain , Resolv :: DNS :: Resource :: IN :: MX ) . to_a . map { | e | e . exchange . to_s }
hostnames = dns . getresources ( domain , Resolv :: DNS :: Resource :: IN :: MX ) . to_a . map { | e | e . exchange . to_s }
@ -29,9 +45,7 @@ class EmailMxValidator < ActiveModel::Validator
end
end
end
end
ips . empty? || on_blacklist? ( hostnames + ips )
[ ips , hostnames ]
rescue Addressable :: URI :: InvalidURIError
true
end
end
def on_blacklist? ( values )
def on_blacklist? ( values )