Class: EmailAddress::Exchanger

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/email_address/exchanger.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(host, config = {}) ⇒ Exchanger

Returns a new instance of Exchanger.



23
24
25
26
# File 'lib/email_address/exchanger.rb', line 23

def initialize(host, config={})
  @host = host
  @config = config
end

Class Method Details

.cached(host) ⇒ Object



9
10
11
12
13
14
15
16
17
18
19
20
21
# File 'lib/email_address/exchanger.rb', line 9

def self.cached(host)
  @host_cache ||= {}
  @cache_size ||= ENV['EMAIL_ADDRESS_CACHE_SIZE'].to_i || 100
  if @host_cache.has_key?(host)
    o = @host_cache.delete(host)
    @host_cache[host] = o # LRU cache, move to end
  elsif @host_cache.size >= @cache_size
    @host_cache.delete(@host_cache.keys.first)
    @host_cache[host] = new(host)
  else
    @host_cache[host] = new(host)
  end
end

Instance Method Details

#domainsObject

Returns Array of domain names for the MX’ers, used to determine the Provider



66
67
68
# File 'lib/email_address/exchanger.rb', line 66

def domains
  @_domains ||= mxers.map {|m| EmailAddress::Host.new(m.first).domain_name }.sort.uniq
end

#each(&block) ⇒ Object



28
29
30
31
32
# File 'lib/email_address/exchanger.rb', line 28

def each(&block)
  mxers.each do |m|
    yield({host:m[0], ip:m[1], priority:m[2]})
  end
end

#in_cidr?(cidr) ⇒ Boolean

Given a cidr (ip/bits) and ip address, returns true on match. Caches cidr object.

Returns:

  • (Boolean)


94
95
96
97
98
99
100
101
102
103
# File 'lib/email_address/exchanger.rb', line 94

def in_cidr?(cidr)
  c = NetAddr::CIDR.create(cidr)
  if cidr.include?(":")
    mx_ips.find { |ip| ip.include?(":") && c.matches?(ip) } ? true : false
  elsif cidr.include?(".")
    mx_ips.find { |ip| !ip.include?(":") && c.matches?(ip) } ? true : false
  else
    false
  end
end

#matches?(rules) ⇒ Boolean

Simple matcher, takes an array of CIDR addresses (ip/bits) and strings. Returns true if any MX IP matches the CIDR or host name ends in string. Ex: match?(%w(127.0.0.1/32 0:0:1/64 .yahoodns.net)) Note: Your networking stack may return IPv6 addresses instead of IPv4 when both are available. If matching on IP, be sure to include both IPv4 and IPv6 forms for matching for hosts running on IPv6 (like gmail).

Returns:

  • (Boolean)


81
82
83
84
85
86
87
88
89
90
91
# File 'lib/email_address/exchanger.rb', line 81

def matches?(rules)
  rules = Array(rules)
  rules.each do |rule|
    if rule.include?("/")
      return rule if self.in_cidr?(rule)
    else
      self.each {|mx| return rule if mx[:host].end_with?(rule) }
    end
  end
  false
end

#mx_ipsObject

Returns an array of MX IP address (String) for the given email domain



71
72
73
# File 'lib/email_address/exchanger.rb', line 71

def mx_ips
  mxers.map {|m| m[1] }
end

#mxersObject

Returns: [[“mta7.am0.yahoodns.net”, “66.94.237.139”, 1], [“mta5.am0.yahoodns.net”, “67.195.168.230”, 1], [“mta6.am0.yahoodns.net”, “98.139.54.60”, 1]] If not found, returns []



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/email_address/exchanger.rb', line 47

def mxers
  @mxers ||= Resolv::DNS.open do |dns|
    ress = dns.getresources(@host, Resolv::DNS::Resource::IN::MX)
    records = ress.map do |r|
      begin
        if r.exchange.to_s > " "
          [r.exchange.to_s, IPSocket::getaddress(r.exchange.to_s), r.preference]
        else
          nil
        end
      rescue SocketError # not found, but could also mean network not work or it could mean one record doesn't resolve an address
        nil
      end
    end
    records.compact
  end
end

#providerObject

Returns the provider name based on the MX-er host names, or nil if not matched



35
36
37
38
39
40
41
42
43
# File 'lib/email_address/exchanger.rb', line 35

def provider
  return @provider if defined? @provider
  EmailAddress::Config.providers.each do |provider, config|
    if config[:exchanger_match] && self.matches?(config[:exchanger_match])
      return @provider = provider
    end
  end
  @provider = :default
end