"""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}]' )