lib/email_detected/checker.rb in email_detected-0.1.1 vs lib/email_detected/checker.rb in email_detected-0.1.2

- old
+ new

@@ -1,40 +1,39 @@ +# frozen_string_literal: true + require 'resolv' require 'net/smtp' class EmailDetected::Checker < Net::SMTP - class MailCheckStatus attr_accessor :errors def self.rcpt_responses @@rcpt_responses ||= - { - -1 => :fail, # Validation failed (non-SMTP) - 250 => :valid, # Requested mail action okay, completed - 251 => :dunno, # User not local; will forward to <forward-path> - 550 => :invalid, # Requested action not taken:, mailbox unavailable - 551 => :dunno, # User not local; please try <forward-path> - 552 => :valid, # Requested mail action aborted:, exceeded storage allocation - 553 => :invalid, # Requested action not taken:, mailbox name not allowed - 450 => :valid_fails, # Requested mail action not taken:, mailbox unavailable - 451 => :valid_fails, # Requested action aborted:, local error in processing - 452 => :valid_fails, # Requested action not taken:, insufficient system storage - 500 => :fail, # Syntax error, command unrecognised - 501 => :invalid, # Syntax error in parameters or arguments - 503 => :fail, # Bad sequence of commands - 521 => :invalid, # <domain> does not accept mail [rfc1846] - 421 => :fail, # <domain> Service not available, closing transmission channel - } + { + -1 => :fail, # Validation failed (non-SMTP) + 250 => :valid, # Requested mail action okay, completed + 251 => :dunno, # User not local; will forward to <forward-path> + 550 => :invalid, # Requested action not taken:, mailbox unavailable + 551 => :dunno, # User not local; please try <forward-path> + 552 => :valid, # Requested mail action aborted:, exceeded storage allocation + 553 => :invalid, # Requested action not taken:, mailbox name not allowed + 450 => :valid_fails, # Requested mail action not taken:, mailbox unavailable + 451 => :valid_fails, # Requested action aborted:, local error in processing + 452 => :valid_fails, # Requested action not taken:, insufficient system storage + 500 => :fail, # Syntax error, command unrecognised + 501 => :invalid, # Syntax error in parameters or arguments + 503 => :fail, # Bad sequence of commands + 521 => :invalid, # <domain> does not accept mail [rfc1846] + 421 => :fail # <domain> Service not available, closing transmission channel + } end def initialize(response_code, error = nil) - errors = Array.new - unless error.nil? - errors.push(EmailDetected::MESSAGES[response_code]) - end - @response = (self.class.rcpt_responses.has_key?(response_code) ? + errors = [] + errors.push(EmailDetected::MESSAGES[response_code]) unless error.nil? + @response = (self.class.rcpt_responses.key?(response_code) ? response_code : -1) @errors = errors end # Symbolic status of mail address verification. @@ -48,22 +47,22 @@ @@rcpt_responses[@response] end # true if verified address is known to be valid def valid? - [:valid, :valid_fails].include? self.status + %i[valid valid_fails].include? status end # true if verified address is known to be invalid def invalid? - self.status == :invalid + status == :invalid end end def self.run(addr, server = nil, decoy_from = nil) # FIXME: needs a better mail address parser - server = get_mail_server(addr[(addr.index('@')+1)..-1]) if server.nil? + server = get_mail_server(addr[(addr.index('@') + 1)..-1]) if server.nil? # This only needs to be something the receiving SMTP server # accepts. We aren't actually sending any mail. decoy_from ||= EmailDetected.config.verifier_email ret = nil @@ -71,33 +70,34 @@ EmailDetected::Checker.start(server) do |smtp| ret = smtp.check_mail_addr(addr, decoy_from) ret = MailCheckStatus.new(ret.status.to_i) end rescue Net::SMTPAuthenticationError, - Net::SMTPServerBusy, - Net::SMTPSyntaxError, - Net::SMTPFatalError, - Net::SMTPUnknownError => error - ret = MailCheckStatus.new(error.to_s[0..2].to_i, error) - rescue IOError, TimeoutError, ArgumentError => error - ret = MailCheckStatus.new(-1, error) + Net::SMTPServerBusy, + Net::SMTPSyntaxError, + Net::SMTPFatalError, + Net::SMTPUnknownError => e + ret = MailCheckStatus.new(e.to_s[0..2].to_i, e) + rescue IOError, TimeoutError, ArgumentError => e + ret = MailCheckStatus.new(-1, e) end - return ret + ret end def check_mail_addr(to_addr, decoy_from = nil) raise IOError, 'closed session' unless @socket raise ArgumentError, 'mail destination not given' if to_addr.empty? + mailfrom decoy_from rcptto to_addr end def self.get_mail_server(host) res = Resolv::DNS.new.getresources(host, Resolv::DNS::Resource::IN::MX) unless res.empty? # FIXME: should return the whole list - return res.sort {|x,y| x.preference <=> y.preference}.first.exchange.to_s + return res.min { |x, y| x.preference <=> y.preference }.exchange.to_s end + nil end - end