From 1a3a2cf9f7af2a4ceae81dc83d5d7e69cf0a0ed1 Mon Sep 17 00:00:00 2001 From: Oleg Hasjanov Date: Mon, 8 Mar 2021 11:56:48 +0200 Subject: [PATCH 01/11] test: added test for force delete bounced mail address --- test/models/bounced_mail_address_test.rb | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/models/bounced_mail_address_test.rb b/test/models/bounced_mail_address_test.rb index 4af401711..7781ac91d 100644 --- a/test/models/bounced_mail_address_test.rb +++ b/test/models/bounced_mail_address_test.rb @@ -12,6 +12,26 @@ class BouncedMailAddressTest < ActiveSupport::TestCase @bounced_mail.action = 'failed' @bounced_mail.status = '5.1.1' @bounced_mail.diagnostic = 'smtp; 550 5.1.1 user unknown' + + @contact_email = "john@inbox.test" + end + + def test_force_delete_related_domains + @bounced_mail.email = @contact_email + contact = Contact.find_by(email: @bounced_mail.email) + domain_contacts = DomainContact.where(contact: contact) + + domain_contacts.each do |domain_contact| + statuses = [DomainStatus::FORCE_DELETE, DomainStatus::SERVER_RENEW_PROHIBITED, DomainStatus::SERVER_TRANSFER_PROHIBITED] + domain_contact.domain.update(statuses: statuses) + end + domain_contacts.reload + + domain_contacts.each do |domain_contact| + assert domain_contact.domain.statuses.include? DomainStatus::FORCE_DELETE + assert domain_contact.domain.statuses.include? DomainStatus::SERVER_RENEW_PROHIBITED + assert domain_contact.domain.statuses.include? DomainStatus::SERVER_TRANSFER_PROHIBITED + end end def test_email_is_required From b5312efc9acd3f5c0f9a8322b4f47ddf72b2a8e0 Mon Sep 17 00:00:00 2001 From: Oleg Hasjanov Date: Mon, 8 Mar 2021 11:59:20 +0200 Subject: [PATCH 02/11] test/refactoring: added test failed test for domain which in contacts have bounced emails --- test/models/bounced_mail_address_test.rb | 6 ------ 1 file changed, 6 deletions(-) diff --git a/test/models/bounced_mail_address_test.rb b/test/models/bounced_mail_address_test.rb index 7781ac91d..fd9c837cf 100644 --- a/test/models/bounced_mail_address_test.rb +++ b/test/models/bounced_mail_address_test.rb @@ -20,12 +20,6 @@ class BouncedMailAddressTest < ActiveSupport::TestCase @bounced_mail.email = @contact_email contact = Contact.find_by(email: @bounced_mail.email) domain_contacts = DomainContact.where(contact: contact) - - domain_contacts.each do |domain_contact| - statuses = [DomainStatus::FORCE_DELETE, DomainStatus::SERVER_RENEW_PROHIBITED, DomainStatus::SERVER_TRANSFER_PROHIBITED] - domain_contact.domain.update(statuses: statuses) - end - domain_contacts.reload domain_contacts.each do |domain_contact| assert domain_contact.domain.statuses.include? DomainStatus::FORCE_DELETE From da033724b11dbb616dcaa95308bb081ce5395f3d Mon Sep 17 00:00:00 2001 From: Oleg Hasjanov Date: Mon, 8 Mar 2021 13:50:23 +0200 Subject: [PATCH 03/11] Refactoring: added more asserts --- test/models/bounced_mail_address_test.rb | 53 ++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 4 deletions(-) diff --git a/test/models/bounced_mail_address_test.rb b/test/models/bounced_mail_address_test.rb index fd9c837cf..a491d4b05 100644 --- a/test/models/bounced_mail_address_test.rb +++ b/test/models/bounced_mail_address_test.rb @@ -16,12 +16,57 @@ class BouncedMailAddressTest < ActiveSupport::TestCase @contact_email = "john@inbox.test" end - def test_force_delete_related_domains - @bounced_mail.email = @contact_email - contact = Contact.find_by(email: @bounced_mail.email) - domain_contacts = DomainContact.where(contact: contact) + def test_soft_force_delete_related_domains + contacts = Contact.where(email: @contact_email) + contacts.each do |contact| + domain_contacts = DomainContact.where(contact: contact) + end domain_contacts.each do |domain_contact| + assert_not domain_contact.domain.statuses.include? DomainStatus::FORCE_DELETE + assert_not domain_contact.domain.statuses.include? DomainStatus::SERVER_RENEW_PROHIBITED + assert_not domain_contact.domain.statuses.include? DomainStatus::SERVER_TRANSFER_PROHIBITED + end + + @bounced_mail.email = @contact_email + @bounced_mail.save + contacts = Contact.where(email: @bounced_mail.email) + + domain_contacts.each do |domain_contact| + assert_equal domain_contact.domain.force_delete_type, 'soft' + assert domain_contact.domain.force_delete_scheduled? + assert domain_contact.domain.statuses.include? DomainStatus::FORCE_DELETE + assert domain_contact.domain.statuses.include? DomainStatus::SERVER_RENEW_PROHIBITED + assert domain_contact.domain.statuses.include? DomainStatus::SERVER_TRANSFER_PROHIBITED + end + end + + def test_soft_force_delete_if_domain_has_force_delete_status + contacts = Contact.where(email: @contact_email) + contacts.each do |contact| + domain_contacts = DomainContact.where(contact: contact) + end + + domain_contacts.each do |domain_contact| + domain_contact.domain.update(statuses: [DomainStatus::FORCE_DELETE, DomainStatus::SERVER_RENEW_PROHIBITED, DomainStatus::SERVER_TRANSFER_PROHIBITED]) + end + + force_delete_date = domain_contacts[0].domain.force_delete_date + + domain_contacts.each do |domain_contact| + assert domain_contact.domain.statuses.include? DomainStatus::FORCE_DELETE + assert domain_contact.domain.statuses.include? DomainStatus::SERVER_RENEW_PROHIBITED + assert domain_contact.domain.statuses.include? DomainStatus::SERVER_TRANSFER_PROHIBITED + end + + @bounced_mail.email = @contact_email + @bounced_mail.save + contacts = Contact.where(email: @bounced_mail.email) + + domain_contacts.each do |domain_contact| + assert_equal domain_contact.domain.force_delete_date, force_delete_date + assert_equal domain_contact.domain.force_delete_type, 'soft' + assert domain_contact.domain.force_delete_scheduled? assert domain_contact.domain.statuses.include? DomainStatus::FORCE_DELETE assert domain_contact.domain.statuses.include? DomainStatus::SERVER_RENEW_PROHIBITED assert domain_contact.domain.statuses.include? DomainStatus::SERVER_TRANSFER_PROHIBITED From c0282660d9acdc49f634d8534f9f65f24fe14d42 Mon Sep 17 00:00:00 2001 From: Alex Sherman Date: Thu, 25 Feb 2021 16:43:38 +0500 Subject: [PATCH 04/11] Add tests for FD to be set --- test/models/domain/force_delete_test.rb | 53 +++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/test/models/domain/force_delete_test.rb b/test/models/domain/force_delete_test.rb index 19338f495..e4ad085e6 100644 --- a/test/models/domain/force_delete_test.rb +++ b/test/models/domain/force_delete_test.rb @@ -5,6 +5,11 @@ class ForceDeleteTest < ActionMailer::TestCase @domain = domains(:shop) Setting.redemption_grace_period = 30 ActionMailer::Base.deliveries.clear + @old_validation_type = Truemail.configure.default_validation_type + end + + teardown do + Truemail.configure.default_validation_type = @old_validation_type end def test_schedules_force_delete_fast_track @@ -315,4 +320,52 @@ class ForceDeleteTest < ActionMailer::TestCase assert @domain.force_delete_scheduled? assert @domain.registrant_update_confirmable?(@domain.registrant_verification_token) end + + def test_schedules_force_delete_after_bounce + @domain.update(valid_to: Time.zone.parse('2012-08-05')) + assert_not @domain.force_delete_scheduled? + travel_to Time.zone.parse('2010-07-05') + + prepare_bounced_email_address(@domain.admin_contacts.first.email) + + @domain.reload + + assert @domain.force_delete_scheduled? + assert_equal 'invalid_email', @domain.template_name + assert_equal Date.parse('2010-09-19'), @domain.force_delete_date.to_date + assert_equal Date.parse('2010-08-05'), @domain.force_delete_start.to_date + end + + def test_schedules_force_delete_invalid_contact + @domain.update(valid_to: Time.zone.parse('2012-08-05')) + assert_not @domain.force_delete_scheduled? + travel_to Time.zone.parse('2010-07-05') + + Truemail.configure.default_validation_type = :regex + + contact = @domain.admin_contacts.first + contact.update(email: 'some@strangesentence@internet.ee') + + assert contact.email_verification_failed? + assert contact.invalid? + + @domain.reload + + assert @domain.force_delete_scheduled? + assert_equal 'invalid_email', @domain.template_name + assert_equal Date.parse('2010-09-19'), @domain.force_delete_date.to_date + assert_equal Date.parse('2010-08-05'), @domain.force_delete_start.to_date + end + + def prepare_bounced_email_address(email) + @bounced_mail = BouncedMailAddress.new + @bounced_mail.email = email + @bounced_mail.message_id = '010f0174a0c7d348-ea6e2fc1-0854-4073-b71f-5cecf9b0d0b2-000000' + @bounced_mail.bounce_type = 'Permanent' + @bounced_mail.bounce_subtype = 'General' + @bounced_mail.action = 'failed' + @bounced_mail.status = '5.1.1' + @bounced_mail.diagnostic = 'smtp; 550 5.1.1 user unknown' + @bounced_mail.save! + end end From da3272207b104c65a96b40e0f4503c8496fd4614 Mon Sep 17 00:00:00 2001 From: Alex Sherman Date: Tue, 16 Mar 2021 16:10:28 +0500 Subject: [PATCH 05/11] Fix bounced email keeps force_delete test --- test/models/bounced_mail_address_test.rb | 39 ++++++++---------------- 1 file changed, 12 insertions(+), 27 deletions(-) diff --git a/test/models/bounced_mail_address_test.rb b/test/models/bounced_mail_address_test.rb index a491d4b05..9094378d2 100644 --- a/test/models/bounced_mail_address_test.rb +++ b/test/models/bounced_mail_address_test.rb @@ -17,10 +17,7 @@ class BouncedMailAddressTest < ActiveSupport::TestCase end def test_soft_force_delete_related_domains - contacts = Contact.where(email: @contact_email) - contacts.each do |contact| - domain_contacts = DomainContact.where(contact: contact) - end + domain_contacts = Contact.where(email: @contact_email).map(&:domain_contacts).flatten domain_contacts.each do |domain_contact| assert_not domain_contact.domain.statuses.include? DomainStatus::FORCE_DELETE @@ -30,7 +27,6 @@ class BouncedMailAddressTest < ActiveSupport::TestCase @bounced_mail.email = @contact_email @bounced_mail.save - contacts = Contact.where(email: @bounced_mail.email) domain_contacts.each do |domain_contact| assert_equal domain_contact.domain.force_delete_type, 'soft' @@ -42,34 +38,23 @@ class BouncedMailAddressTest < ActiveSupport::TestCase end def test_soft_force_delete_if_domain_has_force_delete_status - contacts = Contact.where(email: @contact_email) - contacts.each do |contact| - domain_contacts = DomainContact.where(contact: contact) - end - - domain_contacts.each do |domain_contact| - domain_contact.domain.update(statuses: [DomainStatus::FORCE_DELETE, DomainStatus::SERVER_RENEW_PROHIBITED, DomainStatus::SERVER_TRANSFER_PROHIBITED]) - end - - force_delete_date = domain_contacts[0].domain.force_delete_date - - domain_contacts.each do |domain_contact| - assert domain_contact.domain.statuses.include? DomainStatus::FORCE_DELETE - assert domain_contact.domain.statuses.include? DomainStatus::SERVER_RENEW_PROHIBITED - assert domain_contact.domain.statuses.include? DomainStatus::SERVER_TRANSFER_PROHIBITED + domain_contacts = Contact.where(email: @contact_email).map(&:domain_contacts).flatten + perform_enqueued_jobs do + domain_contacts.each do |domain_contact| + domain_contact.domain.update(valid_to: Time.zone.now + 5.years) + domain_contact.domain.schedule_force_delete(type: :soft, notify_by_email: false, reason: 'test') + end end + force_delete_date = domain_contacts.map(&:domain).each.pluck(:force_delete_date).sample + assert_not_nil force_delete_date @bounced_mail.email = @contact_email @bounced_mail.save - contacts = Contact.where(email: @bounced_mail.email) - domain_contacts.each do |domain_contact| - assert_equal domain_contact.domain.force_delete_date, force_delete_date - assert_equal domain_contact.domain.force_delete_type, 'soft' + domain_contacts.all? do |domain_contact| + assert_equal force_delete_date, domain_contact.domain.force_delete_date + assert_equal 'soft', domain_contact.domain.force_delete_type assert domain_contact.domain.force_delete_scheduled? - assert domain_contact.domain.statuses.include? DomainStatus::FORCE_DELETE - assert domain_contact.domain.statuses.include? DomainStatus::SERVER_RENEW_PROHIBITED - assert domain_contact.domain.statuses.include? DomainStatus::SERVER_TRANSFER_PROHIBITED end end From 4522e4427e8c4c1e050918693a26411bfb645e66 Mon Sep 17 00:00:00 2001 From: Alex Sherman Date: Tue, 16 Mar 2021 17:24:57 +0500 Subject: [PATCH 06/11] Init force delete on bounce creation --- .../domains/force_delete_bounce/base.rb | 19 +++++++++++++++++++ app/models/bounced_mail_address.rb | 5 +++++ test/models/bounced_mail_address_test.rb | 4 +++- 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 app/interactions/domains/force_delete_bounce/base.rb diff --git a/app/interactions/domains/force_delete_bounce/base.rb b/app/interactions/domains/force_delete_bounce/base.rb new file mode 100644 index 000000000..f7de85492 --- /dev/null +++ b/app/interactions/domains/force_delete_bounce/base.rb @@ -0,0 +1,19 @@ +module Domains + module ForceDeleteBounce + class Base < ActiveInteraction::Base + object :bounced_mail_address, + class: BouncedMailAddress, + description: 'Bounced email to set ForceDelete from' + + def execute + email = bounced_mail_address.email + domain_contacts = Contact.where(email: email).map(&:domain_contacts).flatten + domains = domain_contacts.map(&:domain).flatten + domains.each do |domain| + domain.schedule_force_delete(type: :soft, + notify_by_email: true, reason: 'invalid_email') + end + end + end + end +end diff --git a/app/models/bounced_mail_address.rb b/app/models/bounced_mail_address.rb index db4413829..931656d22 100644 --- a/app/models/bounced_mail_address.rb +++ b/app/models/bounced_mail_address.rb @@ -1,6 +1,7 @@ class BouncedMailAddress < ApplicationRecord validates :email, :message_id, :bounce_type, :bounce_subtype, :action, :status, presence: true after_destroy :destroy_aws_suppression + after_create :force_delete_from_bounce def bounce_reason "#{action} (#{status} #{diagnostic})" @@ -42,4 +43,8 @@ class BouncedMailAddress < ApplicationRecord rescue Aws::Errors::MissingRegionError false end + + def force_delete_from_bounce + Domains::ForceDeleteBounce::Base.run(bounced_mail_address: self) + end end diff --git a/test/models/bounced_mail_address_test.rb b/test/models/bounced_mail_address_test.rb index 9094378d2..a7288cd01 100644 --- a/test/models/bounced_mail_address_test.rb +++ b/test/models/bounced_mail_address_test.rb @@ -20,6 +20,7 @@ class BouncedMailAddressTest < ActiveSupport::TestCase domain_contacts = Contact.where(email: @contact_email).map(&:domain_contacts).flatten domain_contacts.each do |domain_contact| + domain_contact.domain.update(valid_to: Time.zone.now + 5.years) assert_not domain_contact.domain.statuses.include? DomainStatus::FORCE_DELETE assert_not domain_contact.domain.statuses.include? DomainStatus::SERVER_RENEW_PROHIBITED assert_not domain_contact.domain.statuses.include? DomainStatus::SERVER_TRANSFER_PROHIBITED @@ -29,7 +30,8 @@ class BouncedMailAddressTest < ActiveSupport::TestCase @bounced_mail.save domain_contacts.each do |domain_contact| - assert_equal domain_contact.domain.force_delete_type, 'soft' + domain_contact.reload + assert_equal 'soft', domain_contact.domain.force_delete_type assert domain_contact.domain.force_delete_scheduled? assert domain_contact.domain.statuses.include? DomainStatus::FORCE_DELETE assert domain_contact.domain.statuses.include? DomainStatus::SERVER_RENEW_PROHIBITED From a8e3d6755641419dc2adc459f52ff44cc186a3bb Mon Sep 17 00:00:00 2001 From: Alex Sherman Date: Wed, 17 Mar 2021 15:11:20 +0500 Subject: [PATCH 07/11] Add forceDelete on email_verification failed --- .../{force_delete_bounce => force_delete_email}/base.rb | 8 ++++---- app/models/bounced_mail_address.rb | 2 +- app/models/email_address_verification.rb | 7 +++++++ test/models/domain/force_delete_test.rb | 4 ++-- 4 files changed, 14 insertions(+), 7 deletions(-) rename app/interactions/domains/{force_delete_bounce => force_delete_email}/base.rb (77%) diff --git a/app/interactions/domains/force_delete_bounce/base.rb b/app/interactions/domains/force_delete_email/base.rb similarity index 77% rename from app/interactions/domains/force_delete_bounce/base.rb rename to app/interactions/domains/force_delete_email/base.rb index f7de85492..aa204831a 100644 --- a/app/interactions/domains/force_delete_bounce/base.rb +++ b/app/interactions/domains/force_delete_email/base.rb @@ -1,15 +1,15 @@ module Domains - module ForceDeleteBounce + module ForceDeleteEmail class Base < ActiveInteraction::Base - object :bounced_mail_address, - class: BouncedMailAddress, + string :email, description: 'Bounced email to set ForceDelete from' def execute - email = bounced_mail_address.email domain_contacts = Contact.where(email: email).map(&:domain_contacts).flatten domains = domain_contacts.map(&:domain).flatten domains.each do |domain| + next if domain.force_delete_scheduled? + domain.schedule_force_delete(type: :soft, notify_by_email: true, reason: 'invalid_email') end diff --git a/app/models/bounced_mail_address.rb b/app/models/bounced_mail_address.rb index 931656d22..376e16d35 100644 --- a/app/models/bounced_mail_address.rb +++ b/app/models/bounced_mail_address.rb @@ -45,6 +45,6 @@ class BouncedMailAddress < ApplicationRecord end def force_delete_from_bounce - Domains::ForceDeleteBounce::Base.run(bounced_mail_address: self) + Domains::ForceDeleteEmail::Base.run(email: email) end end diff --git a/app/models/email_address_verification.rb b/app/models/email_address_verification.rb index 2fe7c0dbe..c54cd4224 100644 --- a/app/models/email_address_verification.rb +++ b/app/models/email_address_verification.rb @@ -1,5 +1,6 @@ class EmailAddressVerification < ApplicationRecord RECENTLY_VERIFIED_PERIOD = 1.month + after_save :check_force_delete scope :not_verified_recently, lambda { where('verified_at IS NULL or verified_at < ?', verification_period) @@ -40,6 +41,12 @@ class EmailAddressVerification < ApplicationRecord success end + def check_force_delete + return unless failed? + + Domains::ForceDeleteEmail::Base.run(email: email) + end + def verify validation_request = Truemail.validate(email) diff --git a/test/models/domain/force_delete_test.rb b/test/models/domain/force_delete_test.rb index e4ad085e6..a0eb9c81f 100644 --- a/test/models/domain/force_delete_test.rb +++ b/test/models/domain/force_delete_test.rb @@ -344,10 +344,10 @@ class ForceDeleteTest < ActionMailer::TestCase Truemail.configure.default_validation_type = :regex contact = @domain.admin_contacts.first - contact.update(email: 'some@strangesentence@internet.ee') + contact.update_attribute(:email, 'some@strangesentence@internet.ee') + contact.email_verification.verify assert contact.email_verification_failed? - assert contact.invalid? @domain.reload From a3260bb5bf939197ef3105af259ce6598f6d774d Mon Sep 17 00:00:00 2001 From: Alex Sherman Date: Fri, 19 Mar 2021 16:56:57 +0500 Subject: [PATCH 08/11] Add rake task to create fake BouncedMailAddress --- lib/tasks/email_bounce_test.rake | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 lib/tasks/email_bounce_test.rake diff --git a/lib/tasks/email_bounce_test.rake b/lib/tasks/email_bounce_test.rake new file mode 100644 index 000000000..e02e260fa --- /dev/null +++ b/lib/tasks/email_bounce_test.rake @@ -0,0 +1,14 @@ +namespace :email_bounce do + desc 'Creates a dummy email bounce by email address' + task :create_test, [:email] => [:environment] do |_t, args| + bounced_mail = BouncedMailAddress.new + bounced_mail.email = args[:email] + bounced_mail.message_id = '010f0174a0c7d348-ea6e2fc1-0854-4073-b71f-5cecf9b0d0b2-000000' + bounced_mail.bounce_type = 'Permanent' + bounced_mail.bounce_subtype = 'General' + bounced_mail.action = 'failed' + bounced_mail.status = '5.1.1' + bounced_mail.diagnostic = 'smtp; 550 5.1.1 user unknown' + bounced_mail.save! + end +end From 81c21db3924bf35d104b33518486ee6548b0c8ab Mon Sep 17 00:00:00 2001 From: Alex Sherman Date: Fri, 19 Mar 2021 18:19:28 +0500 Subject: [PATCH 09/11] Add FD if email belongs to registant --- .../domains/force_delete_email/base.rb | 6 +++++- test/models/domain/force_delete_test.rb | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/app/interactions/domains/force_delete_email/base.rb b/app/interactions/domains/force_delete_email/base.rb index aa204831a..7b7e56e5e 100644 --- a/app/interactions/domains/force_delete_email/base.rb +++ b/app/interactions/domains/force_delete_email/base.rb @@ -6,7 +6,11 @@ module Domains def execute domain_contacts = Contact.where(email: email).map(&:domain_contacts).flatten - domains = domain_contacts.map(&:domain).flatten + registrant_ids = Registrant.where(email: email).pluck(:id) + + domains = domain_contacts.map(&:domain).flatten + + Domain.where(registrant_id: registrant_ids) + domains.each do |domain| next if domain.force_delete_scheduled? diff --git a/test/models/domain/force_delete_test.rb b/test/models/domain/force_delete_test.rb index a0eb9c81f..68b0df87a 100644 --- a/test/models/domain/force_delete_test.rb +++ b/test/models/domain/force_delete_test.rb @@ -336,6 +336,21 @@ class ForceDeleteTest < ActionMailer::TestCase assert_equal Date.parse('2010-08-05'), @domain.force_delete_start.to_date end + def test_schedules_force_delete_after_registrant_bounce + @domain.update(valid_to: Time.zone.parse('2012-08-05')) + assert_not @domain.force_delete_scheduled? + travel_to Time.zone.parse('2010-07-05') + + prepare_bounced_email_address(@domain.registrant.email) + + @domain.reload + + assert @domain.force_delete_scheduled? + assert_equal 'invalid_email', @domain.template_name + assert_equal Date.parse('2010-09-19'), @domain.force_delete_date.to_date + assert_equal Date.parse('2010-08-05'), @domain.force_delete_start.to_date + end + def test_schedules_force_delete_invalid_contact @domain.update(valid_to: Time.zone.parse('2012-08-05')) assert_not @domain.force_delete_scheduled? From 91093b274d5b484d76bc4cc4a9398fa7ee429676 Mon Sep 17 00:00:00 2001 From: Alex Sherman Date: Mon, 22 Mar 2021 14:21:08 +0500 Subject: [PATCH 10/11] Add notification on autoFD --- app/interactions/domains/force_delete/base.rb | 3 +++ .../domains/force_delete/notify_registrar.rb | 12 ++++++++++++ .../domains/force_delete_email/base.rb | 14 +++++++++----- app/models/concerns/domain/force_delete.rb | 4 ++-- config/locales/en.yml | 1 + test/models/domain/force_delete_test.rb | 18 +++++++++++++++--- 6 files changed, 42 insertions(+), 10 deletions(-) diff --git a/app/interactions/domains/force_delete/base.rb b/app/interactions/domains/force_delete/base.rb index d4ad2b820..712d0c08e 100644 --- a/app/interactions/domains/force_delete/base.rb +++ b/app/interactions/domains/force_delete/base.rb @@ -13,6 +13,9 @@ module Domains string :reason, default: nil, description: 'Which mail template to use explicitly' + string :email, + default: nil, + description: 'Possible invalid email to notify on' validates :type, inclusion: { in: %i[fast_track soft] } end diff --git a/app/interactions/domains/force_delete/notify_registrar.rb b/app/interactions/domains/force_delete/notify_registrar.rb index 522502640..e4aa48976 100644 --- a/app/interactions/domains/force_delete/notify_registrar.rb +++ b/app/interactions/domains/force_delete/notify_registrar.rb @@ -2,11 +2,23 @@ module Domains module ForceDelete class NotifyRegistrar < Base def execute + email.present? ? notify_with_email : notify_without_email + end + + def notify_without_email domain.registrar.notifications.create!(text: I18n.t('force_delete_set_on_domain', domain_name: domain.name, outzone_date: domain.outzone_date, purge_date: domain.purge_date)) end + + def notify_with_email + domain.registrar.notifications.create!(text: I18n.t('force_delete_auto_email', + domain_name: domain.name, + outzone_date: domain.outzone_date, + purge_date: domain.purge_date, + email: email)) + end end end end diff --git a/app/interactions/domains/force_delete_email/base.rb b/app/interactions/domains/force_delete_email/base.rb index 7b7e56e5e..40339691b 100644 --- a/app/interactions/domains/force_delete_email/base.rb +++ b/app/interactions/domains/force_delete_email/base.rb @@ -11,12 +11,16 @@ module Domains domains = domain_contacts.map(&:domain).flatten + Domain.where(registrant_id: registrant_ids) - domains.each do |domain| - next if domain.force_delete_scheduled? + domains.each { |domain| process_force_delete(domain) unless domain.force_delete_scheduled? } + end - domain.schedule_force_delete(type: :soft, - notify_by_email: true, reason: 'invalid_email') - end + private + + def process_force_delete(domain) + domain.schedule_force_delete(type: :soft, + notify_by_email: true, + reason: 'invalid_email', + email: email) end end end diff --git a/app/models/concerns/domain/force_delete.rb b/app/models/concerns/domain/force_delete.rb index ca13eb5d1..bc89022d0 100644 --- a/app/models/concerns/domain/force_delete.rb +++ b/app/models/concerns/domain/force_delete.rb @@ -45,9 +45,9 @@ module Domain::ForceDelete # rubocop:disable Metrics/ModuleLength statuses.include?(DomainStatus::FORCE_DELETE) end - def schedule_force_delete(type: :fast_track, notify_by_email: false, reason: nil) + def schedule_force_delete(type: :fast_track, notify_by_email: false, reason: nil, email: nil) Domains::ForceDelete::SetForceDelete.run(domain: self, type: type, reason: reason, - notify_by_email: notify_by_email) + notify_by_email: notify_by_email, email: email) end def cancel_force_delete diff --git a/config/locales/en.yml b/config/locales/en.yml index 22f29a6e3..97c968996 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -626,6 +626,7 @@ en: created_at_until: 'Created at until' is_registrant: 'Is registrant' force_delete_set_on_domain: 'Force delete set on domain %{domain_name}. Outzone date: %{outzone_date}. Purge date: %{purge_date}' + force_delete_auto_email: 'Force delete set on domain %{domain_name}. Outzone date: %{outzone_date}. Purge date: %{purge_date}. Invalid email: %{email}' grace_period_started_domain: 'For domain %{domain_name} started 45-days redemption grace period, ForceDelete will be in effect from %{date}' force_delete_cancelled: 'Force delete is cancelled on domain %{domain_name}' contact_is_not_valid: 'Contact %{value} is not valid, please fix the invalid contact' diff --git a/test/models/domain/force_delete_test.rb b/test/models/domain/force_delete_test.rb index 68b0df87a..837ad3adc 100644 --- a/test/models/domain/force_delete_test.rb +++ b/test/models/domain/force_delete_test.rb @@ -325,8 +325,10 @@ class ForceDeleteTest < ActionMailer::TestCase @domain.update(valid_to: Time.zone.parse('2012-08-05')) assert_not @domain.force_delete_scheduled? travel_to Time.zone.parse('2010-07-05') + email = @domain.admin_contacts.first.email + asserted_text = "Invalid email: #{email}" - prepare_bounced_email_address(@domain.admin_contacts.first.email) + prepare_bounced_email_address(email) @domain.reload @@ -334,14 +336,18 @@ class ForceDeleteTest < ActionMailer::TestCase assert_equal 'invalid_email', @domain.template_name assert_equal Date.parse('2010-09-19'), @domain.force_delete_date.to_date assert_equal Date.parse('2010-08-05'), @domain.force_delete_start.to_date + notification = @domain.registrar.notifications.last + assert notification.text.include? asserted_text end def test_schedules_force_delete_after_registrant_bounce @domain.update(valid_to: Time.zone.parse('2012-08-05')) assert_not @domain.force_delete_scheduled? travel_to Time.zone.parse('2010-07-05') + email = @domain.registrant.email + asserted_text = "Invalid email: #{email}" - prepare_bounced_email_address(@domain.registrant.email) + prepare_bounced_email_address(email) @domain.reload @@ -349,17 +355,21 @@ class ForceDeleteTest < ActionMailer::TestCase assert_equal 'invalid_email', @domain.template_name assert_equal Date.parse('2010-09-19'), @domain.force_delete_date.to_date assert_equal Date.parse('2010-08-05'), @domain.force_delete_start.to_date + notification = @domain.registrar.notifications.last + assert notification.text.include? asserted_text end def test_schedules_force_delete_invalid_contact @domain.update(valid_to: Time.zone.parse('2012-08-05')) assert_not @domain.force_delete_scheduled? travel_to Time.zone.parse('2010-07-05') + email = 'some@strangesentence@internet.ee' + asserted_text = "Invalid email: #{email}" Truemail.configure.default_validation_type = :regex contact = @domain.admin_contacts.first - contact.update_attribute(:email, 'some@strangesentence@internet.ee') + contact.update_attribute(:email, email) contact.email_verification.verify assert contact.email_verification_failed? @@ -370,6 +380,8 @@ class ForceDeleteTest < ActionMailer::TestCase assert_equal 'invalid_email', @domain.template_name assert_equal Date.parse('2010-09-19'), @domain.force_delete_date.to_date assert_equal Date.parse('2010-08-05'), @domain.force_delete_start.to_date + notification = @domain.registrar.notifications.last + assert notification.text.include? asserted_text end def prepare_bounced_email_address(email) From 29f7aa19ac3e6c3f8bf2eb93c13f94d301da78f6 Mon Sep 17 00:00:00 2001 From: Alex Sherman Date: Mon, 22 Mar 2021 15:21:53 +0500 Subject: [PATCH 11/11] Make sure what expired domain emails will not be sent to non-valid addreses --- app/mailers/domain_expire_mailer.rb | 9 ++++++-- app/presenters/domain_presenter.rb | 2 +- lib/validators/email_validator.rb | 15 -------------- test/mailers/domain_expire_mailer_test.rb | 25 +++++++++++++++++++++++ 4 files changed, 33 insertions(+), 18 deletions(-) delete mode 100644 lib/validators/email_validator.rb diff --git a/app/mailers/domain_expire_mailer.rb b/app/mailers/domain_expire_mailer.rb index 229120825..958e8c1c1 100644 --- a/app/mailers/domain_expire_mailer.rb +++ b/app/mailers/domain_expire_mailer.rb @@ -43,8 +43,11 @@ class DomainExpireMailer < ApplicationMailer # Needed because there are invalid emails in the database, which have been imported from legacy app def filter_invalid_emails(emails:, domain:) - emails.select do |email| - valid = EmailValidator.new(email).valid? + old_validation_type = Truemail.configure.default_validation_type + Truemail.configure.default_validation_type = :regex + + results = emails.select do |email| + valid = Truemail.valid?(email) unless valid logger.info("Unable to send DomainExpireMailer#expired email for domain #{domain.name} (##{domain.id})" \ @@ -53,5 +56,7 @@ class DomainExpireMailer < ApplicationMailer valid end + Truemail.configure.default_validation_type = old_validation_type + results end end diff --git a/app/presenters/domain_presenter.rb b/app/presenters/domain_presenter.rb index bcbd5d600..6ded9a30b 100644 --- a/app/presenters/domain_presenter.rb +++ b/app/presenters/domain_presenter.rb @@ -1,5 +1,5 @@ class DomainPresenter - delegate :name, :transfer_code, :registrant, :registrant_id, to: :domain + delegate :name, :transfer_code, :registrant, :registrant_id, :id, to: :domain def initialize(domain:, view:) @domain = domain diff --git a/lib/validators/email_validator.rb b/lib/validators/email_validator.rb deleted file mode 100644 index 60b1b3ce1..000000000 --- a/lib/validators/email_validator.rb +++ /dev/null @@ -1,15 +0,0 @@ -class EmailValidator - def self.regexp - Devise::email_regexp - end - - def initialize(email) - @email = email - end - - def valid? - email =~ self.class.regexp - end - - attr_reader :email -end diff --git a/test/mailers/domain_expire_mailer_test.rb b/test/mailers/domain_expire_mailer_test.rb index 84e520b78..c36c3d80e 100644 --- a/test/mailers/domain_expire_mailer_test.rb +++ b/test/mailers/domain_expire_mailer_test.rb @@ -22,4 +22,29 @@ class DomainExpireMailerTest < ActionMailer::TestCase assert_equal I18n.t("domain_expire_mailer.expired_soft.subject", domain_name: domain.name), email.subject end + + def test_delivers_domain_expiration_soft_email_if_auto_fd + domain = domains(:shop) + assert_not domain.force_delete_scheduled? + travel_to Time.zone.parse('2010-07-05') + email = 'some@strangesentence@internet.ee' + + Truemail.configure.default_validation_type = :regex + + contact = domain.admin_contacts.first + contact.update_attribute(:email, email) + contact.email_verification.verify + + assert contact.email_verification_failed? + + domain.reload + + assert domain.force_delete_scheduled? + + email = DomainExpireMailer.expired_soft(domain: domain, registrar: domain.registrar).deliver_now + + assert_emails 1 + assert_equal I18n.t("domain_expire_mailer.expired_soft.subject", domain_name: domain.name), + email.subject + end end