Skip to content

Commit 8bb01b1

Browse files
medmundsnessita
authored andcommitted
Refs #35514 -- Moved and renamed "Sending multiple emails" in email docs.
Moved "Sending multiple emails" from the "Email backends" section to the "Sending messages" section and renamed it to "Sending many messages efficiently" to better reflect its content. Moved the related connection manager example from the "Email backends" intro into the same section.
1 parent 5a79a09 commit 8bb01b1

1 file changed

Lines changed: 102 additions & 93 deletions

File tree

docs/topics/email.txt

Lines changed: 102 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,106 @@ to "/contact/thanks/" when it's done::
649649

650650
.. _Header injection: http://www.nyphp.org/phundamentals/8_Preventing-Email-Header-Injection.html
651651

652+
.. _topics-sending-multiple-emails:
653+
654+
Sending many messages efficiently
655+
---------------------------------
656+
657+
Establishing and closing an SMTP connection (or any other network connection,
658+
for that matter) is an expensive process. If you have a lot of emails to send,
659+
it makes sense to reuse an SMTP connection, rather than creating and
660+
destroying a connection every time you want to send an email.
661+
662+
There are two ways to tell an email backend to reuse a connection. Both
663+
require an email backend instance obtained via :func:`get_connection`, which is
664+
documented in :ref:`topic-email-backends`.
665+
666+
The first approach is to obtain an email backend instance from
667+
:func:`get_connection` and use its ``send_messages()`` method. This takes a
668+
list of :class:`EmailMessage` (or subclass) instances, and sends them all using
669+
that single connection. As a consequence, any :class:`connection
670+
<EmailMessage>` set on an individual message is ignored.
671+
672+
For example, if you have a function called ``get_notification_emails()`` that
673+
returns a list of :class:`EmailMessage` objects representing some periodic
674+
email you wish to send out, you could send these emails using a single call to
675+
``send_messages()``::
676+
677+
from django.core import mail
678+
679+
connection = mail.get_connection() # Use default email connection
680+
messages = get_notification_emails()
681+
connection.send_messages(messages)
682+
683+
In this example, the call to ``send_messages()`` opens a connection on the
684+
backend, sends the list of messages, and then closes the connection again.
685+
686+
The second approach is to use the ``open()`` and ``close()`` methods on the
687+
email backend to manually control the connection. ``send_messages()`` will not
688+
open or close the connection if it is already open, so if you
689+
manually open the connection, you can control when it is closed. For example::
690+
691+
from django.core import mail
692+
693+
connection = mail.get_connection()
694+
695+
# Manually open the connection.
696+
connection.open()
697+
698+
# Construct an email message that will use the connection.
699+
email1 = mail.EmailMessage(
700+
"Hello",
701+
"Body goes here",
702+
"from@example.com",
703+
["to1@example.com"],
704+
connection=connection,
705+
)
706+
# Send the email through its connection. The connection was already open,
707+
# so send() leaves it open after sending.
708+
email1.send()
709+
710+
# Construct two more email messages. (Passing None as the third argument
711+
# uses settings.DEFAULT_FROM_EMAIL as the "From:" address.)
712+
email2 = mail.EmailMessage("Hi", "Message", None, ["to2@example.com"])
713+
email3 = mail.EmailMessage("Hi", "Message", None, ["to3@example.com"])
714+
# Send the two messages. The connection is still open.
715+
connection.send_messages([email2, email3])
716+
717+
# Because we opened it, we need to manually close the connection.
718+
connection.close()
719+
720+
When you manually open a backend's connection, you are responsible for ensuring
721+
it gets closed. The example above actually has a bug: if an exception occurs
722+
while sending the messages, the connection will not be closed. You could fix
723+
this with a try-finally statement. Or it's often more convenient to use the
724+
backend instance as a context manager, which will automatically call ``open()``
725+
and ``close()`` as needed.
726+
727+
This is equivalent to the previous example, but uses the backend as a
728+
:ref:`context manager <context-managers>` to avoid leaving the connection open
729+
on errors::
730+
731+
from django.core import mail
732+
733+
with mail.get_connection() as connection:
734+
# The backend connection is automatically opened inside the context.
735+
email1 = mail.EmailMessage(
736+
"Hello",
737+
"Body goes here",
738+
"from@example.com",
739+
["to1@example.com"],
740+
connection=connection,
741+
)
742+
email1.send()
743+
744+
# The connection is still open, and is reused for the second send.
745+
email2 = mail.EmailMessage("Hi", "Message", None, ["to2@example.com"])
746+
email3 = mail.EmailMessage("Hi", "Message", None, ["to3@example.com"])
747+
connection.send_messages([email2, email3])
748+
749+
# After exiting the context (either normally or because of an error),
750+
# the backend connection is automatically closed.
751+
652752
.. _topic-email-backends:
653753

