Module: Philiprehberger::EmailValidator::MxCheck

Defined in:
lib/philiprehberger/email_validator/mx_check.rb

Overview

MX record verification using Ruby’s built-in Resolv library.

Checks whether a domain has valid MX records, falling back to A record lookup as permitted by RFC 5321 section 5.1.

Constant Summary collapse

DEFAULT_TIMEOUT =

Default DNS timeout in seconds.

5

Class Method Summary collapse

Class Method Details

.mx_records(domain, timeout: DEFAULT_TIMEOUT) ⇒ Array<String>

Retrieve MX records for a domain.

Parameters:

  • domain (String)

    the domain to look up

  • timeout (Integer) (defaults to: DEFAULT_TIMEOUT)

    DNS query timeout in seconds

Returns:

  • (Array<String>)

    list of MX hostnames sorted by preference



46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/philiprehberger/email_validator/mx_check.rb', line 46

def mx_records(domain, timeout: DEFAULT_TIMEOUT)
  return [] if domain.nil? || domain.strip.empty?

  resolver = Resolv::DNS.new
  resolver.timeouts = timeout

  records = fetch_mx_records(resolver, domain)
  records.sort_by(&:preference).map { |r| r.exchange.to_s }
rescue Resolv::ResolvError, Resolv::ResolvTimeout
  []
ensure
  resolver&.close
end

.valid?(domain, timeout: DEFAULT_TIMEOUT) ⇒ Boolean

Check if a domain has valid MX records.

Falls back to checking A records if no MX records are found, as RFC 5321 permits mail delivery to the A record host.

Parameters:

  • domain (String)

    the domain to check

  • timeout (Integer) (defaults to: DEFAULT_TIMEOUT)

    DNS query timeout in seconds

Returns:

  • (Boolean)

    true if the domain has MX or A records



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/philiprehberger/email_validator/mx_check.rb', line 24

def valid?(domain, timeout: DEFAULT_TIMEOUT)
  return false if domain.nil? || domain.strip.empty?

  resolver = Resolv::DNS.new
  resolver.timeouts = timeout

  mx_records = fetch_mx_records(resolver, domain)
  return true unless mx_records.empty?

  a_records = fetch_a_records(resolver, domain)
  !a_records.empty?
rescue Resolv::ResolvError, Resolv::ResolvTimeout
  false
ensure
  resolver&.close
end