# frozen_string_literal: true module Truemail module Validate class Smtp < Truemail::Validate::Base ERROR = 'smtp error' attr_reader :smtp_results def initialize(result) super(result) @smtp_results = [] end def run return false unless Truemail::Validate::MxBlacklist.check(result) establish_smtp_connection return true if success(success_response?) result.smtp_debug = smtp_results return true if success(not_includes_user_not_found_errors?) add_error(Truemail::Validate::Smtp::ERROR) false end private def fail_fast? configuration.smtp_fail_fast end def filtered_mail_servers_by_fail_fast_scenario fail_fast? ? mail_servers.first(1) : mail_servers end def attempts @attempts ||= begin return {} if fail_fast? || !mail_servers.one? { attempts: configuration.connection_attempts } # attempts should used for case with one mail server only end end def request smtp_results.last end def rcptto_error request.response.errors[:rcptto] end def establish_smtp_connection filtered_mail_servers_by_fail_fast_scenario.each do |mail_server| smtp_results << Truemail::Validate::Smtp::Request.new( configuration: configuration, host: mail_server, email: result.punycode_email, **attempts ) next unless request.check_port request.run || rcptto_error ? break : next end end def success_response? smtp_results.map(&:response).any?(&:rcptto) end def not_includes_user_not_found_errors? return false unless configuration.smtp_safe_check result.smtp_debug.map { |request| request.response.errors }.all? do |errors| next true unless errors.key?(:rcptto) errors.slice(:rcptto).values.none? do |error| configuration.smtp_error_body_pattern.match?(error) end end end end end end