summaryrefslogtreecommitdiff
path: root/docs/topics
diff options
context:
space:
mode:
Diffstat (limited to 'docs/topics')
-rw-r--r--docs/topics/email.txt195
1 files changed, 102 insertions, 93 deletions
diff --git a/docs/topics/email.txt b/docs/topics/email.txt
index 36f7b71e97..0af0bf073d 100644
--- a/docs/topics/email.txt
+++ b/docs/topics/email.txt
@@ -649,6 +649,106 @@ to "/contact/thanks/" when it's done::
.. _Header injection: http://www.nyphp.org/phundamentals/8_Preventing-Email-Header-Injection.html
+.. _topics-sending-multiple-emails:
+
+Sending many messages efficiently
+---------------------------------
+
+Establishing and closing an SMTP connection (or any other network connection,
+for that matter) is an expensive process. If you have a lot of emails to send,
+it makes sense to reuse an SMTP connection, rather than creating and
+destroying a connection every time you want to send an email.
+
+There are two ways to tell an email backend to reuse a connection. Both
+require an email backend instance obtained via :func:`get_connection`, which is
+documented in :ref:`topic-email-backends`.
+
+The first approach is to obtain an email backend instance from
+:func:`get_connection` and use its ``send_messages()`` method. This takes a
+list of :class:`EmailMessage` (or subclass) instances, and sends them all using
+that single connection. As a consequence, any :class:`connection
+<EmailMessage>` set on an individual message is ignored.
+
+For example, if you have a function called ``get_notification_emails()`` that
+returns a list of :class:`EmailMessage` objects representing some periodic
+email you wish to send out, you could send these emails using a single call to
+``send_messages()``::
+
+ from django.core import mail
+
+ connection = mail.get_connection() # Use default email connection
+ messages = get_notification_emails()
+ connection.send_messages(messages)
+
+In this example, the call to ``send_messages()`` opens a connection on the
+backend, sends the list of messages, and then closes the connection again.
+
+The second approach is to use the ``open()`` and ``close()`` methods on the
+email backend to manually control the connection. ``send_messages()`` will not
+open or close the connection if it is already open, so if you
+manually open the connection, you can control when it is closed. For example::
+
+ from django.core import mail
+
+ connection = mail.get_connection()
+
+ # Manually open the connection.
+ connection.open()
+
+ # Construct an email message that will use the connection.
+ email1 = mail.EmailMessage(
+ "Hello",
+ "Body goes here",
+ "from@example.com",
+ ["to1@example.com"],
+ connection=connection,
+ )
+ # Send the email through its connection. The connection was already open,
+ # so send() leaves it open after sending.
+ email1.send()
+
+ # Construct two more email messages. (Passing None as the third argument
+ # uses settings.DEFAULT_FROM_EMAIL as the "From:" address.)
+ email2 = mail.EmailMessage("Hi", "Message", None, ["to2@example.com"])
+ email3 = mail.EmailMessage("Hi", "Message", None, ["to3@example.com"])
+ # Send the two messages. The connection is still open.
+ connection.send_messages([email2, email3])
+
+ # Because we opened it, we need to manually close the connection.
+ connection.close()
+
+When you manually open a backend's connection, you are responsible for ensuring
+it gets closed. The example above actually has a bug: if an exception occurs
+while sending the messages, the connection will not be closed. You could fix
+this with a try-finally statement. Or it's often more convenient to use the
+backend instance as a context manager, which will automatically call ``open()``
+and ``close()`` as needed.
+
+This is equivalent to the previous example, but uses the backend as a
+:ref:`context manager <context-managers>` to avoid leaving the connection open
+on errors::
+
+ from django.core import mail
+
+ with mail.get_connection() as connection:
+ # The backend connection is automatically opened inside the context.
+ email1 = mail.EmailMessage(
+ "Hello",
+ "Body goes here",
+ "from@example.com",
+ ["to1@example.com"],
+ connection=connection,
+ )
+ email1.send()
+
+ # The connection is still open, and is reused for the second send.
+ email2 = mail.EmailMessage("Hi", "Message", None, ["to2@example.com"])
+ email3 = mail.EmailMessage("Hi", "Message", None, ["to3@example.com"])
+ connection.send_messages([email2, email3])
+
+ # After exiting the context (either normally or because of an error),
+ # the backend connection is automatically closed.
+
.. _topic-email-backends:
Email backends
@@ -668,25 +768,8 @@ The email backend class has the following methods:
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()
+``open()`` and ``close()`` as needed. An example is in
+:ref:`topics-sending-multiple-emails`.
Django ships with several email sending backends. With the exception of the
SMTP backend (which is the default), these backends are only useful during
@@ -844,80 +927,6 @@ email backend.
Passing ``fail_silently`` as positional argument is deprecated.
-.. _topics-sending-multiple-emails:
-
-Sending multiple emails
------------------------
-
-Establishing and closing an SMTP connection (or any other network connection,
-for that matter) is an expensive process. If you have a lot of emails to send,
-it makes sense to reuse an SMTP connection, rather than creating and
-destroying a connection every time you want to send an email.
-
-There are two ways you tell an email backend to reuse a connection.
-
-Firstly, you can use the ``send_messages()`` method on a connection. This takes
-a list of :class:`EmailMessage` (or subclass) instances, and sends them all
-using that single connection. As a consequence, any :class:`connection
-<EmailMessage>` set on an individual message is ignored.
-
-For example, if you have a function called ``get_notification_email()`` that
-returns a list of :class:`EmailMessage` objects representing some periodic
-email you wish to send out, you could send these emails using a single call to
-``send_messages()``::
-
- from django.core import mail
-
- connection = mail.get_connection() # Use default email connection
- messages = get_notification_email()
- connection.send_messages(messages)
-
-In this example, the call to ``send_messages()`` opens a connection on the
-backend, sends the list of messages, and then closes the connection again.
-
-The second approach is to use the ``open()`` and ``close()`` methods on the
-email backend to manually control the connection. ``send_messages()`` will not
-manually open or close the connection if it is already open, so if you
-manually open the connection, you can control when it is closed. For example::
-
- from django.core import mail
-
- connection = mail.get_connection()
-
- # Manually open the connection
- connection.open()
-
- # Construct an email message that uses the connection
- email1 = mail.EmailMessage(
- "Hello",
- "Body goes here",
- "from@example.com",
- ["to1@example.com"],
- connection=connection,
- )
- email1.send() # Send the email
-
- # Construct two more messages
- email2 = mail.EmailMessage(
- "Hello",
- "Body goes here",
- "from@example.com",
- ["to2@example.com"],
- )
- email3 = mail.EmailMessage(
- "Hello",
- "Body goes here",
- "from@example.com",
- ["to3@example.com"],
- )
-
- # Send the two emails in a single call.
- connection.send_messages([email2, email3])
- # The connection was already open so send_messages() doesn't close it.
- # We need to manually close the connection.
- connection.close()
-
-
Configuring email for development
=================================