"""Send SES email w/ attachment."""
from datetime import datetime
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import os
from pathlib import Path
import boto3
GENERATION_DATE_FORMAT = '%Y-%m-%d %H:%M %z'
BODY_TEXT = """Attention All,
The {report_type} Report was generated at {generated_at} with the options:
- Period ID(s): {period_ids}
- Payment Interval: {payment_interval}
Please see the attached file: {file_path}
Report any errors to:
accounting-run-watchers-tech@theorchard.com
"""
BODY_HTML = """
{body}
"""
EMAIL_SUBJECT = (
'Report Generation Notice: {report_full_name}'
)
class TaxReportEmail:
"""Tax Report Email Sender."""
def __init__(
self,
file_path,
from_email,
to_emails,
payment_interval,
period_ids,
charset='utf-8'
):
"""Store variables."""
self._report_type = 'Tax Withholding'
self._file_path = file_path
self._from_email = from_email
self._to_emails = to_emails
self._charset = charset
self._generated_at = datetime.now()
self._payment_interval = payment_interval
self._period_ids = period_ids
self._message = MIMEMultipart('mixed')
def build_message_body(self):
"""Build a plain text and HTML version of the email."""
body_part = MIMEMultipart('alternative')
body_text = BODY_TEXT.format(
file_path=self._file_path,
generated_at=self._generated_at,
report_type=self._report_type,
period_ids=self._period_ids,
payment_interval=self._payment_interval
)
encoded_body_text = body_text.encode(self._charset)
self.attach_text(encoded_body_text, 'plain', body_part)
body_html = BODY_HTML.format(
body='
'.join(body_text.split('\n'))
).encode(self._charset)
self.attach_text(body_html, 'html', body_part)
self._message.attach(body_part)
def build_message_attachment(self):
"""Build the file attachment for the email."""
file_contents = Path(self._file_path).read_bytes()
filename = os.path.basename(self._file_path)
attachment_part = MIMEApplication(file_contents)
attachment_part.add_header(
'Content-Disposition',
'attachment',
filename=filename
)
self._message.attach(attachment_part)
def build_message_subject(self):
"""Template out the email subject line."""
return EMAIL_SUBJECT.format(
report_full_name=self.get_report_name(),
period_ids=self._period_ids,
generated_at=self.get_generated_at()
)
def build_email(self):
"""Email the zipped reports to the configured recipients."""
self._message['Subject'] = self.build_message_subject()
self._message['From'] = self._from_email
self._message['To'] = ','.join(self._to_emails)
self.build_message_body()
self.build_message_attachment()
def trigger_email(self):
"""Send the email via SES."""
return boto3.client('ses').send_raw_email(
RawMessage={'Data': self._message.as_string()},
Source=self._from_email,
Destinations=self._to_emails
)
def attach_text(self, template, part_type, part):
"""Attach a text part to the message."""
part_text = template.decode(self._charset)
mime_text = MIMEText(part_text, part_type, self._charset)
part.attach(mime_text)
def get_generated_at(self):
"""Get the generated_at datetime as a formatted string."""
return self._generated_at.strftime(GENERATION_DATE_FORMAT)
def get_report_name(self):
"""Template out the report name."""
return (
f'{self._report_type}: '
f'interval[{self._payment_interval}]+'
f'periods[{self._period_ids}]'
)