mail_backends.py 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. import logging
  2. from celery import shared_task
  3. from django.conf import settings
  4. from django.core.mail import get_connection
  5. from django.core.mail.backends.base import BaseEmailBackend
  6. from djcelery_email.utils import dict_to_email, email_to_dict
  7. from desecapi import metrics
  8. logger = logging.getLogger(__name__)
  9. class MultiLaneEmailBackend(BaseEmailBackend):
  10. config = {"ignore_result": True}
  11. default_backend = "django.core.mail.backends.smtp.EmailBackend"
  12. def __init__(self, lane: str = None, fail_silently=False, **kwargs):
  13. lane = lane or next(iter(settings.TASK_CONFIG))
  14. self.config.update(name=lane, queue=lane)
  15. self.config.update(settings.TASK_CONFIG[lane])
  16. self.task_kwargs = kwargs.copy()
  17. # Make a copy to ensure we don't modify input dict when we set the 'lane'
  18. self.task_kwargs["debug"] = self.task_kwargs.pop("debug", {}).copy()
  19. self.task_kwargs["debug"]["lane"] = lane
  20. super().__init__(fail_silently)
  21. def send_messages(self, email_messages):
  22. dict_messages = [email_to_dict(msg) for msg in email_messages]
  23. TASKS[self.config["name"]].delay(dict_messages, **self.task_kwargs)
  24. return len(email_messages)
  25. @staticmethod
  26. def _run_task(messages, debug, **kwargs):
  27. logger.warning("Sending queued email, details: %s", debug)
  28. kwargs.setdefault(
  29. "backend", kwargs.pop("backbackend", MultiLaneEmailBackend.default_backend)
  30. )
  31. with get_connection(**kwargs) as connection:
  32. return connection.send_messages(
  33. [dict_to_email(message) for message in messages]
  34. )
  35. @property
  36. def task(self):
  37. return shared_task(**self.config)(self._run_task)
  38. # Define tasks so that Celery can discovery them
  39. TASKS = {
  40. name: MultiLaneEmailBackend(lane=name, fail_silently=True).task
  41. for name in settings.TASK_CONFIG
  42. if name.startswith("email_")
  43. }