From b9098538a966fdc1f2b5ee51c094ca3de4db6344 Mon Sep 17 00:00:00 2001 From: Mike Edmunds Date: Sat, 29 Jun 2024 14:08:56 -0700 Subject: [PATCH] Fixed #35033, Refs #28912 -- Fixed repeated headers in EmailMessage. Fixed a regression which would cause multiple To, Cc, and Reply-To headers in the result of EmailMessage.message() if values were supplied for both to/cc/reply_to and the corresponding extra_headers fields. Updated related tests to check the generated message() has exactly one of each expected header using get_all(). Regression in b03d5002955256c4b3ed7cfae5150eb79c0eb97e. --- django/core/mail/message.py | 16 ++++++++-------- tests/mail/tests.py | 21 +++++++++++---------- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/django/core/mail/message.py b/django/core/mail/message.py index 2eb8aa354b..eb467de429 100644 --- a/django/core/mail/message.py +++ b/django/core/mail/message.py @@ -286,7 +286,8 @@ class EmailMessage: # Use cached DNS_NAME for performance msg["Message-ID"] = make_msgid(domain=DNS_NAME) for name, value in self.extra_headers.items(): - if name.lower() != "from": # From is already handled + # Avoid headers handled above. + if name.lower() not in {"from", "to", "cc", "reply-to"}: msg[name] = value return msg @@ -427,14 +428,13 @@ class EmailMessage: def _set_list_header_if_not_empty(self, msg, header, values): """ Set msg's header, either from self.extra_headers, if present, or from - the values argument. + the values argument if not empty. """ - if values: - try: - value = self.extra_headers[header] - except KeyError: - value = ", ".join(str(v) for v in values) - msg[header] = value + try: + msg[header] = self.extra_headers[header] + except KeyError: + if values: + msg[header] = ", ".join(str(v) for v in values) class EmailMultiAlternatives(EmailMessage): diff --git a/tests/mail/tests.py b/tests/mail/tests.py index 1f7cbbadca..a0d28eb0ce 100644 --- a/tests/mail/tests.py +++ b/tests/mail/tests.py @@ -223,7 +223,7 @@ class MailTests(HeadersCheckMixin, SimpleTestCase): cc=["foo@example.com"], headers={"Cc": "override@example.com"}, ).message() - self.assertEqual(message["Cc"], "override@example.com") + self.assertEqual(message.get_all("Cc"), ["override@example.com"]) def test_cc_in_headers_only(self): message = EmailMessage( @@ -233,7 +233,7 @@ class MailTests(HeadersCheckMixin, SimpleTestCase): ["to@example.com"], headers={"Cc": "foo@example.com"}, ).message() - self.assertEqual(message["Cc"], "foo@example.com") + self.assertEqual(message.get_all("Cc"), ["foo@example.com"]) def test_reply_to(self): email = EmailMessage( @@ -379,7 +379,7 @@ class MailTests(HeadersCheckMixin, SimpleTestCase): headers={"From": "from@example.com"}, ) message = email.message() - self.assertEqual(message["From"], "from@example.com") + self.assertEqual(message.get_all("From"), ["from@example.com"]) def test_to_header(self): """ @@ -393,7 +393,7 @@ class MailTests(HeadersCheckMixin, SimpleTestCase): headers={"To": "mailing-list@example.com"}, ) message = email.message() - self.assertEqual(message["To"], "mailing-list@example.com") + self.assertEqual(message.get_all("To"), ["mailing-list@example.com"]) self.assertEqual( email.to, ["list-subscriber@example.com", "list-subscriber2@example.com"] ) @@ -408,7 +408,8 @@ class MailTests(HeadersCheckMixin, SimpleTestCase): ) message = email.message() self.assertEqual( - message["To"], "list-subscriber@example.com, list-subscriber2@example.com" + message.get_all("To"), + ["list-subscriber@example.com, list-subscriber2@example.com"], ) self.assertEqual( email.to, ["list-subscriber@example.com", "list-subscriber2@example.com"] @@ -421,7 +422,7 @@ class MailTests(HeadersCheckMixin, SimpleTestCase): "bounce@example.com", headers={"To": "to@example.com"}, ).message() - self.assertEqual(message["To"], "to@example.com") + self.assertEqual(message.get_all("To"), ["to@example.com"]) def test_reply_to_header(self): """ @@ -436,7 +437,7 @@ class MailTests(HeadersCheckMixin, SimpleTestCase): headers={"Reply-To": "override@example.com"}, ) message = email.message() - self.assertEqual(message["Reply-To"], "override@example.com") + self.assertEqual(message.get_all("Reply-To"), ["override@example.com"]) def test_reply_to_in_headers_only(self): message = EmailMessage( @@ -446,7 +447,7 @@ class MailTests(HeadersCheckMixin, SimpleTestCase): ["to@example.com"], headers={"Reply-To": "reply_to@example.com"}, ).message() - self.assertEqual(message["Reply-To"], "reply_to@example.com") + self.assertEqual(message.get_all("Reply-To"), ["reply_to@example.com"]) def test_multiple_message_call(self): """ @@ -461,9 +462,9 @@ class MailTests(HeadersCheckMixin, SimpleTestCase): headers={"From": "from@example.com"}, ) message = email.message() - self.assertEqual(message["From"], "from@example.com") + self.assertEqual(message.get_all("From"), ["from@example.com"]) message = email.message() - self.assertEqual(message["From"], "from@example.com") + self.assertEqual(message.get_all("From"), ["from@example.com"]) def test_unicode_address_header(self): """