internetee-registry/app/interactions/actions/email_check.rb
2021-12-27 11:55:48 +02:00

125 lines
4.2 KiB
Ruby

module Actions
class EmailCheck
attr_reader :email, :validation_eventable, :check_level
def initialize(email:, validation_eventable:, check_level: nil)
@email = email
@validation_eventable = validation_eventable
@check_level = check_level || :mx
end
def call
result = check_email(email)
save_result(result)
filtering_old_failed_records(result)
result.success ? log_success : log_failure(result)
result.success
end
private
def check_email(parsed_email)
Truemail.validate(parsed_email, with: calculate_check_level).result
end
def calculate_check_level
Rails.env.test? && check_level == 'smtp' ? :mx : check_level.to_sym
end
def filtering_old_failed_records(result)
if @check_level == "mx" && !result.success && validation_eventable.validation_events.count > 3
validation_eventable.validation_events.order!(created_at: :asc)
while validation_eventable.validation_events.count > 3
validation_eventable.validation_events.first.destroy
end
end
if @check_level == "mx" && result.success && validation_eventable.validation_events.count > 1
validation_eventable.validation_events.order!(created_at: :asc)
while validation_eventable.validation_events.count > 1
validation_eventable.validation_events.first.destroy
end
end
if @check_level == "smtp" && validation_eventable.validation_events.count > 1
validation_eventable.validation_events.order!(created_at: :asc)
while validation_eventable.validation_events.count > 1
validation_eventable.validation_events.first.destroy
end
end
end
def save_result(result)
if !result.success && @check_level == "mx"
email_domain = Mail::Address.new(@email).domain
result_validation = check_for_records_value(domain: email_domain, value: 'A')
logger.info "Validated A record for #{email_domain}. Validation result - #{result_validation}"
p "Validated A record for #{email_domain}. Validation result - #{result_validation}"
result_validation = check_for_records_value(domain: email_domain, value: 'AAAA') if result_validation.empty?
logger.info "Validated AAAA record for #{email_domain}. Validation result - #{result_validation}" if result_validation.empty?
p "Validated AAAA record for #{email_domain}. Validation result - #{result_validation}" if result_validation.empty?
result_validation.present? ? result.success = true : result.success = false
validation_eventable.validation_events.create(validation_event_attrs(result))
else
validation_eventable.validation_events.create(validation_event_attrs(result))
end
rescue ActiveRecord::RecordNotSaved
logger.info "Cannot save validation result for #{log_object_id}"
true
end
def check_for_records_value(domain:, value:)
result = nil
dns_servers = ENV['dnssec_resolver_ips'].to_s.split(',').map(&:strip)
Resolv::DNS.open({ nameserver: dns_servers }) do |dns|
dns.timeouts = ENV['a_and_aaaa_validation_timeout'].to_i || 1
ress = nil
case value
when 'A'
ress = dns.getresources domain, Resolv::DNS::Resource::IN::A
when 'AAAA'
ress = dns.getresources domain, Resolv::DNS::Resource::IN::AAAA
end
result = ress.map { |r| r.address }
end
result
end
def validation_event_attrs(result)
{
event_data: event_data(result),
event_type: ValidationEvent::EventType::TYPES[:email_validation],
success: result.success,
}
end
def logger
@logger ||= Rails.logger
end
def event_data(result)
result.to_h.merge(check_level: check_level)
end
def log_failure(result)
logger.info "Failed to validate email #{email} for the #{log_object_id}."
logger.info "Validation level #{check_level}, the result was #{result}"
end
def log_success
logger.info "Successfully validated email #{email} for the #{log_object_id}."
end
def log_object_id
"#{validation_eventable.class}: #{validation_eventable.id}"
end
end
end