From 105220a2ce5c2501dc3ca5982f69057559c8aee9 Mon Sep 17 00:00:00 2001 From: jar3b Date: Wed, 5 Dec 2018 20:03:04 +0300 Subject: [PATCH] Add message sending logic --- README.md | 12 ++++++++--- queued_mailer/backend.py | 6 ++++-- queued_mailer/exceptions.py | 2 ++ queued_mailer/tasks.py | 41 +++++++++++++++++++++++++++++-------- queued_mailer/utils.py | 7 +++++++ 5 files changed, 54 insertions(+), 14 deletions(-) create mode 100644 queued_mailer/exceptions.py create mode 100644 queued_mailer/utils.py diff --git a/README.md b/README.md index c3cb4c8..edf6251 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,15 @@ Django >= 1.11, Celery >= 4.1.1 ### setup -- add `git+https://github.com/jar3b/django-queued-mailer.git` to requirements.txt -- install package `pip install --upgrade git+https://github.com/jar3b/django-queued-mailer.git` -- run celery worker +- Add `git+https://github.com/jar3b/django-queued-mailer.git` to requirements.txt +- Install package `pip install --upgrade git+https://github.com/jar3b/django-queued-mailer.git` +- Modify Django settings: set proper email backend + +``` +EMAIL_BACKEND = 'queued_mailer.backend.EmailBackend' +``` + +- Run celery worker ``` celery -A project worker diff --git a/queued_mailer/backend.py b/queued_mailer/backend.py index ca6914c..0ea0d8f 100644 --- a/queued_mailer/backend.py +++ b/queued_mailer/backend.py @@ -1,10 +1,10 @@ # coding: utf-8 - from django.core.mail.backends.base import BaseEmailBackend from django.utils.encoding import force_text from .logger import logger from .tasks import send_message +from .utils import get_email_connection def _get_message_recipients(email_message): @@ -20,9 +20,11 @@ class EmailBackend(BaseEmailBackend): def send_messages(self, email_messages): num_sent = 0 + connection = get_email_connection() + for email in email_messages: try: - send_message.apply_async([email, ]) + send_message.apply_async([email, connection]) num_sent += 1 except Exception as e: logger.error("cannot send message %s: %r" % (_get_message_recipients(email), e)) diff --git a/queued_mailer/exceptions.py b/queued_mailer/exceptions.py new file mode 100644 index 0000000..82dc030 --- /dev/null +++ b/queued_mailer/exceptions.py @@ -0,0 +1,2 @@ +class EmailTransportException(Exception): + pass diff --git a/queued_mailer/tasks.py b/queued_mailer/tasks.py index 5737464..e3a2e49 100644 --- a/queued_mailer/tasks.py +++ b/queued_mailer/tasks.py @@ -1,21 +1,44 @@ # coding: utf-8 - -from time import sleep +import smtplib +import time +from socket import error as socket_error import celery from celery.utils.log import get_task_logger +from django.core.mail import EmailMessage +from queued_mailer.utils import get_email_connection +from .exceptions import EmailTransportException from .settings import TASK_QUEUE_NAME logger = get_task_logger(__name__) -@celery.task(bind=True, queue=TASK_QUEUE_NAME, acks_late=True, default_retry_delay=30) -def send_message(self, email): - logger.warning('task started') +@celery.task(bind=True, queue=TASK_QUEUE_NAME, acks_late=True, + default_retry_delay=20, autoretry_for=(EmailTransportException,), retry_kwargs={'max_retries': 5}) +def send_message(self, email, connection=None): + logger.debug('task started') + + start_time = time.time() + + if not isinstance(email, EmailMessage): + raise Exception('Invalid message class, only django.core.mail.EmailMessage is supported') + try: - sleep(5) - logger.warning('task success') + if connection is None: + connection = get_email_connection() + + email.connection = connection + email.send() + except (socket_error, smtplib.SMTPSenderRefused, + smtplib.SMTPRecipientsRefused, + smtplib.SMTPDataError, + smtplib.SMTPAuthenticationError) as e: + logger.warning('message transport failure: %r' % e) + raise EmailTransportException(e) except Exception as e: - logger.warning('task error') - raise self.retry(exc=e) + logger.error('message send error: %r' % e) + raise + + elapsed_time = time.time() - start_time + logger.warning("message sent, elasped time %s" % elapsed_time) diff --git a/queued_mailer/utils.py b/queued_mailer/utils.py new file mode 100644 index 0000000..66fc336 --- /dev/null +++ b/queued_mailer/utils.py @@ -0,0 +1,7 @@ +from django.core.mail import get_connection + +from .settings import EMAIL_BACKEND + + +def get_email_connection(): + return get_connection(backend=EMAIL_BACKEND)