import typing import base64 from smtplib import SMTPException, SMTPResponseException from flask import Markup from flask_mail import Message from core_notifications.extensions import mail, celery from core_notifications.helpers.common import split_long_lines, replace_urls from core_notifications.logs import logger from core_notifications.settings import Settings @celery.task( bind=True, default_retry_delay=Settings.TASK_RETRY_DELAY, retry_kwargs={"max_retries": Settings.TASK_MAX_RETRIES}, ) def send_email_task( self, subject: str, to: str, body: str, analytic_url: str, analytics: dict, cc: typing.Optional[typing.List[str]] = None, attachments: typing.Optional[typing.List] = None, track_clicks: bool = False, ): logger.bind(to=to, subject=subject, cc=cc).info("Sending email") if cc: cc = cc if isinstance(cc, list) else [cc] if track_clicks: body = replace_urls( body=body, email_id=self.request.id, to=to, analytic_url=analytic_url, **analytics, ) # Do all body processing before the splitting the long lines! text_body = split_long_lines( Markup(body).striptags(), Settings.MAX_LINE_LENGTH ) html_body = split_long_lines(body, Settings.MAX_LINE_LENGTH) msg = Message( subject=subject, recipients=[to], body=text_body, html=html_body, sender=Settings.MAIL_DEFAULT_SENDER, extra_headers={ "X-SES-CONFIGURATION-SET": Settings.MAIL_CONFIGURATION_SET }, cc=cc, ) if attachments: for attachment in attachments: msg.attach( attachment["filename"], attachment["filetype"], base64.b64decode(attachment["base64_data"]), ) try: mail.send(msg) except SMTPResponseException as exc: # Reaching sending limits (AWS Throttling failure) if exc.smtp_code == 454: logger.bind(to=to, subject=subject, cc=cc, exc=exc).warning( "Reaching sending limits" ) raise self.retry( exc=exc, countdown=Settings.TASK_REACHING_LIMITS_RETRY_DELAY ) else: raise self.retry(exc=exc) except SMTPException as exc: raise self.retry(exc=exc)