merge main again

This commit is contained in:
David Kennedy 2024-02-26 15:18:44 -05:00
commit caa1a9ef84
No known key found for this signature in database
GPG key ID: 6528A5386E66B96B
7 changed files with 128 additions and 40 deletions

View file

@ -286,6 +286,7 @@ AWS_MAX_ATTEMPTS = 3
BOTO_CONFIG = Config(retries={"mode": AWS_RETRY_MODE, "max_attempts": AWS_MAX_ATTEMPTS})
# email address to use for various automated correspondence
# also used as a default to and bcc email
DEFAULT_FROM_EMAIL = "help@get.gov <help@get.gov>"
# connect to an (external) SMTP server for sending email

View file

@ -4,6 +4,7 @@ from typing import Union
import logging
from django.apps import apps
from django.conf import settings
from django.db import models
from django_fsm import FSMField, transition # type: ignore
from django.utils import timezone
@ -588,7 +589,9 @@ class DomainApplication(TimeStampedModel):
logger.error(err)
logger.error(f"Can't query an approved domain while attempting {called_from}")
def _send_status_update_email(self, new_status, email_template, email_template_subject, send_email=True):
def _send_status_update_email(
self, new_status, email_template, email_template_subject, send_email=True, bcc_address=""
):
"""Send a status update email to the submitter.
The email goes to the email address that the submitter gave as their
@ -613,6 +616,7 @@ class DomainApplication(TimeStampedModel):
email_template_subject,
self.submitter.email,
context={"application": self},
bcc_address=bcc_address,
)
logger.info(f"The {new_status} email sent to: {self.submitter.email}")
except EmailSendingError:
@ -654,11 +658,17 @@ class DomainApplication(TimeStampedModel):
# Limit email notifications to transitions from Started and Withdrawn
limited_statuses = [self.ApplicationStatus.STARTED, self.ApplicationStatus.WITHDRAWN]
bcc_address = ""
if settings.IS_PRODUCTION:
bcc_address = settings.DEFAULT_FROM_EMAIL
if self.status in limited_statuses:
self._send_status_update_email(
"submission confirmation",
"emails/submission_confirmation.txt",
"emails/submission_confirmation_subject.txt",
True,
bcc_address,
)
@transition(

View file

@ -1,5 +1,5 @@
from datetime import date
from django.test import TestCase, RequestFactory, Client
from django.test import TestCase, RequestFactory, Client, override_settings
from django.contrib.admin.sites import AdminSite
from contextlib import ExitStack
from django_webtest import WebTest # type: ignore
@ -608,7 +608,9 @@ class TestDomainApplicationAdmin(MockEppLib):
# Use the model admin's save_model method
self.admin.save_model(request, application, form=None, change=True)
def assert_email_is_accurate(self, expected_string, email_index, email_address):
def assert_email_is_accurate(
self, expected_string, email_index, email_address, test_that_no_bcc=False, bcc_email_address=""
):
"""Helper method for the email test cases.
email_index is the index of the email in mock_client."""
@ -628,12 +630,26 @@ class TestDomainApplicationAdmin(MockEppLib):
self.assertEqual(to_email, email_address)
self.assertIn(expected_string, email_body)
if test_that_no_bcc:
_ = ""
with self.assertRaises(KeyError):
with less_console_noise():
_ = kwargs["Destination"]["BccAddresses"][0]
self.assertEqual(_, "")
if bcc_email_address:
bcc_email = kwargs["Destination"]["BccAddresses"][0]
self.assertEqual(bcc_email, bcc_email_address)
def test_save_model_sends_submitted_email(self):
"""When transitioning to submitted from started or withdrawn on a domain request,
an email is sent out.
When transitioning to submitted from dns needed or in review on a domain request,
no email is sent out."""
no email is sent out.
Also test that the default email set in settings is NOT BCCd on non-prod whenever
an email does go out."""
with less_console_noise():
# Ensure there is no user with this email
@ -645,7 +661,64 @@ class TestDomainApplicationAdmin(MockEppLib):
# Test Submitted Status from started
self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.SUBMITTED)
self.assert_email_is_accurate("We received your .gov domain request.", 0, EMAIL)
self.assert_email_is_accurate("We received your .gov domain request.", 0, EMAIL, True)
self.assertEqual(len(self.mock_client.EMAILS_SENT), 1)
# Test Withdrawn Status
self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.WITHDRAWN)
self.assert_email_is_accurate(
"Your .gov domain request has been withdrawn and will not be reviewed by our team.", 1, EMAIL, True
)
self.assertEqual(len(self.mock_client.EMAILS_SENT), 2)
# Test Submitted Status Again (from withdrawn)
self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.SUBMITTED)
self.assertEqual(len(self.mock_client.EMAILS_SENT), 3)
# Move it to IN_REVIEW
self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.IN_REVIEW)
self.assertEqual(len(self.mock_client.EMAILS_SENT), 3)
# Test Submitted Status Again from in IN_REVIEW, no new email should be sent
self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.SUBMITTED)
self.assertEqual(len(self.mock_client.EMAILS_SENT), 3)
# Move it to IN_REVIEW
self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.IN_REVIEW)
self.assertEqual(len(self.mock_client.EMAILS_SENT), 3)
# Move it to ACTION_NEEDED
self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.ACTION_NEEDED)
self.assertEqual(len(self.mock_client.EMAILS_SENT), 3)
# Test Submitted Status Again from in ACTION_NEEDED, no new email should be sent
self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.SUBMITTED)
self.assertEqual(len(self.mock_client.EMAILS_SENT), 3)
@override_settings(IS_PRODUCTION=True)
def test_save_model_sends_submitted_email_with_bcc_on_prod(self):
"""When transitioning to submitted from started or withdrawn on a domain request,
an email is sent out.
When transitioning to submitted from dns needed or in review on a domain request,
no email is sent out.
Also test that the default email set in settings IS BCCd on prod whenever
an email does go out."""
with less_console_noise():
# Ensure there is no user with this email
EMAIL = "mayor@igorville.gov"
User.objects.filter(email=EMAIL).delete()
BCC_EMAIL = settings.DEFAULT_FROM_EMAIL
# Create a sample application
application = completed_application()
# Test Submitted Status from started
self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.SUBMITTED)
self.assert_email_is_accurate("We received your .gov domain request.", 0, EMAIL, False, BCC_EMAIL)
self.assertEqual(len(self.mock_client.EMAILS_SENT), 1)
# Test Withdrawn Status
@ -657,6 +730,7 @@ class TestDomainApplicationAdmin(MockEppLib):
# Test Submitted Status Again (from withdrawn)
self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.SUBMITTED)
self.assert_email_is_accurate("We received your .gov domain request.", 0, EMAIL, False, BCC_EMAIL)
self.assertEqual(len(self.mock_client.EMAILS_SENT), 3)
# Move it to IN_REVIEW

