From d365c6d9656f1fcd0bc2051b87025460b76c0016 Mon Sep 17 00:00:00 2001 From: oleghasjanov Date: Thu, 8 Aug 2024 11:24:00 +0300 Subject: [PATCH] added job --- app/jobs/smtp_email_check_job.rb | 13 +++ app/lib/greylist_checker.rb | 154 +++++++++++++++---------------- 2 files changed, 90 insertions(+), 77 deletions(-) create mode 100644 app/jobs/smtp_email_check_job.rb diff --git a/app/jobs/smtp_email_check_job.rb b/app/jobs/smtp_email_check_job.rb new file mode 100644 index 0000000000..5440b78d14 --- /dev/null +++ b/app/jobs/smtp_email_check_job.rb @@ -0,0 +1,13 @@ +class SmtpEmailCheckJob < ApplicationJob + def perform + contact_emails = Contact.all.pluck(:email) + + contact_emails.each do |email| + result = GreylistChecker.new(email).check + + puts '---------' + puts result + puts '---------' + end + end +end \ No newline at end of file diff --git a/app/lib/greylist_checker.rb b/app/lib/greylist_checker.rb index e5585cd6d1..58f7be7741 100644 --- a/app/lib/greylist_checker.rb +++ b/app/lib/greylist_checker.rb @@ -13,98 +13,98 @@ class GreylistChecker } def initialize(email, options = {}) - @email = email - @domain = email.split('@').last - @options = DEFAULT_OPTIONS.merge(options) - @debug = @options[:debug] - end + @email = email + @domain = email.split('@').last + @options = DEFAULT_OPTIONS.merge(options) + @debug = @options[:debug] +end - def check - mx_servers = get_mx_servers - debug_print("MX servers for #{@domain}: #{mx_servers.join(', ')}") - return { status: :error, message: "Failed to find MX servers" } if mx_servers.empty? +def check + mx_servers = get_mx_servers + debug_print("MX servers for #{@domain}: #{mx_servers.join(', ')}") + return { valid: false, status: :no_mx_record, message: "No MX records found for domain" } if mx_servers.empty? - mx_servers.each do |mx_server| - result = check_server(mx_server) - return result unless result[:status] == :greylisted - end - - { status: :greylisted, message: "All attempts resulted in greylisting" } + mx_servers.each do |mx_server| + result = check_server(mx_server) + return result unless result[:status] == :greylisted end - private + { valid: false, status: :greylisted, message: "Email greylisted by all MX servers" } +end + +private - def get_mx_servers - Resolv::DNS.open do |dns| - mx_records = dns.getresources(@domain, Resolv::DNS::Resource::IN::MX) - mx_records.sort_by(&:preference).map(&:exchange).map(&:to_s) - end - rescue => e - debug_print("Error getting MX servers: #{e.message}") - [] +def get_mx_servers + Resolv::DNS.open do |dns| + mx_records = dns.getresources(@domain, Resolv::DNS::Resource::IN::MX) + mx_records.sort_by(&:preference).map(&:exchange).map(&:to_s) end +rescue => e + debug_print("Error getting MX servers: #{e.message}") + [] +end - def check_server(mx_server) - attempts = 0 - while attempts < @options[:max_attempts] - result = smtp_check(mx_server) - debug_print("Attempt #{attempts + 1} result: #{result}") - - return result unless result[:status] == :greylisted - - attempts += 1 - if attempts < @options[:max_attempts] - debug_print("Waiting before next attempt: #{@options[:retry_delay]} seconds") - sleep @options[:retry_delay] - end +def check_server(mx_server) + attempts = 0 + while attempts < @options[:max_attempts] + result = smtp_check(mx_server) + debug_print("Attempt #{attempts + 1} result: #{result}") + + return result unless result[:status] == :greylisted + + attempts += 1 + if attempts < @options[:max_attempts] + debug_print("Waiting before next attempt: #{@options[:retry_delay]} seconds") + sleep @options[:retry_delay] end - result end + result +end - def smtp_check(mx_server) - debug_print("Starting SMTP check for server: #{mx_server}") +def smtp_check(mx_server) + debug_print("Starting SMTP check for server: #{mx_server}") + + Net::SMTP.start(mx_server, 25, @options[:helo_domain]) do |smtp| + smtp.debug_output = method(:debug_print) if @debug - Net::SMTP.start(mx_server, 25) do |smtp| - smtp.debug_output = method(:debug_print) if @debug - - debug_print("ehlo #{@options[:helo_domain]}") - smtp.ehlo(@options[:helo_domain]) - - debug_print("mail from:<#{@options[:sender_email]}>") - smtp.mailfrom(@options[:sender_email]) - - debug_print("rcpt to:<#{@email}>") - begin - response = smtp.rcptto(@email) - debug_print(response.message) - if response.success? - return { status: :success, message: "Email accepted" } - else - code = response.status.to_s[0..2] - if GREYLIST_CODES.include?(code) - return { status: :greylisted, message: "Greylisting detected: #{response.message}" } - else - return { status: :invalid, message: "Address rejected: #{response.message}" } - end - end - rescue Net::SMTPFatalError => e - debug_print("Received SMTP fatal error: #{e.message}") - return { status: :invalid, message: "Address rejected: #{e.message}" } - rescue Net::SMTPServerBusy => e - debug_print("Received SMTP Server Busy error: #{e.message}") - if GREYLIST_CODES.any? { |code| e.message.start_with?(code) } - return { status: :greylisted, message: "Greylisting detected: #{e.message}" } + debug_print("EHLO #{@options[:helo_domain]}") + smtp.ehlo(@options[:helo_domain]) + + debug_print("MAIL FROM:<#{@options[:sender_email]}>") + smtp.mailfrom(@options[:sender_email]) + + debug_print("RCPT TO:<#{@email}>") + begin + response = smtp.rcptto(@email) + debug_print(response.message) + if response.success? + return { valid: true, status: :success, message: "Email address is valid" } + else + code = response.status.to_s[0..2] + if GREYLIST_CODES.include?(code) + return { valid: false, status: :greylisted, message: "Email greylisted: #{response.message}" } else - return { status: :error, message: "Temporary server error: #{e.message}" } + return { valid: false, status: :invalid, message: "Email address is invalid: #{response.message}" } end end + rescue Net::SMTPFatalError => e + debug_print("Received SMTP fatal error: #{e.message}") + return { valid: false, status: :invalid, message: "Email address is invalid: #{e.message}" } + rescue Net::SMTPServerBusy => e + debug_print("Received SMTP Server Busy error: #{e.message}") + if GREYLIST_CODES.any? { |code| e.message.start_with?(code) } + return { valid: false, status: :greylisted, message: "Email greylisted: #{e.message}" } + else + return { valid: false, status: :error, message: "Temporary server error: #{e.message}" } + end end - rescue => e - debug_print("Error during SMTP check: #{e.class} - #{e.message}") - { status: :error, message: "Error connecting to SMTP server: #{e.message}" } end +rescue => e + debug_print("Error during SMTP check: #{e.class} - #{e.message}") + { valid: false, status: :error, message: "Error connecting to SMTP server: #{e.message}" } +end - def debug_print(message) - puts message if @debug - end +def debug_print(message) + puts message if @debug +end end