manage.get.gov/src/registrar/utility/email.py
2024-03-13 08:48:25 -07:00

105 lines
3.5 KiB
Python

"""Utilities for sending emails."""
import boto3
import logging
from datetime import datetime
from django.conf import settings
from django.template.loader import get_template
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
logger = logging.getLogger(__name__)
class EmailSendingError(RuntimeError):
"""Local error for handling all failures when sending email."""
pass
def send_templated_email(
template_name: str,
subject_template_name: str,
to_address: str,
bcc_address="",
context={},
attachment_file: str = None,
):
"""Send an email built from a template to one email address.
template_name and subject_template_name are relative to the same template
context as Django's HTML templates. context gives additional information
that the template may use.
"""
logger.info(f"An email was sent! Template name: {template_name} to {to_address}")
template = get_template(template_name)
email_body = template.render(context=context)
subject_template = get_template(subject_template_name)
subject = subject_template.render(context=context)
try:
ses_client = boto3.client(
"sesv2",
region_name=settings.AWS_REGION,
aws_access_key_id=settings.AWS_ACCESS_KEY_ID,
aws_secret_access_key=settings.AWS_SECRET_ACCESS_KEY,
config=settings.BOTO_CONFIG,
)
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:
if attachment_file is None:
ses_client.send_email(
FromEmailAddress=settings.DEFAULT_FROM_EMAIL,
Destination=destination,
Content={
"Simple": {
"Subject": {"Data": subject},
"Body": {"Text": {"Data": email_body}},
},
},
)
else:
ses_client = boto3.client(
"ses",
region_name=settings.AWS_REGION,
aws_access_key_id=settings.AWS_ACCESS_KEY_ID,
aws_secret_access_key=settings.AWS_SECRET_ACCESS_KEY,
config=settings.BOTO_CONFIG,
)
send_email_with_attachment(
settings.DEFAULT_FROM_EMAIL, to_address, subject, email_body, attachment_file, ses_client
)
except Exception as exc:
raise EmailSendingError("Could not send SES email.") from exc
def send_email_with_attachment(sender, recipient, subject, body, attachment_file, ses_client):
# Create a multipart/mixed parent container
msg = MIMEMultipart("mixed")
msg["Subject"] = subject
msg["From"] = sender
msg["To"] = recipient
# Add the text part
text_part = MIMEText(body, "plain")
msg.attach(text_part)
# Add the attachment part
attachment_part = MIMEApplication(attachment_file)
# Adding attachment header + filename that the attachment will be called
current_date = datetime.now().strftime("%m%d%Y")
current_filename = f"domain-metadata-{current_date}.zip"
attachment_part.add_header("Content-Disposition", f'attachment; filename="{current_filename}"')
msg.attach(attachment_part)
response = ses_client.send_raw_email(Source=sender, Destinations=[recipient], RawMessage={"Data": msg.as_string()})
return response