diff --git a/lib/validates_email_format_of.rb b/lib/validates_email_format_of.rb
index 92e5c4b..3e03e08 100644
--- a/lib/validates_email_format_of.rb
+++ b/lib/validates_email_format_of.rb
@@ -11,9 +11,10 @@ def self.load_i18n_locales
LocalPartSpecialChars = /[\!\#\$\%\&\'\*\-\/\=\?\+\^\_\`\{\|\}\~]/
- def self.validate_email_domain(email)
+ def self.validate_email_domain(email, check_mx_timeout: 3)
domain = email.to_s.downcase.match(/\@(.+)/)[1]
Resolv::DNS.open do |dns|
+ dns.timeouts = check_mx_timeout
@mx = dns.getresources(domain, Resolv::DNS::Resource::IN::MX) + dns.getresources(domain, Resolv::DNS::Resource::IN::A)
end
@mx.size > 0 ? true : false
@@ -34,6 +35,7 @@ def self.default_message
# Configuration options:
# * message - A custom error message (default is: "does not appear to be valid")
# * check_mx - Check for MX records (default is false)
+ # * check_mx_timeout - Timeout in seconds for checking MX records before a `ResolvTimeout` is raised (default is 3
# * 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 (deprecated)
# * local_length Maximum number of characters allowed in the local part (default is 64)
@@ -42,6 +44,7 @@ def self.default_message
def self.validate_email_format(email, options={})
default_options = { :message => options[:generate_message] ? ERROR_MESSAGE_I18N_KEY : default_message,
:check_mx => false,
+ :check_mx_timeout => 3,
:mx_message => options[:generate_message] ? ERROR_MX_MESSAGE_I18N_KEY : (defined?(I18n) ? I18n.t(ERROR_MX_MESSAGE_I18N_KEY, :scope => [:activemodel, :errors, :messages], :default => DEFAULT_MX_MESSAGE) : DEFAULT_MX_MESSAGE),
:domain_length => 255,
:local_length => 64,
@@ -70,7 +73,7 @@ def self.validate_email_format(email, options={})
return [ opts[:message] ] unless self.validate_local_part_syntax(local) and self.validate_domain_part_syntax(domain)
end
- if opts[:check_mx] and !self.validate_email_domain(email)
+ if opts[:check_mx] and !self.validate_email_domain(email, check_mx_timeout: opts[:check_mx_timeout])
return [ opts[:mx_message] ]
end
diff --git a/spec/validates_email_format_of_spec.rb b/spec/validates_email_format_of_spec.rb
index 667586e..d660a9c 100644
--- a/spec/validates_email_format_of_spec.rb
+++ b/spec/validates_email_format_of_spec.rb
@@ -175,12 +175,14 @@ def initialize(email)
describe "mx record" do
domain = "example.com"
email = "valid@#{domain}"
+ check_mx_timeout = 3
describe "when testing" do
let(:dns) { double(Resolv::DNS) }
let(:mx_record) { [double] }
let(:a_record) { [double] }
before(:each) do
allow(Resolv::DNS).to receive(:open).and_yield(dns)
+ expect(dns).to receive(:"timeouts=").with(3).once
allow(dns).to receive(:getresources).with(domain, Resolv::DNS::Resource::IN::MX).once.and_return(mx_record)
allow(dns).to receive(:getresources).with(domain, Resolv::DNS::Resource::IN::A).once.and_return(a_record)
end