Commit 4aa80149 authored by Daniel Neuhäuser's avatar Daniel Neuhäuser Committed by Tim Graham
Browse files

Fixed #22327 -- Turned BaseEmailBackend into a context manager

Changed the BaseEmailBackend to allow usage as context manager to open
and close connections.
parent d902fd62
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -6,6 +6,13 @@ class BaseEmailBackend(object):
    Base class for email backend implementations.

    Subclasses must at least overwrite send_messages().

   open() and close() can be called indirectly by using a backend object as a
   context manager:

       with backend as connection:
           # do something with connection
           pass
    """
    def __init__(self, fail_silently=False, **kwargs):
        self.fail_silently = fail_silently
@@ -32,6 +39,13 @@ class BaseEmailBackend(object):
        """Close a network connection."""
        pass

    def __enter__(self):
        self.open()
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        self.close()

    def send_messages(self, email_messages):
        """
        Sends one or more EmailMessage objects and returns the number of email
+2 −1
Original line number Diff line number Diff line
@@ -91,7 +91,8 @@ Cache
Email
^^^^^

* ...
* :ref:`Email backends <topic-email-backends>` now support the context manager
  protocol for opening and closing connections.

File Storage
^^^^^^^^^^^^
+15 −0
Original line number Diff line number Diff line
@@ -393,6 +393,21 @@ The email backend class has the following methods:
  connection afterwards. If the connection is already open, it will be
  left open after mail has been sent.

It can also be used as a context manager, which will automatically call
``open()`` and ``close()`` as needed::

    from django.core import mail

    with mail.get_connection() as connection:
        mail.EmailMessage(subject1, body1, from1, [to1],
                          connection=connection).send()
        mail.EmailMessage(subject2, body2, from2, [to2],
                          connection=connection).send()

.. versionadded:: 1.8

    The context manager protocol was added.

Obtaining an instance of an email backend
-----------------------------------------

+21 −0
Original line number Diff line number Diff line
@@ -638,6 +638,27 @@ class BaseEmailBackendTests(HeadersCheckMixin, object):
        except Exception as e:
            self.fail("close() unexpectedly raised an exception: %s" % e)

    def test_use_as_contextmanager(self):
        """
        Test that the connection can be used as a contextmanager.
        """
        opened = [False]
        closed = [False]
        conn = mail.get_connection(username='', password='')

        def open():
            opened[0] = True
        conn.open = open

        def close():
            closed[0] = True
        conn.close = close
        with conn as same_conn:
            self.assertTrue(opened[0])
            self.assertIs(same_conn, conn)
            self.assertFalse(closed[0])
        self.assertTrue(closed[0])


class LocmemBackendTests(BaseEmailBackendTests, SimpleTestCase):
    email_backend = 'django.core.mail.backends.locmem.EmailBackend'