From 4402dfd90ddb7d7c5757cdfc6e7ed1b86b3ee6a3 Mon Sep 17 00:00:00 2001 From: Neil Martinsen-Burrell Date: Mon, 13 Nov 2023 16:09:38 -0600 Subject: [PATCH 1/3] Set transition domain's email_sent flag as the emails are sent --- .../commands/send_domain_invitations.py | 20 +++++++++---------- .../test_transition_domain_migrations.py | 14 +++++++++++++ 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/registrar/management/commands/send_domain_invitations.py b/src/registrar/management/commands/send_domain_invitations.py index 68e805be9..e02c87bf8 100644 --- a/src/registrar/management/commands/send_domain_invitations.py +++ b/src/registrar/management/commands/send_domain_invitations.py @@ -65,8 +65,6 @@ class Command(BaseCommand): self.send_emails() logger.info("done sending emails") - self.update_domains_as_sent() - logger.info("done sending emails and updating transition_domains") else: logger.info("not sending emails") @@ -143,11 +141,13 @@ class Command(BaseCommand): # to True for domain in email_data["domains"]: self.domains_with_errors.append(domain) - - def update_domains_as_sent(self): - """set email_sent to True in all transition_domains which have - been processed successfully""" - for transition_domain in self.transition_domains: - if transition_domain.domain_name not in self.domains_with_errors: - transition_domain.email_sent = True - transition_domain.save() + else: + # email was sent no exception, mark all these transition domains + # as email_sent. + this_email = email_data["email"] + for domain_name in email_data["domains"]: + # self.transition_domains is a queryset so we can sub-select + # from it and use the objects to mark them as sent + this_transition_domain = self.transition_domains.get(username=this_email, domain_name=domain_name) + this_transition_domain.email_sent = True + this_transition_domain.save() diff --git a/src/registrar/tests/test_transition_domain_migrations.py b/src/registrar/tests/test_transition_domain_migrations.py index 5c93fd8f0..e048b2830 100644 --- a/src/registrar/tests/test_transition_domain_migrations.py +++ b/src/registrar/tests/test_transition_domain_migrations.py @@ -13,6 +13,8 @@ from registrar.models import ( UserDomainRole, ) +import boto3_mocking # type: ignore + from django.core.management import call_command from unittest.mock import patch @@ -413,3 +415,15 @@ class TestMigrations(TestCase): self.assertIn("Found 2 transition domains", output) self.assertTrue("would send email to testuser@gmail.com", output) self.assertTrue("would send email to agustina.wyman7@test.com", output) + + # this tries to actually send an email, so mock it out + @boto3_mocking.patching + def test_send_domain_invitations_email_sent(self): + """A transition domain is marked email_sent.""" + with less_console_noise(): + self.run_load_domains() + self.run_transfer_domains() + call_command("send_domain_invitations", "-s", "testuser@gmail.com") + + self.assertTrue(TransitionDomain.objects.get(username="testuser@gmail.com").email_sent) + self.assertFalse(TransitionDomain.objects.get(username="agustina.wyman7@test.com").email_sent) From b110ac1efa7ca441f481dab0c58306b9dd658a75 Mon Sep 17 00:00:00 2001 From: Neil Martinsen-Burrell Date: Mon, 13 Nov 2023 16:33:32 -0600 Subject: [PATCH 2/3] Slight sleep to rate-limit email sending --- src/registrar/management/commands/send_domain_invitations.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/registrar/management/commands/send_domain_invitations.py b/src/registrar/management/commands/send_domain_invitations.py index e02c87bf8..603fbce3a 100644 --- a/src/registrar/management/commands/send_domain_invitations.py +++ b/src/registrar/management/commands/send_domain_invitations.py @@ -2,6 +2,7 @@ import logging import copy +import time from django.core.management import BaseCommand from registrar.models import TransitionDomain @@ -112,6 +113,9 @@ class Command(BaseCommand): if len(self.emails_to_send) > 0: for email_data in self.emails_to_send: self.send_email(email_data) + # wait 1/10 second until sending the next email to keep us + # safely under a rate of 10 emails per second + time.sleep(0.1) else: logger.info("no emails to send") From f30308225031395a0d2d293c97bc8d830dd4c467 Mon Sep 17 00:00:00 2001 From: Neil Martinsen-Burrell Date: Mon, 13 Nov 2023 16:57:01 -0600 Subject: [PATCH 3/3] Don't try to test actually sending emails --- .../tests/test_transition_domain_migrations.py | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/registrar/tests/test_transition_domain_migrations.py b/src/registrar/tests/test_transition_domain_migrations.py index e048b2830..5c93fd8f0 100644 --- a/src/registrar/tests/test_transition_domain_migrations.py +++ b/src/registrar/tests/test_transition_domain_migrations.py @@ -13,8 +13,6 @@ from registrar.models import ( UserDomainRole, ) -import boto3_mocking # type: ignore - from django.core.management import call_command from unittest.mock import patch @@ -415,15 +413,3 @@ class TestMigrations(TestCase): self.assertIn("Found 2 transition domains", output) self.assertTrue("would send email to testuser@gmail.com", output) self.assertTrue("would send email to agustina.wyman7@test.com", output) - - # this tries to actually send an email, so mock it out - @boto3_mocking.patching - def test_send_domain_invitations_email_sent(self): - """A transition domain is marked email_sent.""" - with less_console_noise(): - self.run_load_domains() - self.run_transfer_domains() - call_command("send_domain_invitations", "-s", "testuser@gmail.com") - - self.assertTrue(TransitionDomain.objects.get(username="testuser@gmail.com").email_sent) - self.assertFalse(TransitionDomain.objects.get(username="agustina.wyman7@test.com").email_sent)