Module: MailVerifier

Defined in:
lib/mail_verifier/version.rb,
lib/mail_verifier/verifier.rb,
lib/mail_verifier/exceptions.rb

Defined Under Namespace

Classes: FailureException, NoMailServerException, NotConnectedException, OutOfMailServersException

Constant Summary collapse

VERSION =
"0.1.0"

Class Method Summary collapse

Class Method Details

.close_connectionObject



62
63
64
# File 'lib/mail_verifier/verifier.rb', line 62

def close_connection
  @smtp.finish if @smtp && @smtp.started?
end

.connectObject



45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/mail_verifier/verifier.rb', line 45

def connect
  begin
    server = next_server
    raise OutOfMailServersException.new("Unable to connect to any one of mail servers for #{@dest_email}") if server.nil?
    @smtp = Net::SMTP.start server[:address], 25, @origin_domain
    return true
  rescue OutOfMailServersException => e
    raise OutOfMailServersException, e.message
  rescue => e
    retry
  end
end

.ensure_250(smtp_return) ⇒ Object



90
91
92
93
94
95
96
# File 'lib/mail_verifier/verifier.rb', line 90

def ensure_250(smtp_return)
  if smtp_return.status.to_i == 250
    return true
  else
    raise FailureException.new "Mail server responded with #{smtp_return.status} when we were expecting 250"
  end
end

.ensure_connectedObject



86
87
88
# File 'lib/mail_verifier/verifier.rb', line 86

def ensure_connected
  raise NotConnectedException.new("You have to connect first") if @smtp.nil?
end

.is_connectedObject



41
42
43
# File 'lib/mail_verifier/verifier.rb', line 41

def is_connected
  !@smtp.nil?
end

.list_mxs(domain) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/mail_verifier/verifier.rb', line 28

def list_mxs(domain)
  return [] unless domain
  mxs = []
  res = Resolv::DNS.new.getresources(domain, Resolv::DNS::Resource::IN::MX)

  raise NoMailServerException.new("#{domain} does not exist") if res == []

  res.each do |resource|
    mxs << { priority: resource.preference, address: resource.exchange.to_s }
  end
  mxs.sort_by { |mx| mx[:priority] }
end

.mailfrom(address) ⇒ Object



66
67
68
69
70
# File 'lib/mail_verifier/verifier.rb', line 66

def mailfrom(address)
  ensure_connected

  ensure_250 @smtp.mailfrom(address)
end

.next_serverObject



58
59
60
# File 'lib/mail_verifier/verifier.rb', line 58

def next_server
  @servers.shift
end

.rcptto(address) ⇒ Object



72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/mail_verifier/verifier.rb', line 72

def rcptto(address)
  ensure_connected

  begin
    ensure_250 @smtp.rcptto(address)
  rescue => e
    if e.message[/^550/]
      return false
    else
      raise FailureException.new(e.message)
    end
  end
end

.verify(origin_email, dest_email) ⇒ Object

Entry point.



8
9
10
11
12
13
14
15
16
17
18
# File 'lib/mail_verifier/verifier.rb', line 8

def verify(origin_email, dest_email)
  @origin_email  = origin_email # Some servers require a real mail as "from" to check for destination mails.
  @dest_email    = dest_email
  @dest_domain   = dest_email.split("@")[1]
  @origin_domain = @origin_email.split("@")[1]
  @servers       = list_mxs @dest_domain
  @smtp          = nil

  raise NoMailServerException.new("No mail server for #{@dest_email}") if @servers.empty?
  verify!
end

.verify!Object



20
21
22
23
24
25
26
# File 'lib/mail_verifier/verifier.rb', line 20

def verify!
  connect
  self.mailfrom @origin_email
  self.rcptto(@dest_email).tap do
    close_connection
  end
end