654754
Email backends
@@ -668,25 +768,8 @@ The email backend class has the following methods:
668768
open, it will be left open after mail has been sent.
669769

670770
It can also be used as a context manager, which will automatically call
671-
``open()`` and ``close()`` as needed::
672-
673-
from django.core import mail
674-
675-
with mail.get_connection() as connection:
676-
mail.EmailMessage(
677-
subject1,
678-
body1,
679-
from1,
680-
[to1],
681-
connection=connection,
682-
).send()
683-
mail.EmailMessage(
684-
subject2,
685-
body2,
686-
from2,
687-
[to2],
688-
connection=connection,
689-
).send()
771+
``open()`` and ``close()`` as needed. An example is in
772+
:ref:`topics-sending-multiple-emails`.
690773

691774
Django ships with several email sending backends. With the exception of the
692775
SMTP backend (which is the default), these backends are only useful during
@@ -844,80 +927,6 @@ email backend.
844927

845928
Passing ``fail_silently`` as positional argument is deprecated.
846929

847-
.. _topics-sending-multiple-emails:
848-
849-
Sending multiple emails
850-
-----------------------
851-
852-
Establishing and closing an SMTP connection (or any other network connection,
853-
for that matter) is an expensive process. If you have a lot of emails to send,
854-
it makes sense to reuse an SMTP connection, rather than creating and
855-
destroying a connection every time you want to send an email.
856-
857-
There are two ways you tell an email backend to reuse a connection.
858-
859-
Firstly, you can use the ``send_messages()`` method on a connection. This takes
860-
a list of :class:`EmailMessage` (or subclass) instances, and sends them all
861-
using that single connection. As a consequence, any :class:`connection
862-
<EmailMessage>` set on an individual message is ignored.
863-
864-
For example, if you have a function called ``get_notification_email()`` that
865-
returns a list of :class:`EmailMessage` objects representing some periodic
866-
email you wish to send out, you could send these emails using a single call to
867-
``send_messages()``::
868-
869-
from django.core import mail
870-
871-
connection = mail.get_connection() # Use default email connection
872-
messages = get_notification_email()
873-
connection.send_messages(messages)
874-
875-
In this example, the call to ``send_messages()`` opens a connection on the
876-
backend, sends the list of messages, and then closes the connection again.
877-
878-
The second approach is to use the ``open()`` and ``close()`` methods on the
879-
email backend to manually control the connection. ``send_messages()`` will not
880-
manually open or close the connection if it is already open, so if you
881-
manually open the connection, you can control when it is closed. For example::
882-
883-
from django.core import mail
884-
885-
connection = mail.get_connection()
886-
887-
# Manually open the connection
888-
connection.open()
889-
890-
# Construct an email message that uses the connection
891-
email1 = mail.EmailMessage(
892-
"Hello",
893-
"Body goes here",
894-
"from@example.com",
895-
["to1@example.com"],
896-
connection=connection,
897-
)
898-
email1.send() # Send the email
899-
900-
# Construct two more messages
901-
email2 = mail.EmailMessage(
902-
"Hello",
903-
"Body goes here",
904-
"from@example.com",
905-
["to2@example.com"],
906-
)
907-
email3 = mail.EmailMessage(
908-
"Hello",
909-
"Body goes here",
910-
"from@example.com",
911-
["to3@example.com"],
912-
)
913-
914-
# Send the two emails in a single call.
915-
connection.send_messages([email2, email3])
916-
# The connection was already open so send_messages() doesn't close it.
917-
# We need to manually close the connection.
918-
connection.close()
919-
920-
921930
Configuring email for development
922931
=================================
923932

0 commit comments

Comments
 (0)