View file

@ -1,31 +0,0 @@
from django.test import Client, TestCase, override_settings
from django.contrib.auth import get_user_model
class MyTestCase(TestCase):
def setUp(self):
self.client = Client()
username = "test_user"
first_name = "First"
last_name = "Last"
email = "info@example.com"
self.user = get_user_model().objects.create(
username=username, first_name=first_name, last_name=last_name, email=email
)
self.client.force_login(self.user)
def tearDown(self):
super().tearDown()
self.user.delete()
@override_settings(IS_PRODUCTION=True)
def test_production_environment(self):
"""No banner on prod."""
home_page = self.client.get("/")
self.assertNotContains(home_page, "You are on a test site.")
@override_settings(IS_PRODUCTION=False)
def test_non_production_environment(self):
"""Banner on non-prod."""
home_page = self.client.get("/")
self.assertContains(home_page, "You are on a test site.")

View file

@ -1,4 +1,4 @@
from django.test import Client, TestCase
from django.test import Client, TestCase, override_settings
from django.contrib.auth import get_user_model
from .common import MockEppLib # type: ignore
@ -50,3 +50,32 @@ class TestWithUser(MockEppLib):
DomainApplication.objects.all().delete()
DomainInformation.objects.all().delete()
self.user.delete()
class TestEnvironmentVariablesEffects(TestCase):
def setUp(self):
self.client = Client()
username = "test_user"
first_name = "First"
last_name = "Last"
email = "info@example.com"
self.user = get_user_model().objects.create(
username=username, first_name=first_name, last_name=last_name, email=email
)
self.client.force_login(self.user)
def tearDown(self):
super().tearDown()
self.user.delete()
@override_settings(IS_PRODUCTION=True)
def test_production_environment(self):
"""No banner on prod."""
home_page = self.client.get("/")
self.assertNotContains(home_page, "You are on a test site.")
@override_settings(IS_PRODUCTION=False)
def test_non_production_environment(self):
"""Banner on non-prod."""
home_page = self.client.get("/")
self.assertContains(home_page, "You are on a test site.")

View file

@ -15,7 +15,7 @@ class EmailSendingError(RuntimeError):
pass
def send_templated_email(template_name: str, subject_template_name: str, to_address: str, context={}):
def send_templated_email(template_name: str, subject_template_name: str, to_address: str, bcc_address="", context={}):
"""Send an email built from a template to one email address.
template_name and subject_template_name are relative to the same template
@ -40,10 +40,14 @@ def send_templated_email(template_name: str, subject_template_name: str, to_addr
except Exception as exc:
raise EmailSendingError("Could not access the SES client.") from exc
destination = {"ToAddresses": [to_address]}
if bcc_address:
destination["BccAddresses"] = [bcc_address]
try:
ses_client.send_email(
FromEmailAddress=settings.DEFAULT_FROM_EMAIL,
Destination={"ToAddresses": [to_address]},
Destination=destination,
Content={
"Simple": {
"Subject": {"Data": subject},

View file

@ -14,6 +14,7 @@ from django.http import HttpResponseRedirect
from django.shortcuts import redirect
from django.urls import reverse
from django.views.generic.edit import FormMixin
from django.conf import settings
from registrar.models import (
Domain,
@ -707,7 +708,7 @@ class DomainAddUserView(DomainFormBaseView):
adding a success message to the view if the email sending succeeds"""
# Set a default email address to send to for staff
requestor_email = "help@get.gov"
requestor_email = settings.DEFAULT_FROM_EMAIL
# Check if the email requestor has a valid email address
if not requestor.is_staff and requestor.email is not None and requestor.email.strip() != "":