Changed Email-Address handling from 3.13.13 to 3.13.14

Hi!

We’re running an API that among other tasks is supposed to send emails on behalf of the clients.

Sometimes we receive malformed address headers of the form To: test@test.de <test@test.de> (for whatever reason) and so far our approach has been to get rid of the malformed display name and normalize this to just the address part.

Until python-3.13.13 this was easy because python would just drop the realname, but this has changed in python-3.13.14:

> tox exec -e py31313-django52 -- python3
py31313-django52: commands[0]> python3
Python 3.13.13 (main, Jul 29 2026, 17:47:36) [GCC 15.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import email; import email.policy; m = email.message_from_string('To: test@test.de <test@test.de>\nFrom: obligatoryfrom@example.example\n\n', policy=email.policy.default); m['To']
'test@test.de'
>>>
  py31313-django52: OK (3.03=setup[0.11]+cmd[2.92] seconds)
  congratulations :) (3.05 seconds)
> tox exec -e py31314-django52 -- python3
py31314-django52: commands[0]> python3
Python 3.13.14 (main, Jul 30 2026, 13:33:37) [GCC 15.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import email; import email.policy; m = email.message_from_string('To: test@test.de <test@test.de>\nFrom: obligatoryfrom@example.example\n\n', policy=email.policy.default); m['To']
'test@test.de, <>'
>>>
  py31314-django52: OK (2.97=setup[0.11]+cmd[2.86] seconds)
  congratulations :) (3.00 seconds)

Python 3.13.14 (current version in openSUSE 16.0) splits the address into two addresses, the second is completely empty.

I can’t say I understand the reason behind this or if this is correct according to standards or not. Could anyone give an explanation or advice here?

In any case we would have the option of disallowing those kinds of addresses instead of trying to normalize them, as an uncoded @-sign in the realname part is clearly forbidden.

With a correctly encoded address-header, e.g. To: "test@test.de" <test@test.de> both python versions behave identically.

Python 3.11 and earlier (down to 3.6 I think) behave identical to 3.13.13.

I’d be grateful for any feedback
Best regards
Friedel

I don’t have expertise here and have very little idea if its right or wrong. Though I think this is the change that caused it is: bpo-39100: _header_value_parser: do not treat a Group as invalid-mail… · python/cpython@b413bc7 · GitHub

Thanks for the pointer.

I did look at the changelog at Changelog — Python 3.13.15 documentation for 3.13.14-final and noticed that there are 4 (maybe 5) changes pertaining to address headers:

(Sorry, I can’t put more than 2 links in my post.)

And maybe httpx://github.com/python/cpython/issues/145831

Whatever is causing this, it’s resulting in a completely empty address spec (‘<>’) so as a workaround for now I decided to simply drop addresses with empty usernames.

This is next to our workaround for python 3.11 which in the same test scenario simply left unencoded ‘@’ in the username part caused empty domain and display_name.

Best regards
Friedel