Class: String

Inherits:
Object show all
Defined in:
lib/rubymta/base-x.rb,
lib/rubymta/extended_classes.rb

Instance Method Summary collapse

Instance Method Details

#blacklisted?(dx) ⇒ Boolean

returns true if the IP is blacklisted; otherwise false examples: barracuda = ‘b.barracudacentral.org’.blacklisted?(ip) spamhaus = ‘zen.spamhaus.org’.blacklisted?(ip)

Returns:

  • (Boolean)


103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/rubymta/extended_classes.rb', line 103

def blacklisted?(dx)
  domain = dx.split('.').reverse.join('.')+"."+self
  a = []
  Resolv::DNS.open do |dns|
    begin
      a = dns.getresources(domain, Resolv::DNS::Resource::IN::A)
    rescue Resolv::NXDomainError
      a=[]
    end
  end
  if a.size>0 then true else false end
end

#dig_aObject

returns list of IPV4 addresses, or nil (there should only be one IPV4 address)



30
31
32
33
34
35
# File 'lib/rubymta/extended_classes.rb', line 30

def dig_a
  Resolv::DNS.open do |dns|
    txts = dns.getresources(self,Resolv::DNS::Resource::IN::A).collect { |r| r.address.to_s }
    if txts.empty? then nil else txts[0] end
  end
end

#dig_aaaaObject

returns list of IPV6 addresses, or nil (there should only be one IPV6 address)



39
40
41
42
43
44
# File 'lib/rubymta/extended_classes.rb', line 39

def dig_aaaa
  Resolv::DNS.open do |dns|
    txts = dns.getresources(self,Resolv::DNS::Resource::IN::AAAA).collect { |r| r.address.to_s.downcase }
    if txts.empty? then nil else txts[0] end
  end
end

#dig_dkObject

returns a publibdomainkey, or nil (there should only be one DKIM public key)



83
84
85
86
87
88
# File 'lib/rubymta/extended_classes.rb', line 83

def dig_dk
  Resolv::DNS.open do |dns|
    txts = dns.getresources(self,Resolv::DNS::Resource::IN::TXT).collect { |r| r.strings }
    if txts.empty? then nil else txts[0][0] end
  end
end

#dig_mxObject

returns list of MX names, or nil (there may be multiple MX names for a domain) WARNING: use the #dig_mxs to get the preferences also



49
50
51
52
53
54
# File 'lib/rubymta/extended_classes.rb', line 49

def dig_mx
  Resolv::DNS.open do |dns|
    txts = dns.getresources(self,Resolv::DNS::Resource::IN::MX).collect { |r| r.exchange.to_s }
    if txts.empty? then nil else txts end
  end
end

#dig_mxsObject

returns a hash of { <preference> => [ <mx,ip>, … ] } preferences sorted in numerical order from low–>high (IOW, highest preference to lowest preference) if there is no mx, returns {} ex: “173.194.78.26”]],

20=>[["alt1.aspmx.l.google.com", "173.194.219.27"]],
30=>[["alt2.aspmx.l.google.com", "74.125.192.27"], ["alt3.aspmx.l.google.com", "74.125.141.27"]],
40=>[["alt4.aspmx.l.google.com", "64.233.190.26"]]


64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/rubymta/extended_classes.rb', line 64

def dig_mxs
  mxs = {}
  Resolv::DNS.open do |dns|
    res = dns.getresources(self,Resolv::DNS::Resource::IN::MX)
    if res.size>0
      res = res.sort {|a,b| a.preference<=>b.preference }
      res.each do |mx|
        mxs[mx.preference] ||= []
        domain = mx.exchange.to_s
        ip = domain.dig_a
        mxs[mx.preference] << [domain,ip]
      end
    end
  end
  return mxs
end

#dig_ptrObject

returns a reverse DNS hostname or nil



91
92
93
94
95
96
97
# File 'lib/rubymta/extended_classes.rb', line 91

def dig_ptr
  begin
    Resolv.new.getname(self.downcase)
  rescue Resolv::ResolvError
    nil
  end
end

#from_b(base = 62) ⇒ Object

this is used to convert numbers in the email IDs back to base 10



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# File 'lib/rubymta/base-x.rb', line 4

def from_b(base=62)
  n = 0
  self.each_char do |ch|
    n = n*base
    m = ch.ord
    case
    when m>=97
      k = m-61
    when m>=65
      k = m-55
    when m>=48
      k = m-48
    end
    n += k
  end
  return n
end

#mta_live?(port) ⇒ Boolean

opens a socket to the IP/port to see if there is an SMTP server there - returns “250 …” if the server is there, or times out in 5 seconds to prevent hanging the process

Returns:

  • (Boolean)


126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/rubymta/extended_classes.rb', line 126

def mta_live?(port)
  tcp_socket = nil
  welcome = nil
  begin
    Timeout.timeout(60) do
      begin
        tcp_socket = TCPSocket.open(self,port)
      rescue Errno::ECONNREFUSED => e
        return "421 Service not available (port closed)"
      end
      begin
        welcome = tcp_socket.gets
        return welcome if welcome[1]!='2'
        tcp_socket.write("QUIT\r\n")
        line = tcp_socket.gets
        return line if line[1]!='2'
      ensure
        tcp_socket.close if tcp_socket
      end
    end
    return "250 #{welcome.chomp[4..-1]}"
  rescue SocketError => e
    return "421 Service not available (#{e})"
  rescue Timeout::Error => e
    return "421 Service not available (#{e})"
  end
end

#utf8Object

returns a UTF-8 encoded string – be carefule using this with email: email has to be received and transported with NO changes, except the addition of extra headers at the beginning (before any DKIM headers)



119
120
121
# File 'lib/rubymta/extended_classes.rb', line 119

def utf8
  self.encode('UTF-8', 'binary', :invalid => :replace, :undef => :replace, :replace => '?')
end

#validate_plainObject

this validates a password with the base64 plaintext in an AUTH command encoded -> AGNvY29AY3phcm1haWwuY29tAG15LXBhc3N3b3Jk => [“[email protected]”, “my-password”] call UnixCrypt::SHA256.build(“my-password”) “my-password” –> “$5$BsHk6IIvndgdBmo9$iuO6WMaXzgzpGmGreV4uiH72VRGG1USNK/e5tL7P9jC” “AGNvY29AY3phcm1haWwuY29tAG15LXBhc3N3b3Jk”.validate_plain { “$5$BsHk6IIvndgdBmo9$iuO6WMaXzgzpGmGreV4uiH72VRGG1USNK/e5tL7P9jC” } => “[email protected]”, true



159
160
161
162
163
164
165
166
# File 'lib/rubymta/extended_classes.rb', line 159

def validate_plain
  # decode and split up the username and password)
  username, password = Base64::decode64(self).split("\x00")[1..-1]
  return "", false if username.nil? || password.nil?
  passwd_hash = yield(username) # get the hash
  return username, false if passwd_hash.nil?
  return username, UnixCrypt.valid?(password, passwd_hash)
end