summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordiaxoaine <42137630+diaxoaine@users.noreply.github.com>2026-06-11 09:58:41 +0700
committernessita <124304+nessita@users.noreply.github.com>2026-06-16 19:56:20 -0300
commit09434486302078c3649e034dfa74cf3f102db20b (patch)
treee9dd12e8dd1d1e591c516e4f26e3eaa0bd630cd8
parentb5b53afa29c53a79ae92ed5298144db0cab0ea3b (diff)
Fixed #37152 -- Raised ValueError when Bcc is used in EmailMessage headers.
Bcc addresses are sent via the SMTP envelope and must never appear in the message itself. A "Bcc" key in `extra_headers` was not excluded like From/To/Cc/Reply-To, so it leaked into the generated message as a visible header. Thanks Mike Edmunds for reviews.
-rw-r--r--django/core/mail/message.py8
-rw-r--r--docs/releases/6.1.txt4
-rw-r--r--docs/topics/email.txt2
-rw-r--r--tests/mail/tests.py12
4 files changed, 24 insertions, 2 deletions
diff --git a/django/core/mail/message.py b/django/core/mail/message.py
index 549b8050fe..2b396d870b 100644
--- a/django/core/mail/message.py
+++ b/django/core/mail/message.py
@@ -360,8 +360,14 @@ class EmailMessage:
# Use cached DNS_NAME for performance
msg["Message-ID"] = make_msgid(domain=DNS_NAME)
for name, value in self.extra_headers.items():
+ header = name.lower()
+ if header == "bcc":
+ raise ValueError(
+ 'Bcc is not a valid email header. Use the "bcc" '
+ "argument to specify blind carbon copy recipients."
+ )
# Avoid headers handled above.
- if name.lower() not in {"from", "to", "cc", "reply-to"}:
+ if header not in {"from", "to", "cc", "reply-to"}:
msg[name] = force_str(value, strings_only=True)
self._idna_encode_address_header_domains(msg)
return msg
diff --git a/docs/releases/6.1.txt b/docs/releases/6.1.txt
index adb66a013d..03a9b8cdfd 100644
--- a/docs/releases/6.1.txt
+++ b/docs/releases/6.1.txt
@@ -470,6 +470,10 @@ Email
``EmailMessage``. (This behavior was never documented. The ``send()`` method
will still *use* a ``connection`` that is set on the message before sending.)
+* :meth:`.EmailMessage.message` now raises a ``ValueError`` if ``Bcc`` is
+ included in the ``headers`` argument or ``extra_headers`` attribute. Use the
+ ``bcc`` argument instead.
+
Models
------
diff --git a/docs/topics/email.txt b/docs/topics/email.txt
index d52ffd12ed..c9e3cfd1ce 100644
--- a/docs/topics/email.txt
+++ b/docs/topics/email.txt
@@ -505,7 +505,7 @@ email backend API :ref:`provides an alternative
* ``cc``: A list or tuple of recipient addresses used in the "Cc" header
when sending the email.
- * ``bcc``: A list or tuple of addresses used in the "Bcc" header when
+ * ``bcc``: A list or tuple of addresses used for blind carbon copies when
sending the email.
* ``reply_to``: A list or tuple of recipient addresses used in the
diff --git a/tests/mail/tests.py b/tests/mail/tests.py
index 7963b81892..01a37284c1 100644
--- a/tests/mail/tests.py
+++ b/tests/mail/tests.py
@@ -397,6 +397,18 @@ class EmailMessageTests(MailTestsMixin, SimpleTestCase):
self.assertNotIn("bcc@example.com", message.as_string())
self.assertEqual(email.recipients(), ["to@example.com", "bcc@example.com"])
+ def test_bcc_in_headers_raises_error(self):
+ email = EmailMessage(
+ to=["to@example.com"],
+ headers={"Bcc": "bcc@example.com"},
+ )
+ msg = (
+ 'Bcc is not a valid email header. Use the "bcc" argument to '
+ "specify blind carbon copy recipients."
+ )
+ with self.assertRaisesMessage(ValueError, msg):
+ email.message()
+
def test_reply_to(self):
with self.subTest("Single Reply-To"):
email = EmailMessage(