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 2021-12-26 13:30:38
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-django-mailer (Old)
and /work/SRC/openSUSE:Factory/.python-django-mailer.new.2520 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-django-mailer"
Sun Dec 26 13:30:38 2021 rev:2 rq:942593 version:2.1
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-django-mailer/python-django-mailer.changes
2020-07-08 19:14:19.095387900 +0200
+++
/work/SRC/openSUSE:Factory/.python-django-mailer.new.2520/python-django-mailer.changes
2021-12-26 13:30:58.430978921 +0100
@@ -1,0 +2,18 @@
+Sun Dec 26 11:31:52 UTC 2021 - John Vandenberg <[email protected]>
+
+- Update to v2.1
+ * 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.
+ * 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
+
+-------------------------------------------------------------------
Old:
----
django-mailer-2.0.1.tar.gz
New:
----
django-mailer-2.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-django-mailer.spec ++++++
--- /var/tmp/diff_new_pack.1dciVg/_old 2021-12-26 13:30:58.838979205 +0100
+++ /var/tmp/diff_new_pack.1dciVg/_new 2021-12-26 13:30:58.842979208 +0100
@@ -1,7 +1,7 @@
#
# spec file for package python-django-mailer
#
-# Copyright (c) 2020 SUSE LLC
+# Copyright (c) 2021 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -18,7 +18,7 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
Name: python-django-mailer
-Version: 2.0.1
+Version: 2.1
Release: 0
Summary: A reusable Django app for queuing the sending of email
License: MIT
@@ -60,6 +60,6 @@
%files %{python_files}
%doc AUTHORS CHANGES.rst README.rst
%license LICENSE
-%{python_sitelib}/*
+%{python_sitelib}/*mailer*/
%changelog
++++++ django-mailer-2.0.1.tar.gz -> django-mailer-2.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-mailer-2.0.1/.travis.yml
new/django-mailer-2.1/.travis.yml
--- old/django-mailer-2.0.1/.travis.yml 2019-09-23 19:24:14.000000000 +0200
+++ new/django-mailer-2.1/.travis.yml 2020-10-11 19:47:09.000000000 +0200
@@ -31,8 +31,10 @@
env: TOXENV=py36-django22-test
- python: 3.6
env: TOXENV=py36-django30-test
- - python: 3.6
- env: TOXENV=py36-flake
+ - python: 3.8
+ env: TOXENV=py38-django31-test
+ - python: 3.8
+ env: TOXENV=py38-flake
install:
- pip install coveralls tox>=2.1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-mailer-2.0.1/AUTHORS
new/django-mailer-2.1/AUTHORS
--- old/django-mailer-2.0.1/AUTHORS 2015-07-03 13:16:58.000000000 +0200
+++ new/django-mailer-2.1/AUTHORS 2020-12-05 11:39:47.000000000 +0100
@@ -11,3 +11,5 @@
* Jannis Leidel
* Luke Plant
* Renato Alves
+ * Paul Brown
+ * Sebastian Pipping
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-mailer-2.0.1/CHANGES.rst
new/django-mailer-2.1/CHANGES.rst
--- old/django-mailer-2.0.1/CHANGES.rst 2020-03-01 19:48:34.000000000 +0100
+++ new/django-mailer-2.1/CHANGES.rst 2020-12-05 11:54:27.000000000 +0100
@@ -1,6 +1,22 @@
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
------------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-mailer-2.0.1/PKG-INFO
new/django-mailer-2.1/PKG-INFO
--- old/django-mailer-2.0.1/PKG-INFO 2020-03-01 20:25:48.000000000 +0100
+++ new/django-mailer-2.1/PKG-INFO 2020-12-05 11:56:51.692757600 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: django-mailer
-Version: 2.0.1
+Version: 2.1
Summary: A reusable Django app for queuing the sending of email
Home-page: http://github.com/pinax/django-mailer/
Author: Pinax Team
@@ -82,7 +82,8 @@
* ``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
+ * ``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::
@@ -129,6 +130,60 @@
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
==============
@@ -139,6 +194,9 @@
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
@@ -158,6 +216,22 @@
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
------------------
@@ -291,4 +365,7 @@
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
+Classifier: Programming Language :: Python :: 3.7
+Classifier: Programming Language :: Python :: 3.8
+Classifier: Programming Language :: Python :: 3.9
Classifier: Framework :: Django
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-mailer-2.0.1/README.rst
new/django-mailer-2.1/README.rst
--- old/django-mailer-2.0.1/README.rst 2019-09-23 19:24:14.000000000 +0200
+++ new/django-mailer-2.1/README.rst 2020-10-11 18:34:19.000000000 +0200
@@ -20,19 +20,16 @@
:target: https://pypi.python.org/pypi/django-mailer/
-Pinax
------
-
-Pinax is an open-source platform built on the Django Web Framework. It is an
ecosystem of reusable Django apps, themes, and starter project templates.
-This collection can be found at http://pinaxproject.com.
-
-This app was developed as part of the Pinax ecosystem but is just a Django app
and can be used independently of other Pinax apps.
-
-
django-mailer
-------------
``django-mailer`` is a reusable Django app for queuing the sending of email.
+It works by storing email in the database for later sending.
+
+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).
+
+django-mailer was developed as part of the `Pinax ecosystem
<http://pinaxproject.com>`_ but is just a Django app and can be used
independently of other Pinax apps.
+
Requirements
------------
@@ -78,29 +75,37 @@
0 0 * * * (/path/to/your/python /path/to/your/manage.py purge_mail_log 7
>> ~/cron_mail_purge.log 2>&1)
-Documentation
--------------
+Use the `-r failure` option to remove only failed log entries instead, or `-r
all` to remove them all.
-See ``usage.rst`` in the docs for more advanced use cases -
https://github.com/pinax/django-mailer/blob/master/docs/usage.rst#usage.
+Documentation and support
+-------------------------
+
+See `usage.rst
<https://github.com/pinax/django-mailer/blob/master/docs/usage.rst#usage>`_
+in the docs for more advanced use cases.
The Pinax documentation is available at http://pinaxproject.com/pinax/.
+This is an Open Source project maintained by volunteers, and outside this
documentation the maintainers
+do not offer other support. For cases where you have found a bug you can file
a GitHub issue.
+In case of any questions we recommend you join the `Pinax Slack team
<http://slack.pinaxproject.com>`_
+and ping the Pinax team there instead of creating an issue on GitHub. You may
also be able to get help on
+other programming sites like `Stack Overflow <https://stackoverflow.com/>`_.
+
Contribute
----------
-See ``CONTRIBUTING.rst`` for information about contributing patches to
``django-mailer``.
+See `CONTRIBUTING.rst
<https://github.com/pinax/django-mailer/blob/master/CONTRIBUTING.rst>`_ for
information about contributing patches to ``django-mailer``.
-See this blog post
http://blog.pinaxproject.com/2016/02/26/recap-february-pinax-hangout/ including
a video, or our How to Contribute
(http://pinaxproject.com/pinax/how_to_contribute/) section for an overview on
how contributing to Pinax works. For concrete contribution ideas, please see
our Ways to Contribute/What We Need Help With
(http://pinaxproject.com/pinax/ways_to_contribute/) section.
+See this `blog post including a video
<http://blog.pinaxproject.com/2016/02/26/recap-february-pinax-hangout/>`_, or
our `How to Contribute <http://pinaxproject.com/pinax/how_to_contribute/>`_
section for an overview on how contributing to Pinax works. For concrete
contribution ideas, please see our `Ways to Contribute/What We Need Help With
<http://pinaxproject.com/pinax/ways_to_contribute/>`_ section.
-In case of any questions we recommend you join our Pinax Slack team
(http://slack.pinaxproject.com) and ping us there instead of creating an issue
on GitHub. Creating issues on GitHub is of course also valid but we are usually
able to help you faster if you ping us in Slack.
-We also highly recommend reading our Open Source and Self-Care blog post
(http://blog.pinaxproject.com/2016/01/19/open-source-and-self-care/).
+We also highly recommend reading our `Open Source and Self-Care blog post
<http://blog.pinaxproject.com/2016/01/19/open-source-and-self-care/>`_.
Code of Conduct
---------------
-In order to foster a kind, inclusive, and harassment-free community, the Pinax
Project has a code of conduct, which can be found here
http://pinaxproject.com/pinax/code_of_conduct/.
+In order to foster a kind, inclusive, and harassment-free community, the Pinax
Project has a `code of conduct
<http://pinaxproject.com/pinax/code_of_conduct/>`_.
We ask you to treat everyone as a smart human programmer that shares an
interest in Python, Django, and Pinax with you.
@@ -108,4 +113,4 @@
Pinax Project Blog and Twitter
------------------------------
-For updates and news regarding the Pinax Project, please follow us on Twitter
at @pinaxproject and check out our blog http://blog.pinaxproject.com.
+For updates and news regarding the Pinax Project, please follow us on Twitter
at @pinaxproject and check out `our blog <http://blog.pinaxproject.com>`_.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-mailer-2.0.1/docs/usage.rst
new/django-mailer-2.1/docs/usage.rst
--- old/django-mailer-2.0.1/docs/usage.rst 2019-09-23 19:24:14.000000000
+0200
+++ new/django-mailer-2.1/docs/usage.rst 2020-12-05 11:39:47.000000000
+0100
@@ -74,7 +74,8 @@
* ``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
+* ``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::
@@ -121,6 +122,60 @@
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
==============
@@ -131,6 +186,9 @@
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
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-mailer-2.0.1/runtests.py
new/django-mailer-2.1/runtests.py
--- old/django-mailer-2.0.1/runtests.py 2019-09-23 19:24:14.000000000 +0200
+++ new/django-mailer-2.1/runtests.py 2020-10-11 19:21:59.000000000 +0200
@@ -8,6 +8,7 @@
from django.test.utils import get_runner
warnings.simplefilter("always", DeprecationWarning)
+warnings.simplefilter("always", PendingDeprecationWarning)
DEFAULT_SETTINGS = dict(
INSTALLED_APPS=[
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-mailer-2.0.1/setup.cfg
new/django-mailer-2.1/setup.cfg
--- old/django-mailer-2.0.1/setup.cfg 2020-03-01 20:25:48.000000000 +0100
+++ new/django-mailer-2.1/setup.cfg 2020-12-05 11:56:51.692757600 +0100
@@ -3,7 +3,6 @@
[flake8]
max-line-length = 100
-max-complexity = 10
exclude = src/mailer/migrations,build,.tox
[egg_info]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-mailer-2.0.1/setup.py
new/django-mailer-2.1/setup.py
--- old/django-mailer-2.0.1/setup.py 2020-03-01 19:49:12.000000000 +0100
+++ new/django-mailer-2.1/setup.py 2020-12-05 11:54:27.000000000 +0100
@@ -4,7 +4,7 @@
setup(
name="django-mailer",
- version="2.0.1",
+ version="2.1",
description="A reusable Django app for queuing the sending of email",
long_description=open("docs/usage.rst").read() +
open("CHANGES.rst").read(),
author="Pinax Team",
@@ -24,6 +24,9 @@
"Programming Language :: Python :: 3.4",
"Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
+ "Programming Language :: Python :: 3.7",
+ "Programming Language :: Python :: 3.8",
+ "Programming Language :: Python :: 3.9",
"Framework :: Django",
],
install_requires=[
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/django-mailer-2.0.1/src/django_mailer.egg-info/PKG-INFO
new/django-mailer-2.1/src/django_mailer.egg-info/PKG-INFO
--- old/django-mailer-2.0.1/src/django_mailer.egg-info/PKG-INFO 2020-03-01
20:25:48.000000000 +0100
+++ new/django-mailer-2.1/src/django_mailer.egg-info/PKG-INFO 2020-12-05
11:56:51.000000000 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: django-mailer
-Version: 2.0.1
+Version: 2.1
Summary: A reusable Django app for queuing the sending of email
Home-page: http://github.com/pinax/django-mailer/
Author: Pinax Team
@@ -82,7 +82,8 @@
* ``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
+ * ``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::
@@ -129,6 +130,60 @@
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
==============
@@ -139,6 +194,9 @@
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
@@ -158,6 +216,22 @@
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
------------------
@@ -291,4 +365,7 @@
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
+Classifier: Programming Language :: Python :: 3.7
+Classifier: Programming Language :: Python :: 3.8
+Classifier: Programming Language :: Python :: 3.9
Classifier: Framework :: Django
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-mailer-2.0.1/src/mailer/__init__.py
new/django-mailer-2.1/src/mailer/__init__.py
--- old/django-mailer-2.0.1/src/mailer/__init__.py 2020-03-01
19:48:59.000000000 +0100
+++ new/django-mailer-2.1/src/mailer/__init__.py 2020-12-05
11:54:27.000000000 +0100
@@ -2,8 +2,9 @@
import warnings
+import six
-__version__ = '2.0.1'
+__version__ = '2.1'
def get_priority(priority):
@@ -25,13 +26,17 @@
def send_mail(subject, message, from_email, recipient_list, priority=None,
fail_silently=False, auth_user=None, auth_password=None):
- from django.utils.encoding import force_text
+ if six.PY2:
+ # Only runs Django 1.11
+ from django.utils.encoding import force_unicode as force_str
+ else:
+ from django.utils.encoding import force_str
from mailer.models import make_message
priority = get_priority(priority)
# need to do this in case subject used lazy version of ugettext
- subject = force_text(subject)
- message = force_text(message)
+ subject = force_str(subject)
+ message = force_str(message)
make_message(subject=subject,
body=message,
@@ -47,15 +52,19 @@
"""
Function to queue HTML e-mails
"""
- from django.utils.encoding import force_text
+ if six.PY2:
+ # Only runs Django 1.11
+ from django.utils.encoding import force_unicode as force_str
+ else:
+ from django.utils.encoding import force_str
from django.core.mail import EmailMultiAlternatives
from mailer.models import make_message
priority = get_priority(priority)
# need to do this in case subject used lazy version of ugettext
- subject = force_text(subject)
- message = force_text(message)
+ subject = force_str(subject)
+ message = force_str(message)
msg = make_message(subject=subject,
body=message,
@@ -86,9 +95,13 @@
def mail_admins(subject, message, fail_silently=False, connection=None,
priority=None):
from django.conf import settings
- from django.utils.encoding import force_text
+ if six.PY2:
+ # Only runs Django 1.11
+ from django.utils.encoding import force_unicode as force_str
+ else:
+ from django.utils.encoding import force_str
- return send_mail(settings.EMAIL_SUBJECT_PREFIX + force_text(subject),
+ return send_mail(settings.EMAIL_SUBJECT_PREFIX + force_str(subject),
message,
settings.SERVER_EMAIL,
[a[1] for a in settings.ADMINS])
@@ -96,9 +109,13 @@
def mail_managers(subject, message, fail_silently=False, connection=None,
priority=None):
from django.conf import settings
- from django.utils.encoding import force_text
+ if six.PY2:
+ # Only runs Django 1.11
+ from django.utils.encoding import force_unicode as force_str
+ else:
+ from django.utils.encoding import force_str
- return send_mail(settings.EMAIL_SUBJECT_PREFIX + force_text(subject),
+ return send_mail(settings.EMAIL_SUBJECT_PREFIX + force_str(subject),
message,
settings.SERVER_EMAIL,
[a[1] for a in settings.MANAGERS])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-mailer-2.0.1/src/mailer/engine.py
new/django-mailer-2.1/src/mailer/engine.py
--- old/django-mailer-2.0.1/src/mailer/engine.py 2020-03-01
19:43:27.000000000 +0100
+++ new/django-mailer-2.1/src/mailer/engine.py 2020-12-05 11:39:47.000000000
+0100
@@ -3,16 +3,21 @@
import contextlib
import logging
import smtplib
+import sys
import time
from socket import error as socket_error
import lockfile
+import six
from django import VERSION as DJANGO_VERSION
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.core.mail import get_connection
from django.core.mail.message import make_msgid
+from django.core.mail.utils import DNS_NAME
from django.db import DatabaseError, NotSupportedError, OperationalError,
transaction
+from django.utils.module_loading import import_string
+
from mailer.models import (RESULT_FAILURE, RESULT_SUCCESS, Message,
MessageLog, get_message_id)
if DJANGO_VERSION[0] >= 2:
@@ -32,6 +37,8 @@
# in the current working directory.
LOCK_PATH = getattr(settings, "MAILER_LOCK_PATH", None)
+logger = logging.getLogger(__name__)
+
def prioritize():
"""
@@ -84,7 +91,8 @@
def ensure_message_id(msg):
if get_message_id(msg) is None:
- msg.extra_headers['Message-ID'] = make_msgid()
+ # Use cached DNS_NAME for performance
+ msg.extra_headers['Message-ID'] = make_msgid(domain=DNS_NAME)
def _limits_reached(sent, deferred):
@@ -93,8 +101,8 @@
EMAIL_MAX_BATCH = getattr(settings, "MAILER_EMAIL_MAX_BATCH", None)
if EMAIL_MAX_BATCH is not None and sent >= EMAIL_MAX_BATCH:
- logging.info("EMAIL_MAX_BATCH (%s) reached, "
- "stopping for this round", EMAIL_MAX_BATCH)
+ logger.info("EMAIL_MAX_BATCH (%s) reached, "
+ "stopping for this round", EMAIL_MAX_BATCH)
return True
# Stop sending emails in the current round if more than X emails get
@@ -102,8 +110,8 @@
EMAIL_MAX_DEFERRED = getattr(settings, "MAILER_EMAIL_MAX_DEFERRED", None)
if EMAIL_MAX_DEFERRED is not None and deferred >= EMAIL_MAX_DEFERRED:
- logging.warning("EMAIL_MAX_DEFERRED (%s) reached, "
- "stopping for this round", EMAIL_MAX_DEFERRED)
+ logger.warning("EMAIL_MAX_DEFERRED (%s) reached, "
+ "stopping for this round", EMAIL_MAX_DEFERRED)
return True
@@ -113,13 +121,33 @@
EMAIL_THROTTLE = getattr(settings, "MAILER_EMAIL_THROTTLE", 0)
if EMAIL_THROTTLE:
- logging.debug("Throttling email delivery. "
- "Sleeping %s seconds", EMAIL_THROTTLE)
+ logger.debug("Throttling email delivery. "
+ "Sleeping %s seconds", EMAIL_THROTTLE)
time.sleep(EMAIL_THROTTLE)
+def handle_delivery_exception(connection, message, exc):
+ if isinstance(exc, (smtplib.SMTPAuthenticationError,
+ smtplib.SMTPDataError,
+ smtplib.SMTPRecipientsRefused,
+ smtplib.SMTPSenderRefused,
+ socket_error)):
+ message.defer()
+ logger.info("message deferred due to failure: %s" % exc)
+ MessageLog.objects.log(message, RESULT_FAILURE, log_message=str(exc))
+
+ connection = None # i.e. enforce creation of a new connection
+ status = 'deferred'
+
+ return connection, status
+
+ # The idea is (1) to be backwards compatible with existing behavior
+ # and (2) not have delivery errors go unnoticed
+ six.reraise(*sys.exc_info())
+
+
def acquire_lock():
- logging.debug("acquiring lock...")
+ logger.debug("acquiring lock...")
if LOCK_PATH is not None:
lock_file_path = LOCK_PATH
else:
@@ -130,19 +158,19 @@
try:
lock.acquire(LOCK_WAIT_TIMEOUT)
except lockfile.AlreadyLocked:
- logging.debug("lock already in place. quitting.")
+ logger.error("lock already in place. quitting.")
return False, lock
except lockfile.LockTimeout:
- logging.debug("waiting for the lock timed out. quitting.")
+ logger.error("waiting for the lock timed out. quitting.")
return False, lock
- logging.debug("acquired.")
+ logger.debug("acquired.")
return True, lock
def release_lock(lock):
- logging.debug("releasing lock...")
+ logger.debug("releasing lock...")
lock.release()
- logging.debug("released.")
+ logger.debug("released.")
def _require_no_backend_loop(mailer_email_backend):
@@ -165,16 +193,24 @@
"django.core.mail.backends.smtp.EmailBackend"
)
+ # allows disabling file locking. The default is True
+ use_file_lock = getattr(settings, "MAILER_USE_FILE_LOCK", True)
+
+ error_handler = import_string(
+ getattr(settings, 'MAILER_ERROR_HANDLER',
+ 'mailer.engine.handle_delivery_exception')
+ )
+
_require_no_backend_loop(mailer_email_backend)
- acquired, lock = acquire_lock()
- if not acquired:
- return
+ if use_file_lock:
+ acquired, lock = acquire_lock()
+ if not acquired:
+ return
start_time = time.time()
- deferred = 0
- sent = 0
+ counts = {'deferred': 0, 'sent': 0}
try:
connection = None
@@ -186,7 +222,7 @@
try:
if connection is None:
connection =
get_connection(backend=mailer_email_backend)
- logging.info("sending message '{0}' to {1}".format(
+ logger.info("sending message '{0}' to {1}".format(
message.subject,
", ".join(message.to_addresses))
)
@@ -200,34 +236,28 @@
email.connection = None
message.email = email # For the sake of MessageLog
MessageLog.objects.log(message, RESULT_SUCCESS)
- sent += 1
+ counts['sent'] += 1
else:
- logging.warning("message discarded due to failure in
converting from DB. Added on '%s' with priority '%s'" % (message.when_added,
message.priority)) # noqa
+ logger.warning("message discarded due to failure in
converting from DB. Added on '%s' with priority '%s'" % (message.when_added,
message.priority)) # noqa
message.delete()
- except (socket_error, smtplib.SMTPSenderRefused,
- smtplib.SMTPRecipientsRefused,
- smtplib.SMTPDataError,
- smtplib.SMTPAuthenticationError) as err:
- message.defer()
- logging.info("message deferred due to failure: %s" % err)
- MessageLog.objects.log(message, RESULT_FAILURE,
log_message=str(err))
- deferred += 1
- # Get new connection, it case the connection itself has an
error.
- connection = None
+ except Exception as err:
+ connection, action_taken = error_handler(connection,
message, err)
+ counts[action_taken] += 1
# Check if we reached the limits for the current run
- if _limits_reached(sent, deferred):
+ if _limits_reached(counts['sent'], counts['deferred']):
break
_throttle_emails()
finally:
- release_lock(lock)
+ if use_file_lock:
+ release_lock(lock)
- logging.info("")
- logging.info("%s sent; %s deferred;" % (sent, deferred))
- logging.info("done in %.2f seconds" % (time.time() - start_time))
+ logger.info("")
+ logger.info("%s sent; %s deferred;" % (counts['sent'], counts['deferred']))
+ logger.info("done in %.2f seconds" % (time.time() - start_time))
def send_loop():
@@ -238,6 +268,6 @@
while True:
while not Message.objects.all():
- logging.debug("sleeping for %s seconds before checking queue
again" % EMPTY_QUEUE_SLEEP)
+ 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.0.1/src/mailer/management/commands/purge_mail_log.py
new/django-mailer-2.1/src/mailer/management/commands/purge_mail_log.py
--- old/django-mailer-2.0.1/src/mailer/management/commands/purge_mail_log.py
2019-09-23 19:24:14.000000000 +0200
+++ new/django-mailer-2.1/src/mailer/management/commands/purge_mail_log.py
2020-12-05 11:39:47.000000000 +0100
@@ -1,16 +1,28 @@
import logging
from django.core.management.base import BaseCommand
-from mailer.models import MessageLog
+from mailer.models import MessageLog, RESULT_SUCCESS, RESULT_FAILURE
+
+RESULT_CODES = {
+ 'success': [RESULT_SUCCESS],
+ 'failure': [RESULT_FAILURE],
+ 'all': [RESULT_SUCCESS, RESULT_FAILURE]
+}
+
+logger = logging.getLogger(__name__)
class Command(BaseCommand):
help = "Delete mailer log"
def add_arguments(self, parser):
- parser.add_argument('days', nargs=1, type=int)
+ parser.add_argument('days', type=int)
+ parser.add_argument('-r', '--result', choices=RESULT_CODES.keys(),
+ help='Delete logs of messages with the given
result code(s) '
+ '(default: success)')
def handle(self, *args, **options):
- # Compatiblity with Django-1.6
- days = int(options.get('days', args)[0])
- count = MessageLog.objects.purge_old_entries(days)
- logging.info("%s log entries deleted " % count)
+ days = options['days']
+ result_codes = RESULT_CODES.get(options['result'])
+
+ count = MessageLog.objects.purge_old_entries(days, result_codes)
+ logger.info("%s log entries deleted " % count)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/django-mailer-2.0.1/src/mailer/management/commands/retry_deferred.py
new/django-mailer-2.1/src/mailer/management/commands/retry_deferred.py
--- old/django-mailer-2.0.1/src/mailer/management/commands/retry_deferred.py
2019-09-23 19:24:14.000000000 +0200
+++ new/django-mailer-2.1/src/mailer/management/commands/retry_deferred.py
2020-12-05 11:39:47.000000000 +0100
@@ -1,18 +1,21 @@
import logging
+import warnings
from django.core.management.base import BaseCommand
from mailer.models import Message
from mailer.management.helpers import CronArgMixin
+logger = logging.getLogger(__name__)
+
class Command(CronArgMixin, BaseCommand):
help = "Attempt to resend any deferred mail."
def handle(self, *args, **options):
- if options['cron'] == 0:
- logging.basicConfig(level=logging.DEBUG, format="%(message)s")
- else:
- logging.basicConfig(level=logging.ERROR, format="%(message)s")
+ if options['cron']:
+ warnings.warn("retry_deferred's -c/--cron option is no longer "
+ "necessary and will be removed in a future release",
+ DeprecationWarning)
count = Message.objects.retry_deferred() # @@@ new_priority not yet
supported
- logging.info("%s message(s) retried" % count)
+ logger.info("%s message(s) retried" % count)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/django-mailer-2.0.1/src/mailer/management/commands/send_mail.py
new/django-mailer-2.1/src/mailer/management/commands/send_mail.py
--- old/django-mailer-2.0.1/src/mailer/management/commands/send_mail.py
2019-09-23 19:24:14.000000000 +0200
+++ new/django-mailer-2.1/src/mailer/management/commands/send_mail.py
2020-12-05 11:39:47.000000000 +0100
@@ -1,4 +1,5 @@
import logging
+import warnings
from django.conf import settings
from django.core.management.base import BaseCommand
@@ -10,18 +11,20 @@
# allow a sysadmin to pause the sending of mail temporarily.
PAUSE_SEND = getattr(settings, "MAILER_PAUSE_SEND", False)
+logger = logging.getLogger(__name__)
+
class Command(CronArgMixin, BaseCommand):
help = "Do one pass through the mail queue, attempting to send all mail."
def handle(self, *args, **options):
if options['cron'] == 0:
- logging.basicConfig(level=logging.DEBUG, format="%(message)s")
- else:
- logging.basicConfig(level=logging.ERROR, format="%(message)s")
- logging.info("-" * 72)
+ warnings.warn("send_mail's -c/--cron option is no longer "
+ "necessary and will be removed in a future release",
+ DeprecationWarning)
+ logger.info("-" * 72)
# if PAUSE_SEND is turned on don't do anything.
if not PAUSE_SEND:
send_all()
else:
- logging.info("sending is paused, quitting.")
+ logger.info("sending is paused, quitting.")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-mailer-2.0.1/src/mailer/models.py
new/django-mailer-2.1/src/mailer/models.py
--- old/django-mailer-2.0.1/src/mailer/models.py 2019-09-23
19:24:14.000000000 +0200
+++ new/django-mailer-2.1/src/mailer/models.py 2020-12-05 11:39:47.000000000
+0100
@@ -5,6 +5,8 @@
import pickle
import datetime
+import six
+
try:
from django.utils.encoding import python_2_unicode_compatible
except ImportError:
@@ -13,7 +15,10 @@
from django.utils.timezone import now as datetime_now
from django.core.mail import EmailMessage
from django.db import models
-from django.utils.translation import ugettext_lazy as _
+if six.PY2:
+ from django.utils.translation import ugettext_lazy as _
+else:
+ from django.utils.translation import gettext_lazy as _
PRIORITY_HIGH = 1
@@ -30,6 +35,8 @@
PRIORITY_MAPPING = dict((label, v) for (v, label) in PRIORITIES)
+logger = logging.getLogger(__name__)
+
def get_message_id(msg):
# From django.core.mail.message: Email header names are case-insensitive
@@ -108,6 +115,9 @@
@python_2_unicode_compatible
class Message(models.Model):
+ """
+ The email stored for later sending.
+ """
# The actual data - a pickled EmailMessage
message_data = models.TextField()
@@ -168,7 +178,7 @@
retval = []
for e in lst:
if DontSendEntry.objects.has_address(e):
- logging.info("skipping email to %s as on don't send list " %
e.encode("utf-8"))
+ logger.info("skipping email to %s as on don't send list " %
e.encode("utf-8"))
else:
retval.append(e)
return retval
@@ -251,9 +261,12 @@
log_message=log_message,
)
- def purge_old_entries(self, days):
+ def purge_old_entries(self, days, result_codes=None):
+ if result_codes is None:
+ # retro-compatibility with previous versions
+ result_codes = [RESULT_SUCCESS]
limit = datetime_now() - datetime.timedelta(days=days)
- query = self.filter(when_attempted__lt=limit, result=RESULT_SUCCESS)
+ query = self.filter(when_attempted__lt=limit, result__in=result_codes)
count = query.count()
query.delete()
return count
@@ -261,6 +274,10 @@
@python_2_unicode_compatible
class MessageLog(models.Model):
+ """
+ A log entry which stores the result (and optionally a log message) for an
+ attempt to send a Message.
+ """
# fields from Message
message_data = models.TextField()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-mailer-2.0.1/tests/test_mailer.py
new/django-mailer-2.1/tests/test_mailer.py
--- old/django-mailer-2.0.1/tests/test_mailer.py 2020-03-01
20:21:00.000000000 +0100
+++ new/django-mailer-2.1/tests/test_mailer.py 2020-12-05 11:39:47.000000000
+0100
@@ -12,7 +12,7 @@
from django.core.management import call_command
from django.test import TestCase
from django.utils.timezone import now as datetime_now
-from mock import ANY, Mock, patch
+from mock import Mock, patch
import six
import mailer
@@ -90,20 +90,20 @@
self.assertEqual(Message.objects.count(), 0)
def test_purge_old_entries(self):
- # Send one successfully
- with
self.settings(MAILER_EMAIL_BACKEND="django.core.mail.backends.locmem.EmailBackend"):
- mailer.send_mail("Subject", "Body", "[email protected]",
- ["[email protected]"])
- engine.send_all()
-
- # And one failure
- with
self.settings(MAILER_EMAIL_BACKEND="tests.FailingMailerEmailBackend"):
- mailer.send_mail("Subject", "Body", "[email protected]",
- ["[email protected]"])
- engine.send_all()
- Message.objects.retry_deferred()
- engine.send_all()
+ def send_mail(success):
+ backend = ("django.core.mail.backends.locmem.EmailBackend"
+ if success else "tests.FailingMailerEmailBackend")
+ with self.settings(MAILER_EMAIL_BACKEND=backend):
+ mailer.send_mail("Subject", "Body", "[email protected]",
["[email protected]"])
+ engine.send_all()
+ if not success:
+ Message.objects.retry_deferred()
+ engine.send_all()
+
+ # 1 success, 1 failure, and purge only success
+ send_mail(True)
+ send_mail(False)
with patch.object(mailer.models, 'datetime_now') as datetime_now_patch:
datetime_now_patch.return_value = datetime_now() +
datetime.timedelta(days=2)
@@ -112,6 +112,25 @@
self.assertNotEqual(MessageLog.objects.filter(result=RESULT_FAILURE).count(), 0)
self.assertEqual(MessageLog.objects.filter(result=RESULT_SUCCESS).count(), 0)
+ # 1 success, 1 failure, and purge only failures
+ send_mail(True)
+
+ with patch.object(mailer.models, 'datetime_now') as datetime_now_patch:
+ datetime_now_patch.return_value = datetime_now() +
datetime.timedelta(days=2)
+ call_command('purge_mail_log', '1', '-r', 'failure')
+
+
self.assertEqual(MessageLog.objects.filter(result=RESULT_FAILURE).count(), 0)
+
self.assertNotEqual(MessageLog.objects.filter(result=RESULT_SUCCESS).count(), 0)
+
+ # 1 success, 1 failure, and purge everything
+ send_mail(False)
+
+ with patch.object(mailer.models, 'datetime_now') as datetime_now_patch:
+ datetime_now_patch.return_value = datetime_now() +
datetime.timedelta(days=2)
+ call_command('purge_mail_log', '1', '-r', 'all')
+
+ self.assertEqual(MessageLog.objects.count(), 0)
+
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:
@@ -263,12 +282,12 @@
self.assertEqual(Message.objects.deferred().count(), 0)
with
self.settings(MAILER_EMAIL_BACKEND="tests.FailingMailerEmailBackend",
MAILER_EMAIL_MAX_DEFERRED=2): # noqa
- # 2 will get deferred 3 remain undeferred
- with patch("logging.warning") as w:
+ with patch('mailer.engine.logger.warning') as mock_warning:
+ # 2 will get deferred 3 remain undeferred
engine.send_all()
- w.assert_called_once()
- arg = w.call_args[0][0]
+ mock_warning.assert_called_once()
+ arg = mock_warning.call_args[0][0]
self.assertIn("EMAIL_MAX_DEFERRED", arg)
self.assertIn("stopping for this round", arg)
@@ -537,11 +556,11 @@
msg.save()
- with patch("logging.warning") as w:
+ with patch('mailer.engine.logger.warning') as mock_warning:
engine.send_all()
- w.assert_called_once()
- arg = w.call_args[0][0]
+ mock_warning.assert_called_once()
+ arg = mock_warning.call_args[0][0]
self.assertIn("message discarded due to failure in converting
from DB", arg)
self.assertEqual(Message.objects.count(), 0)
@@ -641,39 +660,32 @@
return call_command(command, cron=cron_value)
# newer django; test parsing by passing argument as string
+ # --cron/c command option is deprecated
return call_command(command, '--cron={}'.format(cron_value))
class CommandHelperTest(TestCase):
def test_send_mail_no_cron(self):
- with patch('mailer.management.commands.send_mail.logging') as logging:
- call_command('send_mail')
- logging.basicConfig.assert_called_with(level=logging.DEBUG,
format=ANY)
+ call_command('send_mail')
def test_send_mail_cron_0(self):
- with patch('mailer.management.commands.send_mail.logging') as logging:
- call_command_with_cron_arg('send_mail', 0)
- logging.basicConfig.assert_called_with(level=logging.DEBUG,
format=ANY)
+ # deprecated
+ call_command_with_cron_arg('send_mail', 0)
def test_send_mail_cron_1(self):
- with patch('mailer.management.commands.send_mail.logging') as logging:
- call_command_with_cron_arg('send_mail', 1)
- logging.basicConfig.assert_called_with(level=logging.ERROR,
format=ANY)
+ # deprecated
+ call_command_with_cron_arg('send_mail', 1)
def test_retry_deferred_no_cron(self):
- with patch('mailer.management.commands.retry_deferred.logging') as
logging:
- call_command('retry_deferred')
- logging.basicConfig.assert_called_with(level=logging.DEBUG,
format=ANY)
+ call_command('retry_deferred')
def test_retry_deferred_cron_0(self):
- with patch('mailer.management.commands.retry_deferred.logging') as
logging:
- call_command_with_cron_arg('retry_deferred', 0)
- logging.basicConfig.assert_called_with(level=logging.DEBUG,
format=ANY)
+ # deprecated
+ call_command_with_cron_arg('retry_deferred', 0)
def test_retry_deferred_cron_1(self):
- with patch('mailer.management.commands.retry_deferred.logging') as
logging:
- call_command_with_cron_arg('retry_deferred', 1)
- logging.basicConfig.assert_called_with(level=logging.ERROR,
format=ANY)
+ # deprecated
+ call_command_with_cron_arg('retry_deferred', 1)
class EmailBackendSettingLoopTest(TestCase):
@@ -686,3 +698,32 @@
self.assertIn('mailer.backend.DbBackend', str(catcher.exception))
self.assertIn('EMAIL_BACKEND', str(catcher.exception))
self.assertIn('MAILER_EMAIL_BACKEND', str(catcher.exception))
+
+
+class UseFileLockTest(TestCase):
+ """Test the MAILER_USE_FILE_LOCK setting."""
+
+ def setUp(self):
+ # mocking return_value to prevent "ValueError: not enough values to
unpack"
+ self.patcher_acquire_lock = patch("mailer.engine.acquire_lock",
return_value=(True, True))
+ self.patcher_release_lock = patch("mailer.engine.release_lock",
return_value=(True, True))
+
+ self.mock_acquire_lock = self.patcher_acquire_lock.start()
+ self.mock_release_lock = self.patcher_release_lock.start()
+
+ def test_mailer_use_file_lock_enabled(self):
+ with
self.settings(MAILER_EMAIL_BACKEND="django.core.mail.backends.locmem.EmailBackend"):
+ engine.send_all()
+ self.mock_acquire_lock.assert_called_once()
+ self.mock_release_lock.assert_called_once()
+
+ def test_mailer_use_file_lock_disabled(self):
+ with self.settings(MAILER_USE_FILE_LOCK=False,
+
MAILER_EMAIL_BACKEND="django.core.mail.backends.locmem.EmailBackend"):
+ engine.send_all()
+ self.mock_acquire_lock.assert_not_called()
+ self.mock_release_lock.assert_not_called()
+
+ def tearDown(self):
+ self.patcher_acquire_lock.stop()
+ self.patcher_release_lock.stop()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-mailer-2.0.1/tox.ini
new/django-mailer-2.1/tox.ini
--- old/django-mailer-2.0.1/tox.ini 2020-03-01 20:06:59.000000000 +0100
+++ new/django-mailer-2.1/tox.ini 2020-12-05 11:54:27.000000000 +0100
@@ -4,8 +4,9 @@
py27-django111-test,
py34-django{111,20}-test,
{py35,py36}-django{111,20}-test,
- py36-django{21,22,30}-test,
- {py27,py34,py35,py36}-flake,
+ py38-django{21,22,30,31}-test,
+ py39-django31-test,
+ {py27,py38}-flake,
checkmanifest,
[testenv]
@@ -14,6 +15,10 @@
py34: python3.4
py35: python3.5
py36: python3.6
+ py37: python3.7
+ py38: python3.8
+ py39: python3.9
+
commands =
test: coverage run ./runtests.py
flake: flake8 --statistics --benchmark
@@ -25,12 +30,16 @@
py34: mock==3.0.5
py35: mock==3.0.5
py36: mock==4.0.1
- django111: Django==1.11.28
+ py37: mock==4.0.1
+ py38: mock==4.0.1
+ py39: mock==4.0.1
+ django111: Django==1.11.29
django20: Django==2.0.13
django21: Django==2.1.15
- django22: Django==2.2.10
- django30: Django==3.0.3
- flake: flake8==3.7.7
+ 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]