"""email factor tasks""" from smtplib import SMTPException from typing import Any, Dict, List from celery import group from django.core.mail import EmailMessage from structlog import get_logger from passbook.factors.email.models import EmailFactor from passbook.root.celery import CELERY_APP LOGGER = get_logger() def send_mails(factor: EmailFactor, *messages: List[EmailMessage]): """Wrapper to convert EmailMessage to dict and send it from worker""" tasks = [] for message in messages: tasks.append(_send_mail_task.s(factor.pk, message.__dict__)) lazy_group = group(*tasks) promise = lazy_group() return promise @CELERY_APP.task(bind=True) def _send_mail_task(self, email_factor_pk: int, message: Dict[Any, Any]): """Send E-Mail according to EmailFactor parameters from background worker. Automatically retries if message couldn't be sent.""" factor: EmailFactor = EmailFactor.objects.get(pk=email_factor_pk) backend = factor.backend backend.open() # Since django's EmailMessage objects are not JSON serialisable, # we need to rebuild them from a dict message_object = EmailMessage() for key, value in message.items(): setattr(message_object, key, value) message_object.from_email = factor.from_address LOGGER.debug("Sending mail", to=message_object.to) try: num_sent = factor.backend.send_messages([message_object]) except SMTPException as exc: raise self.retry(exc=exc) if num_sent != 1: raise self.retry()