#35033: EmailMessage repeats header if provided via the headers kwargs
-------------------------------------+-------------------------------------
     Reporter:  Aalekh Patel         |                    Owner:  Salvo
                                     |  Polizzi
         Type:  Bug                  |                   Status:  assigned
    Component:  Core (Mail)          |                  Version:  dev
     Severity:  Normal               |               Resolution:
     Keywords:  email, headers,      |             Triage Stage:  Accepted
  compat32                           |
    Has patch:  1                    |      Needs documentation:  0
  Needs tests:  0                    |  Patch needs improvement:  1
Easy pickings:  0                    |                    UI/UX:  0
-------------------------------------+-------------------------------------
Changes (by Mike Edmunds):

 * keywords:  email, headers => email, headers, compat32

Comment:

 Ah, the forum mentions the ticket I couldn't find: #17444 allowed
 different `to=...` and `headers={"To": ...}`

 I think this got broken when
 `EmailMessage._set_list_header_if_not_empty()` was added. And `cc` and
 `reply_to` are likely broken in the same way (based on reading the code).

 The problem is that Python's `email.message.Message`
 
[https://docs.python.org/3/library/email.compat32-message.html#email.message.Message.__setitem__
 behaves as a multi-value dict when assigning to header keys], but
 
[https://docs.python.org/3/library/email.compat32-message.html#email.message.Message.__getitem__
 returns only one of the values when reading from keys]. The current logic
 in `_set_list_header_if_not_empty()` assumes it works like a regular dict,
 and the tests from #17444 were insufficient to catch that mistake.

 The minimal and safe fix is something like:

 1. First make the existing tests fail on current buggy behavior: update
 
[https://github.com/django/django/blob/stable/5.1.x/tests/mail/tests.py#L410-L412
 test_to_header()] to use
 
[https://docs.python.org/3/library/email.compat32-message.html#email.message.Message.get_all
 get_all("To")] and verify there's only the one correct value in the list.
 Same thing in
 [https://github.com/django/django/blob/stable/5.1.x/tests/mail/tests.py#L439
 test_reply_to_header()]. Wouldn't hurt to update some other nearby tests
 in the same way, and add a test_cc_header().

 2. Then fix
 
[https://github.com/django/django/blob/stable/5.1.x/django/core/mail/message.py#L432
 this line] in `_set_list_header_if_not_empty()` so it only assigns to the
 header if there's not already a header there. (Indent it one level so it
 only runs in the except clause.)

 I would suggest we ''not try to'' enforce ​RFC 5322-3.6 email header
 counting rules in Django. If/when Django [https://groups.google.com/g
 /django-developers/c/2zf9GQtjdIk moves to Python's modern email API],
 those (and many other email header restrictions) will be enforced by
 Python.
-- 
Ticket URL: <https://code.djangoproject.com/ticket/35033#comment:33>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/010701905201e656-ea43914b-534b-4693-9abe-094b0368a8e9-000000%40eu-central-1.amazonses.com.

Reply via email to