Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-django-mailer for openSUSE:Factory checked in at 2022-05-10 15:12:43 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-django-mailer (Old) and /work/SRC/openSUSE:Factory/.python-django-mailer.new.1538 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-django-mailer" Tue May 10 15:12:43 2022 rev:4 rq:976037 version:2.2 Changes: -------- --- /work/SRC/openSUSE:Factory/python-django-mailer/python-django-mailer.changes 2022-01-07 12:48:04.655916133 +0100 +++ /work/SRC/openSUSE:Factory/.python-django-mailer.new.1538/python-django-mailer.changes 2022-05-10 15:13:02.455654034 +0200 @@ -1,0 +2,13 @@ +Mon May 9 15:45:01 UTC 2022 - pgaj...@suse.com + +- version update to 2.2 + * Migrate models ``id`` fields to ``BigAutoField``. + * Add ``runmailer`` management command. This command starts a loop that + * Added ``runmailer`` management command. This command starts a loop that + frequently checks the database for new emails. The wait time between + checks can be controlled using the ``MAILER_EMPTY_QUEUE_SLEEP`` setting. +- added patches + fix https://github.com/pinax/django-mailer/issues/157 + + python-django-mailer-no-mock.patch + +------------------------------------------------------------------- Old: ---- django-mailer-2.1.tar.gz New: ---- django-mailer-2.2.tar.gz python-django-mailer-no-mock.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-django-mailer.spec ++++++ --- /var/tmp/diff_new_pack.HDwZ3k/_old 2022-05-10 15:13:02.943654649 +0200 +++ /var/tmp/diff_new_pack.HDwZ3k/_new 2022-05-10 15:13:02.951654659 +0200 @@ -19,13 +19,15 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} %define skip_python36 1 Name: python-django-mailer -Version: 2.1 +Version: 2.2 Release: 0 Summary: A reusable Django app for queuing the sending of email License: MIT Group: Development/Languages/Python URL: https://github.com/pinax/django-mailer/ Source: https://files.pythonhosted.org/packages/source/d/django-mailer/django-mailer-%{version}.tar.gz +# https://github.com/pinax/django-mailer/issues/157 +Patch0: python-django-mailer-no-mock.patch BuildRequires: %{python_module setuptools} BuildRequires: fdupes BuildRequires: python-rpm-macros @@ -36,7 +38,6 @@ # SECTION test requirements BuildRequires: %{python_module Django >= 1.11} BuildRequires: %{python_module lockfile >= 0.8} -BuildRequires: %{python_module mock} BuildRequires: %{python_module six} # /SECTION %python_subpackages @@ -47,6 +48,7 @@ %prep %setup -q -n django-mailer-%{version} +%patch0 -p1 %build %python_build ++++++ django-mailer-2.1.tar.gz -> django-mailer-2.2.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-mailer-2.1/.travis.yml new/django-mailer-2.2/.travis.yml --- old/django-mailer-2.1/.travis.yml 2020-10-11 19:47:09.000000000 +0200 +++ new/django-mailer-2.2/.travis.yml 1970-01-01 01:00:00.000000000 +0100 @@ -1,45 +0,0 @@ -language: python -python: 2.7 -env: - - TOXENV=checkmanifest - -matrix: - include: - - python: 2.7 - env: TOXENV=py27-django111-test - - python: 2.7 - env: TOXENV=py27-flake - - python: 3.4 - env: TOXENV=py34-django111-test - - python: 3.4 - env: TOXENV=py34-django20-test - - python: 3.4 - env: TOXENV=py34-flake - - python: 3.5 - env: TOXENV=py35-django111-test - - python: 3.5 - env: TOXENV=py35-django20-test - - python: 3.5 - env: TOXENV=py35-flake - - python: 3.6 - env: TOXENV=py36-django111-test - - python: 3.6 - env: TOXENV=py36-django20-test - - python: 3.6 - env: TOXENV=py36-django21-test - - python: 3.6 - env: TOXENV=py36-django22-test - - python: 3.6 - env: TOXENV=py36-django30-test - - python: 3.8 - env: TOXENV=py38-django31-test - - python: 3.8 - env: TOXENV=py38-flake - -install: - - pip install coveralls tox>=2.1 -script: - - tox -after_script: - - coveralls -sudo: false diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-mailer-2.1/AUTHORS new/django-mailer-2.2/AUTHORS --- old/django-mailer-2.1/AUTHORS 2020-12-05 11:39:47.000000000 +0100 +++ new/django-mailer-2.2/AUTHORS 2021-02-24 08:13:08.000000000 +0100 @@ -13,3 +13,4 @@ * Renato Alves * Paul Brown * Sebastian Pipping + * Jaap Roes diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-mailer-2.1/CHANGES.rst new/django-mailer-2.2/CHANGES.rst --- old/django-mailer-2.1/CHANGES.rst 2020-12-05 11:54:27.000000000 +0100 +++ new/django-mailer-2.2/CHANGES.rst 2022-03-11 18:05:44.000000000 +0100 @@ -1,6 +1,15 @@ Change log ========== +2.2 - 2022-03-11 +---------------- + +* Migrate models ``id`` fields to ``BigAutoField``. +* Add ``runmailer`` management command. This command starts a loop that +* Added ``runmailer`` management command. This command starts a loop that + frequently checks the database for new emails. The wait time between + checks can be controlled using the ``MAILER_EMPTY_QUEUE_SLEEP`` setting. + 2.1 - 2020-12-05 ---------------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-mailer-2.1/CONTRIBUTING.rst new/django-mailer-2.2/CONTRIBUTING.rst --- old/django-mailer-2.1/CONTRIBUTING.rst 2015-07-04 16:03:57.000000000 +0200 +++ new/django-mailer-2.2/CONTRIBUTING.rst 2021-02-24 08:13:08.000000000 +0100 @@ -59,7 +59,7 @@ ------------- Please keep your pull requests focused on one specific thing only. If you -have a number of contributions to make, then please send seperate pull +have a number of contributions to make, then please send separate pull requests. It is much easier on maintainers to receive small, well defined, pull requests, than it is to have a single large one that batches up a lot of unrelated commits. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-mailer-2.1/MANIFEST.in new/django-mailer-2.2/MANIFEST.in --- old/django-mailer-2.1/MANIFEST.in 2019-09-23 19:24:14.000000000 +0200 +++ new/django-mailer-2.2/MANIFEST.in 2021-09-24 09:45:34.000000000 +0200 @@ -3,9 +3,10 @@ include *.rst include MANIFEST.in include .coveragerc -include tox.ini .travis.yml +include tox.ini include *.py include *.sh +include *.txt graft docs graft src diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-mailer-2.1/PKG-INFO new/django-mailer-2.2/PKG-INFO --- old/django-mailer-2.1/PKG-INFO 2020-12-05 11:56:51.692757600 +0100 +++ new/django-mailer-2.2/PKG-INFO 2022-03-11 18:06:43.301470300 +0100 @@ -1,359 +1,11 @@ -Metadata-Version: 1.1 +Metadata-Version: 2.1 Name: django-mailer -Version: 2.1 +Version: 2.2 Summary: A reusable Django app for queuing the sending of email Home-page: http://github.com/pinax/django-mailer/ Author: Pinax Team Author-email: develop...@pinaxproject.com License: UNKNOWN -Description: ===== - Usage - ===== - - First, add "mailer" to your ``INSTALLED_APPS`` in your settings.py. - Run ``./manage.py migrate`` to install models. - - Using EMAIL_BACKEND - =================== - - This is the preferred and easiest way to use django-mailer. - - To automatically switch all your mail to use django-mailer, first set - EMAIL_BACKEND:: - - EMAIL_BACKEND = "mailer.backend.DbBackend" - - If you were previously using a non-default EMAIL_BACKEND, you need to configure - the MAILER_EMAIL_BACKEND setting, so that django-mailer knows how to actually send - the mail:: - - MAILER_EMAIL_BACKEND = "your.actual.EmailBackend" - - Now, just use the normal `Django mail functions - <https://docs.djangoproject.com/en/stable/topics/email/>`_ for sending email. These - functions will store mail on a queue in the database, which must be sent as - below. - - Explicitly putting mail on the queue - ==================================== - - If you don't want to send all email through django-mailer, you can send mail - using ``mailer.send_mail``, which has the same signature as Django's - ``send_mail`` function. - - You can also do the following:: - - # favour django-mailer but fall back to django.core.mail - from django.conf import settings - - if "mailer" in settings.INSTALLED_APPS: - from mailer import send_mail - else: - from django.core.mail import send_mail - - and then just call send_mail like you normally would in Django:: - - send_mail(subject, message_body, settings.DEFAULT_FROM_EMAIL, recipients) - - There is also a convenience function ``mailer.send_html_mail`` for creating HTML - (this function is **not** in Django):: - - send_html_mail(subject, message_plaintext, message_html, settings.DEFAULT_FROM_EMAIL, recipients) - - Additionally you can send all the admins as specified in the ``ADMIN`` - setting by calling:: - - mail_admins(subject, message_body) - - or all managers as defined in the ``MANAGERS`` setting by calling:: - - mail_managers(subject, message_body) - - Clear queue with command extensions - =================================== - - With mailer in your INSTALLED_APPS, there will be three new manage.py commands - you can run: - - * ``send_mail`` will clear the current message queue. If there are any - failures, they will be marked deferred and will not be attempted again by - ``send_mail``. - - * ``retry_deferred`` will move any deferred mail back into the normal queue - (so it will be attempted again on the next ``send_mail``). - - * ``purge_mail_log`` will remove old successful message logs from the database, to prevent it from filling up your database. - Use the ``-r failure`` option to remove only failed message logs instead, or ``-r all`` to remove them all. - - - You may want to set these up via cron to run regularly:: - - - * * * * * (/path/to/your/python /path/to/your/manage.py send_mail >> ~/cron_mail.log 2>&1) - 0,20,40 * * * * (/path/to/your/python /path/to/your/manage.py retry_deferred >> ~/cron_mail_deferred.log 2>&1) - 0 0 * * * (/path/to/your/python /path/to/your/manage.py purge_mail_log 7 >> ~/cron_mail_purge.log 2>&1) - - For use in Pinax, for example, that might look like:: - - * * * * * (cd $PINAX; /usr/local/bin/python2.5 manage.py send_mail >> $PINAX/cron_mail.log 2>&1) - 0,20,40 * * * * (cd $PINAX; /usr/local/bin/python2.5 manage.py retry_deferred >> $PINAX/cron_mail_deferred.log 2>&1) - 0 0 * * * (cd $PINAX; /usr/local/bin/python2.5 manage.py purge_mail_log 7 >> $PINAX/cron_mail_purge.log 2>&1) - - This attempts to send mail every minute with a retry on failure every 20 - minutes, and purges the mail log for entries older than 7 days. - - ``manage.py send_mail`` uses a lock file in case clearing the queue takes - longer than the interval between calling ``manage.py send_mail``. - - Note that if your project lives inside a virtualenv, you also have to execute - this command from the virtualenv. The same, naturally, applies also if you're - executing it with cron. The `Pinax documentation`_ explains that in more - details. - - .. _pinax documentation: http://pinaxproject.com/docs/dev/deployment.html#sending-mail-and-notices - - Controlling the delivery process - ================================ - - If you wish to have a finer control over the delivery process, which defaults - to deliver everything in the queue, you can use the following 3 variables - (default values shown):: - - MAILER_EMAIL_MAX_BATCH = None # integer or None - MAILER_EMAIL_MAX_DEFERRED = None # integer or None - MAILER_EMAIL_THROTTLE = 0 # passed to time.sleep() - - These control how many emails are sent successfully before stopping the - current run `MAILER_EMAIL_MAX_BATCH`, after how many failed/deferred emails - should it stop `MAILER_EMAIL_MAX_DEFERRED` and how much time to wait between - each email `MAILER_EMAIL_THROTTLE`. - - Unprocessed emails will be evaluated in the following delivery iterations. - - Error handling - ============== - - django-mailer comes with a default error handler - ``mailer.engine.handle_delivery_exception``. - - It marks the related message as deferred for any of these exceptions: - - - ``smtplib.SMTPAuthenticationError`` - - ``smtplib.SMTPDataError`` - - ``smtplib.SMTPRecipientsRefused`` - - ``smtplib.SMTPSenderRefused`` - - ``socket.error`` - - Any other exceptions is re-raised. - That is done for backwords-compatiblity as well as for flexibility: - we would otherwise have to maintain an extensive and changing - list of exception types, which does not scale, and you get - the chance to do error handling that fits your environment like a glove. - - When the default behavior does not fit your environment, you can specify your - own custom delivery error handler through setting ``MAILER_ERROR_HANDLER``. - The value should be a string for use with Django's ``import_string``, - the default is ``"mailer.engine.handle_delivery_exception"``. - - Your handler is passed three arguments, in order: - - - ``connection`` ??? the backend connection instance that failed delivery - - ``message`` ??? the ``Message`` instance that failed delivery - - ``exc`` ??? the exception instance raised by the mailer backend - - Your handler should return a 2-tuple of: - - 1. a connection instance (or ``None`` to cause a new connection to be created) - 2. a string denoting the action taken by the handler, - either ``"sent"`` or ``"deferred"`` precisely - - For an example of a custom error handler:: - - def my_handler(connection, message, exc): - if isinstance(exc, SomeDeliveryException): - # trying to re-send this very message desparately - # (if you have good reason to) - [..] - status = 'sent' - elif isinstance(exc, SomeOtherException): - message.defer() - connection = None # i.e. ask for a new connection - status = 'deferred' - else: - six.reraise(*sys.exc_info()) - - return connection, status - - Other settings - ============== - - If you need to be able to control where django-mailer puts its lock file (used - to ensure mail is not sent twice), you can set ``MAILER_LOCK_PATH`` to a full - absolute path to the file to be used as a lock. The extension ".lock" will be - added. The process running ``send_mail`` needs to have permissions to create and - delete this file, and others in the same directory. With the default value of - ``None`` django-mailer will use a path in current working directory. - - If you need to disable the file-based locking, you can set the - ``MAILER_USE_FILE_LOCK`` setting to ``False``. - - If you need to change the batch size used by django-mailer to save messages in - ``mailer.backend.DbBackend``, you can set ``MAILER_MESSAGES_BATCH_SIZE`` to a - value more suitable for you. This value, which defaults to `None`, will be passed to - `Django's bulk_create method <https://docs.djangoproject.com/en/stable/ref/models/querysets/#bulk-create>`_ - as the `batch_size` parameter. - - Using the DontSendEntry table - ============================= - - django-mailer creates a ``DontSendEntry`` model, which is used to filter out - recipients from messages being created. - - But beware, it's actually only used when directly sending messages through - mailer, not when mailer is used as an alternate ``EMAIL_BACKEND`` for Django. - Also, even if recipients become empty due to this filtering, the email will be - queued for sending anyway. (A patch to fix these issues would be accepted) - Change log - ========== - - 2.1 - 2020-12-05 - ---------------- - - * The ``retry_deferred`` and ``send_mail`` commands rely on the log level set - in your django project now. The ``-c/--cron`` option in those commands has - been deprecated and the logic to configure log levels and the message - format has been removed. - * Changed logging to use module specific loggers to avoid interfering - with other loggers. - * Added ``MAILER_USE_FILE_LOCK`` setting to allow disabling file based locking. - * Added ``-r`` option to ``purge_mail_log`` management command. Thanks julienc91 - * Fixed deprecation warnings on Django 3.1 - * Use cached DNS_NAME for performance - * Added ability to override the default error handler via the ``MAILER_ERROR_HANDLER`` - settings key - - 2.0.1 - 2020-03-01 - ------------------ - - * Fixed issue with migration that some people experienced (see `PR 118 - <https://github.com/pinax/django-mailer/pull/118>`_) - - 2.0 - 2019-09-23 - ---------------- - - * Django 3.0 support - * Dropped support for old Django versions (before 1.11) - * Changed DB ``priority`` field to an integer, instead of text field container an integer - * Multi-process safety for sending emails via database row-level locking. - - Previously, there was a file-system based lock to ensure that multiple - processes were not attempting to send the mail queue, to stop multiple sending - of the same email. However, this mechanism only works if all processes that - might be attempting to do this are on the same machine with access to the same - file-system. - - Now, in addition to this file lock, we use transactions and row-level locking - in the database when attempting to send a message, which guarantees that only - one process can send the message. In addition, for databases that support - ``NOWAIT`` with ``SELECT FOR UPDATE``, such as PostgreSQL, if multiple - processes attempt to send the mail queue at the same time, the work should be - distributed between them (rather than being done by only one process). - - A negative consequence is that **SQLite support is degraded**: due to the way - it implements locking and our use of transactions when sending the email - queue, you can get exceptions in other processes that are trying to add items - to the queue. Use of SQLite with django-mailer is **not recommended**. - - * ``retry_deferred`` command has also been updated to be simpler and work - correctly for multiple processes. - - * Dropped some backwards compat support for Django < 1.8. If you are upgrading - from a version of Django before 1.8, you should install a version of - django-mailer < 2.0, do ``send_all`` to flush the queue, then upgrade - django-mailer to 2.0 or later. - - 1.2.6 - 2019-04-03 - ------------------ - - * Official Django 2.1 and 2.2 support. - * Don't close DB connection in management commands. - This is unnecessary with modern Django. - - 1.2.5 - ----- - - * Fixed packaging file permission problems. - * Added Japanese locale (thanks msk7777) - - 1.2.4 - ----- - - * Django 2.0 support. - - 1.2.3 - ----- - - * Fixed crasher with models ``__str__`` - - 1.2.2 - ----- - - * Django 1.10 support. - * Fixed reprs for Message and MessageLog. - - 1.2.1 - ----- - - * More helpful admin for Message and MessageLog - * Handle exceptions from really old Django versions - - 1.2.0 - ----- - - * Save the ``Message-ID`` header on ``Message`` explicitly to enable finding - emails using this identifier. - - This includes a database schema migration. - - - 1.1.0 - ----- - - * Deprecated calling ``send_mail`` and ``send_html_mail`` using ``priority`` - kwargs ``"high"``, ``"medium"``, and ``"low"``. Instead you should use - ``PRIORITY_HIGH``, ``PRIORITY_MEDIUM`` and ``PRIORITY_LOW`` from - ``mailer.models``. - - * Fixed bug with migrations for Django 1.7, which wanted to create a migration - to 'fix' the EmailField length back down to 75 instead of 254. - - - 1.0.1 - ----- - - * Included migrations - for both South and Django 1.7 native migrations. - - Note: - - * If you use South, you will need at least South 1.0 - * You will need to use '--fake' or '--fake-initial' on existing installations. - - These migrations were supposed to be in 1.0.0 but were omitted due to a - packaging error. - - 1.0.0 - ----- - - * Throttling of email sending - * Django 1.8 support - * Admin tweaks and improvements - * Various other fixes, especially from Renato Alves <alves....@gmail.com> - thank you! - - 0.1.0 - ----- - - * First PyPI version - Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Web Environment @@ -368,4 +20,16 @@ Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 Classifier: Framework :: Django +License-File: LICENSE +License-File: AUTHORS + +``django-mailer`` is a reusable Django app for queuing the sending of email. +It works by storing email in the database for later sending. +The main reason for doing this is that for many apps, the database will be +much more reliable and faster than other email sending backends which require +3rd party services e.g. SMTP or an HTTP API. By storing and sending later, we can +return succeed immediately, and then attempt actual email sending in the background, +with retries if needed. + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-mailer-2.1/README.rst new/django-mailer-2.2/README.rst --- old/django-mailer-2.1/README.rst 2020-10-11 18:34:19.000000000 +0200 +++ new/django-mailer-2.2/README.rst 2021-09-24 09:44:21.000000000 +0200 @@ -4,8 +4,8 @@ .. image:: http://slack.pinaxproject.com/badge.svg :target: http://slack.pinaxproject.com/ -.. image:: https://img.shields.io/travis/pinax/django-mailer.svg - :target: https://travis-ci.org/pinax/django-mailer +.. image:: https://github.com/pinax/django-mailer/actions/workflows/build.yml/badge.svg + :target: https://github.com/pinax/django-mailer/actions/workflows/build.yml .. image:: https://img.shields.io/coveralls/pinax/django-mailer.svg :target: https://coveralls.io/r/pinax/django-mailer @@ -25,6 +25,17 @@ ``django-mailer`` is a reusable Django app for queuing the sending of email. It works by storing email in the database for later sending. +The main reason for doing this is that for many apps, the database will be +much more reliable and faster than other email sending backends which require +3rd party services e.g. SMTP or an HTTP API. By storing and sending later, we can +return succeed immediately, and then attempt actual email sending in the background, +with retries if needed. + +An additional use case is that if you are storing the mail in the same +database as your normal application, the database call can participate in +any ongoing transaction - that is, if the database transaction is rolled back, +the email sending will also be rolled back. (In some cases this behaviour +might not be desirable, so be careful). Keep in mind that file attachments are also temporarily stored in the database, which means if you are sending files larger than several hundred KB in size, you are likely to run into database limitations on how large your query can be. If this happens, you'll either need to fall back to using Django's default mail backend, or increase your database limits (a procedure that depends on which database you are using). @@ -77,6 +88,12 @@ Use the `-r failure` option to remove only failed log entries instead, or `-r all` to remove them all. +Note that the ``send_mail`` cronjob can only run at a maximum frequency of once each minute. If a maximum +delay of 60 seconds between creating an email and sending it is too much, an alternative is available. + +Using ``./manage.py runmailer`` a long running process is started that will check the database +for new emails each ``MAILER_EMPTY_QUEUE_SLEEP`` (default: 30 seconds). + Documentation and support ------------------------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-mailer-2.1/RELEASE.rst new/django-mailer-2.2/RELEASE.rst --- old/django-mailer-2.1/RELEASE.rst 2019-09-23 19:24:14.000000000 +0200 +++ new/django-mailer-2.2/RELEASE.rst 2021-09-24 09:45:26.000000000 +0200 @@ -1,7 +1,8 @@ Release process --------------- -* Check that the master branching is passing all tests - https://travis-ci.org/pinax/django-mailer +* Check that the master branching is passing all tests: + https://github.com/pinax/django-mailer/actions/workflows/build.yml * In CHANGES.rst, change the 'Unreleased' heading to the new version, and commit. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-mailer-2.1/docs/usage.rst new/django-mailer-2.2/docs/usage.rst --- old/django-mailer-2.1/docs/usage.rst 2020-12-05 11:39:47.000000000 +0100 +++ new/django-mailer-2.2/docs/usage.rst 2021-03-14 19:45:20.000000000 +0100 @@ -2,7 +2,7 @@ Usage ===== -First, add "mailer" to your ``INSTALLED_APPS`` in your settings.py. +First, add "mailer" to your ``INSTALLED_APPS`` in your ``settings.py``. Run ``./manage.py migrate`` to install models. Using EMAIL_BACKEND @@ -11,12 +11,12 @@ This is the preferred and easiest way to use django-mailer. To automatically switch all your mail to use django-mailer, first set -EMAIL_BACKEND:: +``EMAIL_BACKEND``:: EMAIL_BACKEND = "mailer.backend.DbBackend" -If you were previously using a non-default EMAIL_BACKEND, you need to configure -the MAILER_EMAIL_BACKEND setting, so that django-mailer knows how to actually send +If you were previously using a non-default ``EMAIL_BACKEND``, you need to configure +the ``MAILER_EMAIL_BACKEND`` setting, so that django-mailer knows how to actually send the mail:: MAILER_EMAIL_BACKEND = "your.actual.EmailBackend" @@ -29,48 +29,33 @@ Explicitly putting mail on the queue ==================================== -If you don't want to send all email through django-mailer, you can send mail -using ``mailer.send_mail``, which has the same signature as Django's -``send_mail`` function. - -You can also do the following:: - - # favour django-mailer but fall back to django.core.mail - from django.conf import settings - - if "mailer" in settings.INSTALLED_APPS: - from mailer import send_mail - else: - from django.core.mail import send_mail - -and then just call send_mail like you normally would in Django:: - - send_mail(subject, message_body, settings.DEFAULT_FROM_EMAIL, recipients) - -There is also a convenience function ``mailer.send_html_mail`` for creating HTML -(this function is **not** in Django):: - - send_html_mail(subject, message_plaintext, message_html, settings.DEFAULT_FROM_EMAIL, recipients) - -Additionally you can send all the admins as specified in the ``ADMIN`` -setting by calling:: - - mail_admins(subject, message_body) - -or all managers as defined in the ``MANAGERS`` setting by calling:: - - mail_managers(subject, message_body) +The best method to explicitly send some messages through the django-mailer queue (and perhaps +not others), is to use the ``connection`` parameter to the normal ``django.core.mail.send_mail`` +function or the ``django.core.mail.EmailMessage`` constructor - see the Django docs as above and +the `django.core.mail.get_connection <https://docs.djangoproject.com/en/stable/topics/email/#obtaining-an-instance-of-an-email-backend>`_ +function. + +Another method to use the django-mailer queue directly, which dates from before there was such +as thing as an "email backend" in Django, is to import the ``send_mail`` function (and similar) +from ``mailer`` instead of from ``django.core.mail``. There is also a ``send_html_mail`` convenience +function. However, we no longer guarantee that these functions will have a 100% compatible signature +with the Django version, so we recommend you don't use these functions. Clear queue with command extensions =================================== -With mailer in your INSTALLED_APPS, there will be three new manage.py commands -you can run: +With mailer in your ``INSTALLED_APPS``, there will be four new +``manage.py`` commands you can run: * ``send_mail`` will clear the current message queue. If there are any failures, they will be marked deferred and will not be attempted again by ``send_mail``. +* ``runmailer`` similar to ``send_mail``, but will keep running and checking the + database for new messages each ``MAILER_EMPTY_QUEUE_SLEEP`` (default: 30) seconds. + Can be used *instead* of ``send_mail`` to circumvent the maximum frequency + of once per minute inherent to cron. + * ``retry_deferred`` will move any deferred mail back into the normal queue (so it will be attempted again on the next ``send_mail``). @@ -87,9 +72,9 @@ For use in Pinax, for example, that might look like:: - * * * * * (cd $PINAX; /usr/local/bin/python2.5 manage.py send_mail >> $PINAX/cron_mail.log 2>&1) - 0,20,40 * * * * (cd $PINAX; /usr/local/bin/python2.5 manage.py retry_deferred >> $PINAX/cron_mail_deferred.log 2>&1) - 0 0 * * * (cd $PINAX; /usr/local/bin/python2.5 manage.py purge_mail_log 7 >> $PINAX/cron_mail_purge.log 2>&1) + * * * * * (cd $PINAX; /usr/local/bin/python manage.py send_mail >> $PINAX/cron_mail.log 2>&1) + 0,20,40 * * * * (cd $PINAX; /usr/local/bin/python manage.py retry_deferred >> $PINAX/cron_mail_deferred.log 2>&1) + 0 0 * * * (cd $PINAX; /usr/local/bin/python manage.py purge_mail_log 7 >> $PINAX/cron_mail_purge.log 2>&1) This attempts to send mail every minute with a retry on failure every 20 minutes, and purges the mail log for entries older than 7 days. @@ -102,7 +87,12 @@ executing it with cron. The `Pinax documentation`_ explains that in more details. +If you intend to use ``manage.py runmailer`` instead of ``send_mail`` it's +up to you to keep this command running in the background. This can be achieved +using `supervisord`_ or similar software. + .. _pinax documentation: http://pinaxproject.com/docs/dev/deployment.html#sending-mail-and-notices +.. _supervisord: http://supervisord.org/ Controlling the delivery process ================================ @@ -116,9 +106,9 @@ MAILER_EMAIL_THROTTLE = 0 # passed to time.sleep() These control how many emails are sent successfully before stopping the -current run `MAILER_EMAIL_MAX_BATCH`, after how many failed/deferred emails -should it stop `MAILER_EMAIL_MAX_DEFERRED` and how much time to wait between -each email `MAILER_EMAIL_THROTTLE`. +current run ``MAILER_EMAIL_MAX_BATCH``, after how many failed/deferred emails +should it stop ``MAILER_EMAIL_MAX_DEFERRED`` and how much time to wait between +each email ``MAILER_EMAIL_THROTTLE``. Unprocessed emails will be evaluated in the following delivery iterations. @@ -137,7 +127,7 @@ - ``socket.error`` Any other exceptions is re-raised. -That is done for backwords-compatiblity as well as for flexibility: +That is done for backwards-compatibility as well as for flexibility: we would otherwise have to maintain an extensive and changing list of exception types, which does not scale, and you get the chance to do error handling that fits your environment like a glove. @@ -191,9 +181,9 @@ If you need to change the batch size used by django-mailer to save messages in ``mailer.backend.DbBackend``, you can set ``MAILER_MESSAGES_BATCH_SIZE`` to a -value more suitable for you. This value, which defaults to `None`, will be passed to +value more suitable for you. This value, which defaults to ``None``, will be passed to `Django's bulk_create method <https://docs.djangoproject.com/en/stable/ref/models/querysets/#bulk-create>`_ -as the `batch_size` parameter. +as the ``batch_size`` parameter. Using the DontSendEntry table ============================= @@ -201,7 +191,7 @@ django-mailer creates a ``DontSendEntry`` model, which is used to filter out recipients from messages being created. -But beware, it's actually only used when directly sending messages through -mailer, not when mailer is used as an alternate ``EMAIL_BACKEND`` for Django. +However, note that it's actually only used when directly sending messages through +``mailer.send_mail``, not when mailer is used as an alternate ``EMAIL_BACKEND`` for Django. Also, even if recipients become empty due to this filtering, the email will be queued for sending anyway. (A patch to fix these issues would be accepted) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-mailer-2.1/requirements-dev.txt new/django-mailer-2.2/requirements-dev.txt --- old/django-mailer-2.1/requirements-dev.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/django-mailer-2.2/requirements-dev.txt 2021-06-15 08:27:13.000000000 +0200 @@ -0,0 +1,2 @@ +flake8==3.8.4 +check-manifest diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-mailer-2.1/requirements-test.txt new/django-mailer-2.2/requirements-test.txt --- old/django-mailer-2.1/requirements-test.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/django-mailer-2.2/requirements-test.txt 2021-06-15 08:25:29.000000000 +0200 @@ -0,0 +1,2 @@ +mock==3.0.5;python_version<'3.6' +mock==4.0.1;python_version>='3.6' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-mailer-2.1/setup.py new/django-mailer-2.2/setup.py --- old/django-mailer-2.1/setup.py 2020-12-05 11:54:27.000000000 +0100 +++ new/django-mailer-2.2/setup.py 2022-03-11 18:05:44.000000000 +0100 @@ -4,9 +4,15 @@ setup( name="django-mailer", - version="2.1", + version="2.2", description="A reusable Django app for queuing the sending of email", - long_description=open("docs/usage.rst").read() + open("CHANGES.rst").read(), + long_description="""``django-mailer`` is a reusable Django app for queuing the sending of email. +It works by storing email in the database for later sending. +The main reason for doing this is that for many apps, the database will be +much more reliable and faster than other email sending backends which require +3rd party services e.g. SMTP or an HTTP API. By storing and sending later, we can +return succeed immediately, and then attempt actual email sending in the background, +with retries if needed.""", author="Pinax Team", author_email="develop...@pinaxproject.com", url="http://github.com/pinax/django-mailer/", @@ -27,6 +33,7 @@ "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", "Framework :: Django", ], install_requires=[ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-mailer-2.1/src/django_mailer.egg-info/PKG-INFO new/django-mailer-2.2/src/django_mailer.egg-info/PKG-INFO --- old/django-mailer-2.1/src/django_mailer.egg-info/PKG-INFO 2020-12-05 11:56:51.000000000 +0100 +++ new/django-mailer-2.2/src/django_mailer.egg-info/PKG-INFO 2022-03-11 18:06:43.000000000 +0100 @@ -1,359 +1,11 @@ -Metadata-Version: 1.1 +Metadata-Version: 2.1 Name: django-mailer -Version: 2.1 +Version: 2.2 Summary: A reusable Django app for queuing the sending of email Home-page: http://github.com/pinax/django-mailer/ Author: Pinax Team Author-email: develop...@pinaxproject.com License: UNKNOWN -Description: ===== - Usage - ===== - - First, add "mailer" to your ``INSTALLED_APPS`` in your settings.py. - Run ``./manage.py migrate`` to install models. - - Using EMAIL_BACKEND - =================== - - This is the preferred and easiest way to use django-mailer. - - To automatically switch all your mail to use django-mailer, first set - EMAIL_BACKEND:: - - EMAIL_BACKEND = "mailer.backend.DbBackend" - - If you were previously using a non-default EMAIL_BACKEND, you need to configure - the MAILER_EMAIL_BACKEND setting, so that django-mailer knows how to actually send - the mail:: - - MAILER_EMAIL_BACKEND = "your.actual.EmailBackend" - - Now, just use the normal `Django mail functions - <https://docs.djangoproject.com/en/stable/topics/email/>`_ for sending email. These - functions will store mail on a queue in the database, which must be sent as - below. - - Explicitly putting mail on the queue - ==================================== - - If you don't want to send all email through django-mailer, you can send mail - using ``mailer.send_mail``, which has the same signature as Django's - ``send_mail`` function. - - You can also do the following:: - - # favour django-mailer but fall back to django.core.mail - from django.conf import settings - - if "mailer" in settings.INSTALLED_APPS: - from mailer import send_mail - else: - from django.core.mail import send_mail - - and then just call send_mail like you normally would in Django:: - - send_mail(subject, message_body, settings.DEFAULT_FROM_EMAIL, recipients) - - There is also a convenience function ``mailer.send_html_mail`` for creating HTML - (this function is **not** in Django):: - - send_html_mail(subject, message_plaintext, message_html, settings.DEFAULT_FROM_EMAIL, recipients) - - Additionally you can send all the admins as specified in the ``ADMIN`` - setting by calling:: - - mail_admins(subject, message_body) - - or all managers as defined in the ``MANAGERS`` setting by calling:: - - mail_managers(subject, message_body) - - Clear queue with command extensions - =================================== - - With mailer in your INSTALLED_APPS, there will be three new manage.py commands - you can run: - - * ``send_mail`` will clear the current message queue. If there are any - failures, they will be marked deferred and will not be attempted again by - ``send_mail``. - - * ``retry_deferred`` will move any deferred mail back into the normal queue - (so it will be attempted again on the next ``send_mail``). - - * ``purge_mail_log`` will remove old successful message logs from the database, to prevent it from filling up your database. - Use the ``-r failure`` option to remove only failed message logs instead, or ``-r all`` to remove them all. - - - You may want to set these up via cron to run regularly:: - - - * * * * * (/path/to/your/python /path/to/your/manage.py send_mail >> ~/cron_mail.log 2>&1) - 0,20,40 * * * * (/path/to/your/python /path/to/your/manage.py retry_deferred >> ~/cron_mail_deferred.log 2>&1) - 0 0 * * * (/path/to/your/python /path/to/your/manage.py purge_mail_log 7 >> ~/cron_mail_purge.log 2>&1) - - For use in Pinax, for example, that might look like:: - - * * * * * (cd $PINAX; /usr/local/bin/python2.5 manage.py send_mail >> $PINAX/cron_mail.log 2>&1) - 0,20,40 * * * * (cd $PINAX; /usr/local/bin/python2.5 manage.py retry_deferred >> $PINAX/cron_mail_deferred.log 2>&1) - 0 0 * * * (cd $PINAX; /usr/local/bin/python2.5 manage.py purge_mail_log 7 >> $PINAX/cron_mail_purge.log 2>&1) - - This attempts to send mail every minute with a retry on failure every 20 - minutes, and purges the mail log for entries older than 7 days. - - ``manage.py send_mail`` uses a lock file in case clearing the queue takes - longer than the interval between calling ``manage.py send_mail``. - - Note that if your project lives inside a virtualenv, you also have to execute - this command from the virtualenv. The same, naturally, applies also if you're - executing it with cron. The `Pinax documentation`_ explains that in more - details. - - .. _pinax documentation: http://pinaxproject.com/docs/dev/deployment.html#sending-mail-and-notices - - Controlling the delivery process - ================================ - - If you wish to have a finer control over the delivery process, which defaults - to deliver everything in the queue, you can use the following 3 variables - (default values shown):: - - MAILER_EMAIL_MAX_BATCH = None # integer or None - MAILER_EMAIL_MAX_DEFERRED = None # integer or None - MAILER_EMAIL_THROTTLE = 0 # passed to time.sleep() - - These control how many emails are sent successfully before stopping the - current run `MAILER_EMAIL_MAX_BATCH`, after how many failed/deferred emails - should it stop `MAILER_EMAIL_MAX_DEFERRED` and how much time to wait between - each email `MAILER_EMAIL_THROTTLE`. - - Unprocessed emails will be evaluated in the following delivery iterations. - - Error handling - ============== - - django-mailer comes with a default error handler - ``mailer.engine.handle_delivery_exception``. - - It marks the related message as deferred for any of these exceptions: - - - ``smtplib.SMTPAuthenticationError`` - - ``smtplib.SMTPDataError`` - - ``smtplib.SMTPRecipientsRefused`` - - ``smtplib.SMTPSenderRefused`` - - ``socket.error`` - - Any other exceptions is re-raised. - That is done for backwords-compatiblity as well as for flexibility: - we would otherwise have to maintain an extensive and changing - list of exception types, which does not scale, and you get - the chance to do error handling that fits your environment like a glove. - - When the default behavior does not fit your environment, you can specify your - own custom delivery error handler through setting ``MAILER_ERROR_HANDLER``. - The value should be a string for use with Django's ``import_string``, - the default is ``"mailer.engine.handle_delivery_exception"``. - - Your handler is passed three arguments, in order: - - - ``connection`` ??? the backend connection instance that failed delivery - - ``message`` ??? the ``Message`` instance that failed delivery - - ``exc`` ??? the exception instance raised by the mailer backend - - Your handler should return a 2-tuple of: - - 1. a connection instance (or ``None`` to cause a new connection to be created) - 2. a string denoting the action taken by the handler, - either ``"sent"`` or ``"deferred"`` precisely - - For an example of a custom error handler:: - - def my_handler(connection, message, exc): - if isinstance(exc, SomeDeliveryException): - # trying to re-send this very message desparately - # (if you have good reason to) - [..] - status = 'sent' - elif isinstance(exc, SomeOtherException): - message.defer() - connection = None # i.e. ask for a new connection - status = 'deferred' - else: - six.reraise(*sys.exc_info()) - - return connection, status - - Other settings - ============== - - If you need to be able to control where django-mailer puts its lock file (used - to ensure mail is not sent twice), you can set ``MAILER_LOCK_PATH`` to a full - absolute path to the file to be used as a lock. The extension ".lock" will be - added. The process running ``send_mail`` needs to have permissions to create and - delete this file, and others in the same directory. With the default value of - ``None`` django-mailer will use a path in current working directory. - - If you need to disable the file-based locking, you can set the - ``MAILER_USE_FILE_LOCK`` setting to ``False``. - - If you need to change the batch size used by django-mailer to save messages in - ``mailer.backend.DbBackend``, you can set ``MAILER_MESSAGES_BATCH_SIZE`` to a - value more suitable for you. This value, which defaults to `None`, will be passed to - `Django's bulk_create method <https://docs.djangoproject.com/en/stable/ref/models/querysets/#bulk-create>`_ - as the `batch_size` parameter. - - Using the DontSendEntry table - ============================= - - django-mailer creates a ``DontSendEntry`` model, which is used to filter out - recipients from messages being created. - - But beware, it's actually only used when directly sending messages through - mailer, not when mailer is used as an alternate ``EMAIL_BACKEND`` for Django. - Also, even if recipients become empty due to this filtering, the email will be - queued for sending anyway. (A patch to fix these issues would be accepted) - Change log - ========== - - 2.1 - 2020-12-05 - ---------------- - - * The ``retry_deferred`` and ``send_mail`` commands rely on the log level set - in your django project now. The ``-c/--cron`` option in those commands has - been deprecated and the logic to configure log levels and the message - format has been removed. - * Changed logging to use module specific loggers to avoid interfering - with other loggers. - * Added ``MAILER_USE_FILE_LOCK`` setting to allow disabling file based locking. - * Added ``-r`` option to ``purge_mail_log`` management command. Thanks julienc91 - * Fixed deprecation warnings on Django 3.1 - * Use cached DNS_NAME for performance - * Added ability to override the default error handler via the ``MAILER_ERROR_HANDLER`` - settings key - - 2.0.1 - 2020-03-01 - ------------------ - - * Fixed issue with migration that some people experienced (see `PR 118 - <https://github.com/pinax/django-mailer/pull/118>`_) - - 2.0 - 2019-09-23 - ---------------- - - * Django 3.0 support - * Dropped support for old Django versions (before 1.11) - * Changed DB ``priority`` field to an integer, instead of text field container an integer - * Multi-process safety for sending emails via database row-level locking. - - Previously, there was a file-system based lock to ensure that multiple - processes were not attempting to send the mail queue, to stop multiple sending - of the same email. However, this mechanism only works if all processes that - might be attempting to do this are on the same machine with access to the same - file-system. - - Now, in addition to this file lock, we use transactions and row-level locking - in the database when attempting to send a message, which guarantees that only - one process can send the message. In addition, for databases that support - ``NOWAIT`` with ``SELECT FOR UPDATE``, such as PostgreSQL, if multiple - processes attempt to send the mail queue at the same time, the work should be - distributed between them (rather than being done by only one process). - - A negative consequence is that **SQLite support is degraded**: due to the way - it implements locking and our use of transactions when sending the email - queue, you can get exceptions in other processes that are trying to add items - to the queue. Use of SQLite with django-mailer is **not recommended**. - - * ``retry_deferred`` command has also been updated to be simpler and work - correctly for multiple processes. - - * Dropped some backwards compat support for Django < 1.8. If you are upgrading - from a version of Django before 1.8, you should install a version of - django-mailer < 2.0, do ``send_all`` to flush the queue, then upgrade - django-mailer to 2.0 or later. - - 1.2.6 - 2019-04-03 - ------------------ - - * Official Django 2.1 and 2.2 support. - * Don't close DB connection in management commands. - This is unnecessary with modern Django. - - 1.2.5 - ----- - - * Fixed packaging file permission problems. - * Added Japanese locale (thanks msk7777) - - 1.2.4 - ----- - - * Django 2.0 support. - - 1.2.3 - ----- - - * Fixed crasher with models ``__str__`` - - 1.2.2 - ----- - - * Django 1.10 support. - * Fixed reprs for Message and MessageLog. - - 1.2.1 - ----- - - * More helpful admin for Message and MessageLog - * Handle exceptions from really old Django versions - - 1.2.0 - ----- - - * Save the ``Message-ID`` header on ``Message`` explicitly to enable finding - emails using this identifier. - - This includes a database schema migration. - - - 1.1.0 - ----- - - * Deprecated calling ``send_mail`` and ``send_html_mail`` using ``priority`` - kwargs ``"high"``, ``"medium"``, and ``"low"``. Instead you should use - ``PRIORITY_HIGH``, ``PRIORITY_MEDIUM`` and ``PRIORITY_LOW`` from - ``mailer.models``. - - * Fixed bug with migrations for Django 1.7, which wanted to create a migration - to 'fix' the EmailField length back down to 75 instead of 254. - - - 1.0.1 - ----- - - * Included migrations - for both South and Django 1.7 native migrations. - - Note: - - * If you use South, you will need at least South 1.0 - * You will need to use '--fake' or '--fake-initial' on existing installations. - - These migrations were supposed to be in 1.0.0 but were omitted due to a - packaging error. - - 1.0.0 - ----- - - * Throttling of email sending - * Django 1.8 support - * Admin tweaks and improvements - * Various other fixes, especially from Renato Alves <alves....@gmail.com> - thank you! - - 0.1.0 - ----- - - * First PyPI version - Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Web Environment @@ -368,4 +20,16 @@ Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 Classifier: Framework :: Django +License-File: LICENSE +License-File: AUTHORS + +``django-mailer`` is a reusable Django app for queuing the sending of email. +It works by storing email in the database for later sending. +The main reason for doing this is that for many apps, the database will be +much more reliable and faster than other email sending backends which require +3rd party services e.g. SMTP or an HTTP API. By storing and sending later, we can +return succeed immediately, and then attempt actual email sending in the background, +with retries if needed. + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-mailer-2.1/src/django_mailer.egg-info/SOURCES.txt new/django-mailer-2.2/src/django_mailer.egg-info/SOURCES.txt --- old/django-mailer-2.1/src/django_mailer.egg-info/SOURCES.txt 2020-12-05 11:56:51.000000000 +0100 +++ new/django-mailer-2.2/src/django_mailer.egg-info/SOURCES.txt 2022-03-11 18:06:43.000000000 +0100 @@ -1,5 +1,4 @@ .coveragerc -.travis.yml AUTHORS CHANGES.rst CONTRIBUTING.rst @@ -9,6 +8,8 @@ RELEASE.rst manage.py release.sh +requirements-dev.txt +requirements-test.txt runtests.py setup.cfg setup.py @@ -22,6 +23,7 @@ src/django_mailer.egg-info/top_level.txt src/mailer/__init__.py src/mailer/admin.py +src/mailer/apps.py src/mailer/backend.py src/mailer/engine.py src/mailer/models.py @@ -32,11 +34,13 @@ src/mailer/management/commands/__init__.py src/mailer/management/commands/purge_mail_log.py src/mailer/management/commands/retry_deferred.py +src/mailer/management/commands/runmailer.py src/mailer/management/commands/send_mail.py src/mailer/migrations/0001_initial.py src/mailer/migrations/0002_auto_20150720_1433.py src/mailer/migrations/0003_messagelog_message_id.py src/mailer/migrations/0004_auto_20190920_1512.py +src/mailer/migrations/0005_id_bigautofield.py src/mailer/migrations/__init__.py tests/__init__.py tests/test_mailer.py \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-mailer-2.1/src/mailer/__init__.py new/django-mailer-2.2/src/mailer/__init__.py --- old/django-mailer-2.1/src/mailer/__init__.py 2020-12-05 11:54:27.000000000 +0100 +++ new/django-mailer-2.2/src/mailer/__init__.py 2022-03-11 18:05:44.000000000 +0100 @@ -4,7 +4,7 @@ import six -__version__ = '2.1' +__version__ = '2.2' def get_priority(priority): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-mailer-2.1/src/mailer/apps.py new/django-mailer-2.2/src/mailer/apps.py --- old/django-mailer-2.1/src/mailer/apps.py 1970-01-01 01:00:00.000000000 +0100 +++ new/django-mailer-2.2/src/mailer/apps.py 2022-03-11 18:03:48.000000000 +0100 @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class MailerConfig(AppConfig): + name = 'mailer' + default_auto_field = 'django.db.models.BigAutoField' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-mailer-2.1/src/mailer/engine.py new/django-mailer-2.2/src/mailer/engine.py --- old/django-mailer-2.1/src/mailer/engine.py 2020-12-05 11:39:47.000000000 +0100 +++ new/django-mailer-2.2/src/mailer/engine.py 2022-03-11 18:03:48.000000000 +0100 @@ -255,9 +255,11 @@ if use_file_lock: release_lock(lock) - logger.info("") - logger.info("%s sent; %s deferred;" % (counts['sent'], counts['deferred'])) - logger.info("done in %.2f seconds" % (time.time() - start_time)) + logger.info("Sent", extra={ + 'sent': counts['sent'], + 'deferred': counts['deferred'], + 'duration': time.time() - start_time, + }) def send_loop(): @@ -267,7 +269,7 @@ """ while True: - while not Message.objects.all(): + while not Message.objects.non_deferred().exists(): logger.debug("sleeping for %s seconds before checking queue again" % EMPTY_QUEUE_SLEEP) time.sleep(EMPTY_QUEUE_SLEEP) send_all() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-mailer-2.1/src/mailer/management/commands/runmailer.py new/django-mailer-2.2/src/mailer/management/commands/runmailer.py --- old/django-mailer-2.1/src/mailer/management/commands/runmailer.py 1970-01-01 01:00:00.000000000 +0100 +++ new/django-mailer-2.2/src/mailer/management/commands/runmailer.py 2021-02-24 08:13:08.000000000 +0100 @@ -0,0 +1,17 @@ +import sys +from datetime import datetime + +from django.core.management import BaseCommand + +from mailer.engine import send_loop + + +class Command(BaseCommand): + """Start the django-mailer send loop""" + + def handle(self, *args, **options): + self.stdout.write(datetime.now().strftime('%B %d, %Y - %X')) + self.stdout.write('Starting django-mailer send loop.') + quit_command = 'CTRL-BREAK' if sys.platform == 'win32' else 'CONTROL-C' + self.stdout.write('Quit the loop with %s.' % quit_command) + send_loop() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-mailer-2.1/src/mailer/migrations/0005_id_bigautofield.py new/django-mailer-2.2/src/mailer/migrations/0005_id_bigautofield.py --- old/django-mailer-2.1/src/mailer/migrations/0005_id_bigautofield.py 1970-01-01 01:00:00.000000000 +0100 +++ new/django-mailer-2.2/src/mailer/migrations/0005_id_bigautofield.py 2022-03-11 18:03:48.000000000 +0100 @@ -0,0 +1,28 @@ +# Generated by Django 3.2.9 on 2021-11-04 13:31 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('mailer', '0004_auto_20190920_1512'), + ] + + operations = [ + migrations.AlterField( + model_name='dontsendentry', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + migrations.AlterField( + model_name='message', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + migrations.AlterField( + model_name='messagelog', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + ] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-mailer-2.1/src/mailer/models.py new/django-mailer-2.2/src/mailer/models.py --- old/django-mailer-2.1/src/mailer/models.py 2020-12-05 11:39:47.000000000 +0100 +++ new/django-mailer-2.2/src/mailer/models.py 2022-03-11 18:03:48.000000000 +0100 @@ -38,6 +38,16 @@ logger = logging.getLogger(__name__) +class BigAutoModel(models.Model): + # default_auto_field = 'django.db.models.BigAutoField' isn't supported + # by Django < 3.2. Use an explicit field definition instead. + # This workaround can be removed once support for Django < 3.2 is dropped. + id = models.BigAutoField(auto_created=True, primary_key=True, verbose_name='ID') + + class Meta: + abstract = True + + def get_message_id(msg): # From django.core.mail.message: Email header names are case-insensitive # (RFC 2045), so we have to accommodate that when doing comparisons. @@ -114,7 +124,7 @@ @python_2_unicode_compatible -class Message(models.Model): +class Message(BigAutoModel): """ The email stored for later sending. """ @@ -221,7 +231,7 @@ return queryset.exists() -class DontSendEntry(models.Model): +class DontSendEntry(BigAutoModel): to_address = models.EmailField(max_length=254) when_added = models.DateTimeField() @@ -273,7 +283,7 @@ @python_2_unicode_compatible -class MessageLog(models.Model): +class MessageLog(BigAutoModel): """ A log entry which stores the result (and optionally a log message) for an attempt to send a Message. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-mailer-2.1/tests/test_mailer.py new/django-mailer-2.2/tests/test_mailer.py --- old/django-mailer-2.1/tests/test_mailer.py 2020-12-05 11:39:47.000000000 +0100 +++ new/django-mailer-2.2/tests/test_mailer.py 2022-03-11 18:03:48.000000000 +0100 @@ -134,6 +134,9 @@ def test_send_loop(self): with self.settings(MAILER_EMAIL_BACKEND="django.core.mail.backends.locmem.EmailBackend"): with patch("mailer.engine.send_all", side_effect=StopIteration) as send: + mailer.send_mail("Subject", "Body", "defer...@example.com", + ["r...@example.com"], priority=PRIORITY_DEFERRED) + with patch("time.sleep", side_effect=StopIteration) as sleep: self.assertRaises(StopIteration, engine.send_loop) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-mailer-2.1/tox.ini new/django-mailer-2.2/tox.ini --- old/django-mailer-2.1/tox.ini 2020-12-05 11:54:27.000000000 +0100 +++ new/django-mailer-2.2/tox.ini 2022-03-11 18:03:48.000000000 +0100 @@ -1,50 +1,41 @@ [tox] -# Remember to add to .travis.yml if this is added to. +# Remember to add to .github/workflows/build.yml if this is added to. envlist = + # Not every combination, just a representative sample: py27-django111-test, - py34-django{111,20}-test, - {py35,py36}-django{111,20}-test, - py38-django{21,22,30,31}-test, - py39-django31-test, - {py27,py38}-flake, - checkmanifest, + {py35,py36}-django20-test, + py37-django21-test, + py38-django22-test, + py39-django{30,31,32,40}-test, + py310-django40-test, + flake-py39-django32, + checkmanifest-py39, [testenv] basepython = py27: python2.7 - py34: python3.4 py35: python3.5 py36: python3.6 py37: python3.7 py38: python3.8 py39: python3.9 + py310: python3.10 commands = test: coverage run ./runtests.py flake: flake8 --statistics --benchmark + checkmanifest: check-manifest deps = - six - lockfile==0.10.2 coverage - py27: mock==3.0.5 - py34: mock==3.0.5 - py35: mock==3.0.5 - py36: mock==4.0.1 - py37: mock==4.0.1 - py38: mock==4.0.1 - py39: mock==4.0.1 + -r requirements-test.txt + -e . + flake8: -r requirements-dev.txt + checkmanifest: -r requirements-dev.txt django111: Django==1.11.29 django20: Django==2.0.13 django21: Django==2.1.15 - django22: Django==2.2.16 - django30: Django==3.0.10 - django31: Django==3.1.2 - flake: flake8==3.8.4 - py27-flake: Django<2.0 - -[testenv:checkmanifest] -basepython = python2.7 -deps = - check-manifest - Django<3.0 -commands = check-manifest + django22: Django==2.2.19 + django30: Django==3.0.14 + django31: Django==3.1.12 + django32: Django==3.2.4 + django40: Django==4.0.3 ++++++ python-django-mailer-no-mock.patch ++++++ diff -upr django-mailer-2.2.orig/tests/test_mailer.py django-mailer-2.2/tests/test_mailer.py --- django-mailer-2.2.orig/tests/test_mailer.py 2022-05-09 17:23:15.968311514 +0200 +++ django-mailer-2.2/tests/test_mailer.py 2022-05-09 17:23:15.976311564 +0200 @@ -12,7 +12,7 @@ from django.core.exceptions import Impro from django.core.management import call_command from django.test import TestCase from django.utils.timezone import now as datetime_now -from mock import Mock, patch +from unittest.mock import Mock, patch import six import mailer