diff --git a/app/interactions/actions/a_and_aaaa_email_validation.rb b/app/interactions/actions/a_and_aaaa_email_validation.rb index f0ec569f4..ab769cc9d 100644 --- a/app/interactions/actions/a_and_aaaa_email_validation.rb +++ b/app/interactions/actions/a_and_aaaa_email_validation.rb @@ -16,19 +16,28 @@ module Actions end def resolve_a_and_aaaa_records(dns_servers:, email_domain:, value:) - Resolv::DNS.open({ nameserver: dns_servers }) do |dns| - dns.timeouts = ENV['a_and_aaaa_validation_timeout'].to_i || 1 - ress = nil + Resolv::DNS.open(nameserver: dns_servers, ndots: 1, search: []) do |dns| + dns.timeouts = (ENV['a_and_aaaa_validation_timeout'] || 1).to_i case value when 'A' - ress = dns.getresources email_domain, Resolv::DNS::Resource::IN::A + resolve_a_records(dns: dns, domain: email_domain) when 'AAAA' - ress = dns.getresources email_domain, Resolv::DNS::Resource::IN::AAAA + resolve_aaaa_records(dns: dns, domain: email_domain) + else + [] end - - ress.map(&:address) end end + + def resolve_a_records(dns:, domain:) + resources = dns.getresources(domain, Resolv::DNS::Resource::IN::A) + resources.map(&:address) + end + + def resolve_aaaa_records(dns:, domain:) + resources = dns.getresources(domain, Resolv::DNS::Resource::IN::AAAA) + resources.map(&:address) + end end end diff --git a/app/interactions/actions/email_check.rb b/app/interactions/actions/email_check.rb index 67c049cb3..4df58753e 100644 --- a/app/interactions/actions/email_check.rb +++ b/app/interactions/actions/email_check.rb @@ -2,6 +2,8 @@ module Actions class EmailCheck attr_reader :email, :validation_eventable, :check_level + SAVE_RESULTS_BATCH_SIZE = 500 + def initialize(email:, validation_eventable:, check_level: nil) @email = email @validation_eventable = validation_eventable @@ -11,7 +13,7 @@ module Actions def call result = check_email(email) save_result(result) - result.success ? log_success : log_failure(result) + handle_logging(result) result.success end @@ -22,55 +24,63 @@ module Actions end def calculate_check_level - Rails.env.test? && check_level == 'smtp' ? :mx : check_level.to_sym + check_level_sym = check_level.to_sym + return :mx if Rails.env.test? && check_level_sym == :smtp + + check_level_sym end - def filtering_old_failed_records(result, contact) + def filter_old_failed_records(result, contact) ValidationEvent::INVALID_EVENTS_COUNT_BY_LEVEL.each do |level, limit| handle_failed_records(contact: contact, check_level: level, limit: limit, success: result.success) end end def handle_failed_records(contact:, check_level:, limit:, success:) - if @check_level.to_sym == check_level && !success && contact.validation_events.count > limit - contact.validation_events.order!(created_at: :asc) - while contact.validation_events.count > limit - contact.validation_events.first.destroy - end - end + return unless @check_level.to_sym == check_level.to_sym && !success + + excess_events_count = contact.validation_events.count - limit + return unless excess_events_count.positive? + + contact.validation_events.order(created_at: :asc).limit(excess_events_count).destroy_all end - def filtering_old_records(contact:, success:) - return unless success - - contact.validation_events.destroy_all + def filter_old_records(contact:, success:) + contact.validation_events.destroy_all if success end def save_result(result) contacts = Contact.where(email: email) - if !result.success && @check_level == 'mx' - result_validation = Actions::AAndAaaaEmailValidation.call(email: @email, value: 'A') - output_a_and_aaaa_validation_results(email: @email, result: result_validation, type: 'A') - - result_validation = Actions::AAndAaaaEmailValidation.call(email: @email, value: 'AAAA') if result_validation.empty? - output_a_and_aaaa_validation_results(email: @email, result: result_validation, type: 'AAAA') - result.success = result_validation.present? - end + handle_mx_validation(result) if !result.success && @check_level == 'mx' result.configuration = nil - contacts.find_in_batches(batch_size: 500) do |contact_batches| + contacts.find_in_batches(batch_size: SAVE_RESULTS_BATCH_SIZE) do |contact_batches| contact_batches.each do |contact| - # methods should be in this order! - filtering_old_records(contact: contact, success: result.success) - contact.validation_events.create(validation_event_attrs(result)) - filtering_old_failed_records(result, contact) + handle_saving_result(contact, result) end end rescue ActiveRecord::RecordNotSaved - logger.info "Cannot save validation result for #{log_object_id}" - true + logger.info "Cannot save validation result for #{log_object_id}" and return true + end + + def handle_mx_validation(result) + result_validation = Actions::AAndAaaaEmailValidation.call(email: email, value: 'A') + output_a_and_aaaa_validation_results(email: email, result: result_validation, type: 'A') + + if result_validation.empty? + result_validation = Actions::AAndAaaaEmailValidation.call(email: email, value: 'AAAA') + output_a_and_aaaa_validation_results(email: email, result: result_validation, type: 'AAAA') + end + + result.success = result_validation.present? + end + + def handle_saving_result(contact, result) + filter_old_records(contact: contact, success: result.success) + contact.validation_events.create!(validation_event_attrs(result)) + filter_old_failed_records(result, contact) end def output_a_and_aaaa_validation_results(email:, result:, type:) @@ -79,27 +89,6 @@ module Actions logger.info "Validated #{type} record for #{email}. Validation result - #{result}" 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| - timeouts = ENV['a_and_aaaa_validation_timeout'] || '1' - dns.timeouts = timeouts.to_i - 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(&:address) - end - - result - end - def validation_event_attrs(result) { event_data: event_data(result), @@ -116,13 +105,13 @@ module Actions 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}." + def handle_logging(result) + if result.success + logger.info "Successfully validated email #{email} for #{log_object_id}." + else + logger.info "Failed to validate email #{email} for #{log_object_id}." + logger.info "Validation level #{check_level}, the result was #{result}" + end end def log_object_id diff --git a/app/interactions/domains/force_delete_lift/base.rb b/app/interactions/domains/force_delete_lift/base.rb index 867194d3b..eb6b41024 100644 --- a/app/interactions/domains/force_delete_lift/base.rb +++ b/app/interactions/domains/force_delete_lift/base.rb @@ -16,25 +16,26 @@ module Domains end def force_delete_condition(domain) - domain.force_delete_scheduled? && + force_delete_scheduled?(domain) && template_of_invalid_email?(domain) && contact_emails_valid?(domain) && bounces_absent?(domain) end + def force_delete_scheduled?(domain) + domain.force_delete_scheduled? + end + def template_of_invalid_email?(domain) domain.template_name == 'invalid_email' end def contact_emails_valid?(domain) - flag = nil - domain.contacts.each do |c| - flag = c.need_to_lift_force_delete? - return flag unless flag + return false unless c.need_to_lift_force_delete? end - flag && domain.registrant.need_to_lift_force_delete? + domain.registrant.need_to_lift_force_delete? end def bounces_absent?(domain) diff --git a/app/jobs/check_force_delete_lift.rb b/app/jobs/check_force_delete_lift.rb index 524c4bcdc..18c276056 100644 --- a/app/jobs/check_force_delete_lift.rb +++ b/app/jobs/check_force_delete_lift.rb @@ -2,20 +2,31 @@ class CheckForceDeleteLift < ApplicationJob queue_as :default def perform - domains = Domain.where("(status_notes->'serverForceDelete') is not null") - .select { |d| d.registrant.need_to_lift_force_delete? } + domains = find_domains_to_lift_force_delete handle_refresh_status(domains) if domains.present? - domains = (domains + Domain.where("force_delete_data->'template_name' = ?", 'invalid_email') - .where("force_delete_data->'force_delete_type' = ?", 'soft')).uniq - domains.each do |domain| + domains_to_process = find_domains_to_process(domains) + + domains_to_process.each do |domain| Domains::ForceDeleteLift::Base.run(domain: domain) end end private + def find_domains_to_lift_force_delete + Domain.where("'#{DomainStatus::FORCE_DELETE}' = ANY (statuses)") + .select { |d| d.registrant.need_to_lift_force_delete? } + end + + def find_domains_to_process(domains) + force_delete_template_domains = Domain.where("force_delete_data->'template_name' = ?", 'invalid_email') + .where("force_delete_data->'force_delete_type' = ?", 'soft') + + (domains + force_delete_template_domains).uniq + end + def handle_refresh_status(domains) domains.each do |domain| registrant = domain.registrant diff --git a/app/jobs/verify_emails_job.rb b/app/jobs/verify_emails_job.rb index 441a46569..3410ba7a5 100644 --- a/app/jobs/verify_emails_job.rb +++ b/app/jobs/verify_emails_job.rb @@ -4,18 +4,16 @@ class VerifyEmailsJob < ApplicationJob def perform(email:, check_level: 'mx') contact = Contact.find_by(email: email) - return Rails.logger.info "No found #{email} contact" if contact.nil? + return logger.info "Contact #{email} not found!" if contact.nil? - return unless filter_check_level(contact) + return unless need_to_verify?(contact) validate_check_level(check_level) - action = Actions::EmailCheck.new(email: contact.email, - validation_eventable: contact, - check_level: check_level) - action.call + + logger.info "Trying to verify contact email #{email} with check_level #{check_level}" + contact.verify_email(check_level: check_level) rescue StandardError => e - logger.error e.message - raise e + handle_error(e) end private @@ -26,6 +24,16 @@ class VerifyEmailsJob < ApplicationJob raise StandardError, "Check level #{check_level} is invalid" end + def need_to_verify?(contact) + return true unless contact.validation_events.any? + + last_validation = contact.validation_events.last + + return true if last_validation.successful? && last_validation.created_at < validation_expiry_date + + last_validation.failed? && last_validation.event_data['check_level'] == 'regex' ? false : true + end + def logger @logger ||= Rails.logger end @@ -34,12 +42,12 @@ class VerifyEmailsJob < ApplicationJob ValidationEvent::VALID_CHECK_LEVELS end - def filter_check_level(contact) - return true unless contact.validation_events.exists? + def validation_expiry_date + Time.zone.now - ValidationEvent::VALIDATION_PERIOD + end - data = contact.validation_events.order(created_at: :asc).last - return true if data.successful? && data.created_at < (Time.zone.now - ValidationEvent::VALIDATION_PERIOD) - - !(data.failed? && data.event_data['check_level'] == 'regex') + def handle_error(error) + logger.error error.message + raise error end end diff --git a/app/models/concerns/email_verifable.rb b/app/models/concerns/email_verifable.rb index 2d2191d8f..dec2582af 100644 --- a/app/models/concerns/email_verifable.rb +++ b/app/models/concerns/email_verifable.rb @@ -16,21 +16,19 @@ module EmailVerifable end def need_to_start_force_delete? - flag = false - ValidationEvent::INVALID_EVENTS_COUNT_BY_LEVEL.each do |level, count| - flag = true if validation_events.count >= count && validate_email_data(level: level, count: count) + ValidationEvent::INVALID_EVENTS_COUNT_BY_LEVEL.any? do |level, count| + validation_events.count >= count && validate_email_data(level: level, count: count) end - - flag end def need_to_lift_force_delete? - validation_events.failed.empty? || - ValidationEvent::REDEEM_EVENTS_COUNT_BY_LEVEL.any? do |level, count| - validation_events.order(created_at: :desc).limit(count).all? do |event| - event.check_level == level.to_s && event.successful? - end - end + return true if validation_events.failed.empty? + + ValidationEvent::REDEEM_EVENTS_COUNT_BY_LEVEL.any? do |level, count| + validation_events.order(created_at: :desc) + .limit(count) + .all? { |event| event.check_level == level.to_s && event.successful? } + end end def correct_email_format diff --git a/lib/tasks/verify_email.rake b/lib/tasks/verify_email.rake index 8aa5037a5..9aa28612e 100644 --- a/lib/tasks/verify_email.rake +++ b/lib/tasks/verify_email.rake @@ -3,12 +3,13 @@ require 'rake_option_parser_boilerplate' require 'syslog/logger' require 'active_record' +SPAM_PROTECT_TIMEOUT = 30.seconds + namespace :verify_email do # bundle exec rake verify_email:check_all -- --check_level=mx --spam_protect=true # bundle exec rake verify_email:check_all -- -dshop.test -cmx -strue desc 'Starts verifying email jobs with optional check level and spam protection' task check_all: :environment do - SPAM_PROTECT_TIMEOUT = 30.seconds options = { domain_name: nil, check_level: 'mx', @@ -18,48 +19,48 @@ namespace :verify_email do options = RakeOptionParserBoilerplate.process_args(options: options, banner: banner, hash: opts_hash) + ValidationEvent.old_records.destroy_all email_contacts = prepare_contacts(options) - email_contacts.each do |email| - VerifyEmailsJob.set(wait_until: spam_protect_timeout(options)) - .perform_later(email: email, check_level: check_level(options)) - end + enqueue_email_verification(email_contacts, options) end end -def check_level(options) - options[:check_level] -end - -def spam_protect(options) - options[:spam_protect] +def enqueue_email_verification(email_contacts, options) + email_contacts.each do |email| + VerifyEmailsJob.set(wait_until: spam_protect_timeout(options)) + .perform_later(email: email, check_level: options[:check_level]) + end end def spam_protect_timeout(options) - spam_protect(options) ? 0.seconds : SPAM_PROTECT_TIMEOUT + options[:spam_protect] ? 0.seconds : SPAM_PROTECT_TIMEOUT end def prepare_contacts(options) if options[:domain_name].present? contacts_by_domain(options[:domain_name]) else - time = Time.zone.now - ValidationEvent::VALIDATION_PERIOD - validation_events_ids = ValidationEvent.where('created_at > ?', time).distinct.pluck(:validation_eventable_id) - - contacts_emails = Contact.where.not(id: validation_events_ids).pluck(:email) - (contacts_emails + failed_email_contacts).uniq + unvalidated_and_failed_contacts_emails end end -def failed_email_contacts - failed_contacts = [] +def unvalidated_and_failed_contacts_emails + time = Time.zone.now - ValidationEvent::VALIDATION_PERIOD + validation_events_ids = ValidationEvent.where('created_at >= ?', time) + .distinct.pluck(:validation_eventable_id) + unvalidated_contacts_emails = Contact.where.not(id: validation_events_ids).pluck(:email) + (unvalidated_contacts_emails + failed_contacts_emails).uniq +end + +def failed_contacts_emails(emails: []) failed_validations_ids = ValidationEvent.failed.distinct.pluck(:validation_eventable_id) - contacts = Contact.where(id: failed_validations_ids).includes(:validation_events) - contacts.find_each(batch_size: 10_000) do |contact| - failed_contacts << contact.email + + Contact.where(id: failed_validations_ids).find_each(batch_size: 10_000) do |contact| + emails << contact.email end - failed_contacts.uniq + emails.uniq end def contacts_by_domain(domain_name) diff --git a/test/interactions/email_check_test.rb b/test/interactions/email_check_test.rb index 0c704ba72..e3b1a8a17 100644 --- a/test/interactions/email_check_test.rb +++ b/test/interactions/email_check_test.rb @@ -1,7 +1,6 @@ require 'test_helper' class EmailCheckTest < ActiveSupport::TestCase - setup do WebMock.disable_net_connect! @@ -9,104 +8,67 @@ class EmailCheckTest < ActiveSupport::TestCase end def test_invalid_email_in_mx_level_with_a_and_aaaa_records - trumail_results = OpenStruct.new(success: false, - email: @contact.email, - domain: "box.tests", - errors: {:mx=>"target host(s) not found"}, - ) - - Spy.on_instance_method(Actions::EmailCheck, :check_email).and_return(trumail_results) + Spy.on_instance_method(Actions::EmailCheck, :check_email).and_return(trumail_result) Spy.on_instance_method(Actions::AAndAaaaEmailValidation, :call).and_return([true]) - action = Actions::EmailCheck.new(email: @contact.email, - validation_eventable: @contact, - check_level: 'mx') - action.call + Actions::EmailCheck.new(email: @contact.email, + validation_eventable: @contact, + check_level: 'mx').call assert_equal @contact.validation_events.count, 1 assert @contact.validation_events.last.success end def test_invalid_email_in_mx_level_with_empty_a_and_aaaa_records - trumail_results = OpenStruct.new(success: false, - email: @contact.email, - domain: "box.tests", - errors: {:mx=>"target host(s) not found"}, - ) - - Spy.on_instance_method(Actions::EmailCheck, :check_email).and_return(trumail_results) + Spy.on_instance_method(Actions::EmailCheck, :check_email).and_return(trumail_result) Spy.on_instance_method(Actions::AAndAaaaEmailValidation, :call).and_return([]) - action = Actions::EmailCheck.new(email: @contact.email, - validation_eventable: @contact, - check_level: 'mx') - action.call + Actions::EmailCheck.new(email: @contact.email, + validation_eventable: @contact, + check_level: 'mx').call assert_equal @contact.validation_events.count, 1 refute @contact.validation_events.last.success end - def test_should_remove_invalid_validation_record_if_there_count_more_than_three - trumail_results = OpenStruct.new(success: false, - email: @contact.email, - domain: "box.tests", - errors: {:mx=>"target host(s) not found"}, - ) - - Spy.on_instance_method(Actions::EmailCheck, :check_email).and_return(trumail_results) + def test_should_remove_invalid_validation_records_if_there_count_more_than_three + Spy.on_instance_method(Actions::EmailCheck, :check_email).and_return(trumail_result) Spy.on_instance_method(Actions::AAndAaaaEmailValidation, :call).and_return([]) action = Actions::EmailCheck.new(email: @contact.email, validation_eventable: @contact, check_level: 'mx') - 3.times do - action.call - end + 3.times { action.call } assert_equal @contact.validation_events.count, 3 refute @contact.validation_events.last.success - 3.times do - action.call - end + 3.times { action.call } assert_equal @contact.validation_events.count, 3 refute @contact.validation_events.last.success end def test_should_remove_valid_validation_record_if_there_count_more_than_one - trumail_results = OpenStruct.new(success: false, - email: @contact.email, - domain: "box.tests", - errors: {:mx=>"target host(s) not found"}, - ) - - Spy.on_instance_method(Actions::EmailCheck, :check_email).and_return(trumail_results) + Spy.on_instance_method(Actions::EmailCheck, :check_email).and_return(trumail_result) Spy.on_instance_method(Actions::AAndAaaaEmailValidation, :call).and_return([true]) action = Actions::EmailCheck.new(email: @contact.email, validation_eventable: @contact, check_level: 'mx') - 3.times do - action.call - end + 3.times { action.call } assert_equal @contact.validation_events.count, 1 assert @contact.validation_events.last.success end def test_should_remove_old_record_if_validation_pass_the_limit - trumail_results = OpenStruct.new(success: false, - email: @contact.email, - domain: "box.tests", - errors: {:mx=>"target host(s) not found"}) - action = Actions::EmailCheck.new(email: @contact.email, validation_eventable: @contact, check_level: 'mx') - action.stub :check_email, trumail_results do + action.stub :check_email, trumail_result do 4.times do action.call end @@ -119,17 +81,13 @@ class EmailCheckTest < ActiveSupport::TestCase contact_two = contacts(:william) contact_two.update(email: @contact.email) contact_two.reload - trumail_results = OpenStruct.new(success: false, - email: @contact.email, - domain: "box.tests", - errors: {:mx=>"target host(s) not found"}) action = Actions::EmailCheck.new(email: @contact.email, validation_eventable: @contact, check_level: 'mx') - action.stub :check_email, trumail_results do - 4.times do + action.stub :check_email, trumail_result do + 4.times do action.call end end @@ -137,4 +95,13 @@ class EmailCheckTest < ActiveSupport::TestCase assert_equal @contact.validation_events.count, 3 assert_equal contact_two.validation_events.count, 3 end + + private + + def trumail_result + OpenStruct.new(success: false, + email: @contact.email, + domain: 'box.tests', + errors: { mx: 'target host(s) not found' }) + end end diff --git a/test/models/domain/force_delete_test.rb b/test/models/domain/force_delete_test.rb index 2aeca4dd0..5ad6f7503 100644 --- a/test/models/domain/force_delete_test.rb +++ b/test/models/domain/force_delete_test.rb @@ -82,7 +82,7 @@ class ForceDeleteTest < ActionMailer::TestCase statuses_to_be_added = [ DomainStatus::FORCE_DELETE, DomainStatus::SERVER_RENEW_PROHIBITED, - DomainStatus::SERVER_TRANSFER_PROHIBITED + DomainStatus::SERVER_TRANSFER_PROHIBITED, ] @domain.schedule_force_delete(type: :soft) @@ -94,7 +94,7 @@ class ForceDeleteTest < ActionMailer::TestCase statuses_to_be_added = [ DomainStatus::FORCE_DELETE, DomainStatus::SERVER_RENEW_PROHIBITED, - DomainStatus::SERVER_TRANSFER_PROHIBITED + DomainStatus::SERVER_TRANSFER_PROHIBITED, ] @domain.schedule_force_delete(type: :fast_track) @@ -104,7 +104,7 @@ class ForceDeleteTest < ActionMailer::TestCase def test_scheduling_force_delete_allows_domain_deletion statuses_to_be_removed = [ - DomainStatus::CLIENT_DELETE_PROHIBITED + DomainStatus::CLIENT_DELETE_PROHIBITED, ] @domain.statuses = statuses_to_be_removed + %w[other-status] @@ -119,7 +119,7 @@ class ForceDeleteTest < ActionMailer::TestCase DomainStatus::PENDING_UPDATE, DomainStatus::PENDING_TRANSFER, DomainStatus::PENDING_RENEW, - DomainStatus::PENDING_CREATE + DomainStatus::PENDING_CREATE, ] @domain.statuses = statuses_to_be_removed + %w[other-status] @@ -169,7 +169,7 @@ class ForceDeleteTest < ActionMailer::TestCase statuses = [ DomainStatus::FORCE_DELETE, DomainStatus::SERVER_RENEW_PROHIBITED, - DomainStatus::SERVER_TRANSFER_PROHIBITED + DomainStatus::SERVER_TRANSFER_PROHIBITED, ] @domain.statuses = @domain.statuses + statuses @domain.save! @@ -196,7 +196,7 @@ class ForceDeleteTest < ActionMailer::TestCase def test_cancelling_force_delete_keeps_previous_statuses statuses = [ DomainStatus::SERVER_RENEW_PROHIBITED, - DomainStatus::SERVER_TRANSFER_PROHIBITED + DomainStatus::SERVER_TRANSFER_PROHIBITED, ] @domain.statuses = statuses @@ -441,8 +441,8 @@ class ForceDeleteTest < ActionMailer::TestCase travel_to Time.zone.parse('2010-07-05') email = '`@internet2.ee' - invalid_email = '`@internet.ee' - asserted_text = "Invalid email: #{invalid_email}" + # invalid_email = '`@internet.ee' + # asserted_text = "Invalid email: #{invalid_email}" Truemail.configure.default_validation_type = :regex diff --git a/test/tasks/emails/verify_email_task_test.rb b/test/tasks/emails/verify_email_task_test.rb index 256bc0fdd..e7540cb35 100644 --- a/test/tasks/emails/verify_email_task_test.rb +++ b/test/tasks/emails/verify_email_task_test.rb @@ -1,10 +1,10 @@ require 'test_helper' class VerifyEmailTaskTest < ActiveJob::TestCase - def setup @contact = contacts(:john) @invalid_contact = contacts(:invalid_email) + @registrar = registrars(:bestnames) @default_whitelist = Truemail.configure.whitelisted_domains @default_blacklist = Truemail.configure.blacklisted_domains @@ -31,89 +31,58 @@ class VerifyEmailTaskTest < ActiveJob::TestCase [domain(@invalid_contact.email)].reject(&:blank?) end - # def test_should_be_verified_duplicate_emails - # william = Contact.where(email: "william@inbox.test").count - # - # assert_equal william, 2 - # assert_equal Contact.all.count, 9 - # run_task - # assert_equal ValidationEvent.count, Contact.count - 1 - # end + def test_should_skip_duplicate_emails + william_contacts_count = Contact.where(email: 'william@inbox.test').count - # def test_should_not_affect_to_successfully_verified_emails - # assert_equal ValidationEvent.count, 0 - # run_task - # assert_equal ValidationEvent.count, Contact.count - 1 # Contact has duplicate email and it is skip - # - # run_task - # assert_equal ValidationEvent.count, Contact.count - 1 - # end + assert_equal william_contacts_count, 2 + assert_equal Contact.count, 9 + run_task + assert_equal ValidationEvent.count, Contact.count - 1 + end - # def test_should_verify_contact_which_was_not_verified - # bestnames = registrars(:bestnames) - # assert_equal ValidationEvent.count, 0 - # run_task - # assert_equal ValidationEvent.count, Contact.count - 1 # Contact has duplicate email and it is skip - # - # assert_equal Contact.count, 9 - # c = Contact.create(name: 'Jeembo', - # email: 'heey@jeembo.com', - # phone: '+555.555', - # ident: '1234', - # ident_type: 'priv', - # ident_country_code: 'US', - # registrar: bestnames, - # code: 'jeembo-01') - # - # assert_equal Contact.count, 10 - # run_task - # assert_equal ValidationEvent.count, Contact.count - 1 - # end + def test_should_not_affect_successfully_verified_emails + assert_equal ValidationEvent.count, 0 + run_task - # def test_should_verify_again_contact_which_has_faield_verification - # assert_equal ValidationEvent.count, 0 - # run_task - # assert_equal Contact.count, 9 - # assert_equal ValidationEvent.count, 8 # Contact has duplicate email and it is skip - # - # contact = contacts(:john) - # v = ValidationEvent.find_by(validation_eventable_id: contact.id) - # v.update!(success: false) - # - # run_task - # assert_equal ValidationEvent.all.count, 9 - # end + assert_equal ValidationEvent.count, Contact.count - 1 + assert_equal ValidationEvent.where(success: true).count, 5 + assert_equal ValidationEvent.where(success: false).count, 3 - # def test_should_verify_contact_which_has_expired_date_of_verification - # expired_date = Time.now - ValidationEvent::VALIDATION_PERIOD - 1.day - # - # assert_equal ValidationEvent.count, 0 - # run_task - # assert_equal Contact.count, 9 - # assert_equal ValidationEvent.count, 8 # Contact has duplicate email and it is skip - # - # contact = contacts(:john) - # v = ValidationEvent.find_by(validation_eventable_id: contact.id) - # v.update!(created_at: expired_date) - # - # run_task - # assert_equal ValidationEvent.all.count, 9 - # end + run_task + assert_equal ValidationEvent.where(success: true).count, 5 + assert_equal ValidationEvent.where(success: false).count, 6 + end - def test_fd_should_not_removed_if_change_email_to_another_invalid_one + def test_should_verify_contact_email_which_was_not_verified + assert_equal ValidationEvent.count, 0 + + run_task + + assert_equal ValidationEvent.count, Contact.count - 1 + assert_equal Contact.count, 9 + + assert_difference 'Contact.count', 1 do + create_valid_contact + end + + assert_difference 'ValidationEvent.where(success: true).count', 1 do + run_task + end + end + + def test_fd_should_not_be_removed_if_email_changed_to_another_invalid_one contact = contacts(:john) contact.domains.last.schedule_force_delete(type: :soft) assert contact.domains.last.force_delete_scheduled? - contact.update(email: "test@box.test") + contact.update!(email: 'test@box.test') contact.reload trumail_results = OpenStruct.new(success: false, email: contact.email, - domain: "box.tests", - errors: {:mx=>"target host(s) not found"}, - ) + domain: 'box.tests', + errors: { mx: 'target host(s) not found' }) Spy.on_instance_method(Actions::EmailCheck, :check_email).and_return(trumail_results) run_task @@ -147,4 +116,15 @@ class VerifyEmailTaskTest < ActiveJob::TestCase Rake::Task['verify_email:check_all'].execute end end + + def create_valid_contact + Contact.create!(name: 'Jeembo', + email: 'heey@jeembo.com', + phone: '+555.555', + ident: '1234', + ident_type: 'priv', + ident_country_code: 'US', + registrar: @registrar, + code: 'jeembo-01') + end end