Opened 11 months ago
Last modified 4 months ago
#35033 closed Bug
EmailMessage repeats "To" header if provided via the headers kwargs — at Initial Version
Reported by: | Aalekh Patel | Owned by: | nobody |
---|---|---|---|
Component: | Core (Mail) | Version: | dev |
Severity: | Normal | Keywords: | email, headers, compat32 |
Cc: | Adam Johnson, Florian Apolloner, David Wobrock, Mike Edmunds | Triage Stage: | Ready for checkin |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | yes | UI/UX: | no |
Description
If you create an EmailMessage
instance with a "To"
key in the headers=
kwarg, it attaches the To
header to the email two times, violating RFC 5322#3.6.
My suspicion is that it attaches it the first time from extra_headers
in self._set_list_header_if_not_empty(msg, 'To', self.to)
at django.core.mail.message:266 and the second time again from extra_headers
at django.core.mail.message:282
message = EmailMessage( subject="test subject", body="test body", from_email="from@example.com", to=["guy1@example.com"], headers={ "To": ", ".join(["guy1@example.com", "guy2@example.com", "guy3@example.com"]), }, )
For example, here is a Python 3.9.18 shell output for the EmailMessage
above that shows the To
header appears twice.
>>> from django.core.mail import EmailMessage >>> message = EmailMessage(subject="test subject", body="test body", from_email="from@example.com",to=["guy1@example.com"], headers={"To": ", ".join(["guy1@example.com", "guy2@example.com", "guy3@example.com"])}) >>> print(list(message.message().raw_items())) [('Content-Type', 'text/plain; charset="utf-8"'), ('MIME-Version', '1.0'), ('Content-Transfer-Encoding', '7bit'), ('Subject', 'test subject'), ('From', 'from@example.com'), ('To', 'guy1@example.com, guy2@example.com, guy3@example.com'), ('Date', 'Wed, 13 Dec 2023 15:59:31 -0000'), ('Message-ID', '<170248317136.759.5778419642073676754@036d358ca984>'), ('To', 'guy1@example.com, guy2@example.com, guy3@example.com')]
My current workaround is to override the EmailMessage::message
method to skip adding the To
, Cc
, From
, Reply-To
headers the second time, since we're already attaching them the first time above. In other words:
@@ -21,7 +21,7 @@ # 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 + if name.lower() not in ('from', 'to', 'cc', 'reply-to'): # These are already handled msg[name] = value return msg