Commit ffd4359
committed
[FIX] base: avoid bpo-35805 corrupting Message-Id
Python 3 before 3.8 has a bug that causes the email.policy classes to
incorrectly fold and RFC2047-encode "identification fields" in email
messages. This mainly applies to Message-Id, References, and In-Reply-To
fields.
We are impacted by this bug since odoo#35929 where we switched to
using the "modern" email.message API.
RFC2047 section 5 clearly states that those headers/fields are not to be
encoded, and that would violate RFC5322.
Further, such a folded Message-Id is considered non-RFC-conformant by
popular MTAs (GMail, Outlook), which will then generate *another*
Message-Id field, causing the original threading information to be lost.
Replies to such a modified message will reference the new, unknown
Message-Id, and won't be attached to the original thread.
The solution we adopt here is to monkey-patch the SMTP policies to
special-case those identification fields and deactivate the automatic
folding, until the bug is properly and fully fixed in the standard lib.
Some considerations taken into account for this patch:
- `email.policy.SMTP` is being monkey-patched globally to make sure we
fix all possible places where Messages are being encoded/folded
- the fix is **not** made version-specific, considering that even in Python
3.8 the official bugfix only applies to Message-Id, but still fails to
protect other identification fields, like *References* and
*In-Reply-To*. The author specifically noted that shortcoming [2].
The fix wouldn't break anything on Python 3.8 anyway.
- the `noFoldPolicy` trick for preventing folding is done with no max
line length at all. RFC5322, section 2.1.1 states [3] that the maximum
length is 998 due to legacy implementations, but there is no provision
to wrap identification fields that are longer than that. Wrapping at
998 chars would corrupt the header anyway. We'll just count on the
fact that we don't usually need 1k+ chars in those headers.
The invalid folding/encoding in action on Python 3.6 (in Python 3.8 only
the second header gets folded):
```py
>>> msg = email.message.EmailMessage(policy=email.policy.SMTP)
>>> msg['Message-Id'] = '<929227342217024.1596730490.324691772460938-example-30661-some.reference@test-123.example.com>'
>>> msg['In-Reply-To'] = '<92922734221723.1596730568.324691772460444-another-30661-parent.reference@test-123.example.com>'
>>> print(msg.as_string())
Message-Id: =?utf-8?q?=3C929227342217024=2E1596730490=2E324691772460938-exam?=
=?utf-8?q?ple-30661-some=2Ereference=40test-123=2Eexample=2Ecom=3E?=
In-Reply-To: =?utf-8?q?=3C92922734221723=2E1596730568=2E324691772460444-anot?=
=?utf-8?q?her-30661-parent=2Ereference=40test-123=2Eexample=2Ecom=3E?=
```
and the expected result after the fix:
```py
>>> msg = email.message.EmailMessage(policy=email.policy.SMTP)
>>> msg['Message-Id'] = '<929227342217024.1596730490.324691772460938-example-30661-some.reference@test-123.example.com>'
>>> msg['In-Reply-To'] = '<92922734221723.1596730568.324691772460444-another-30661-parent.reference@test-123.example.com>'
>>> print(msg.as_string())
Message-Id: <929227342217024.1596730490.324691772460938-example-30661-some.reference@test-123.example.com>
In-Reply-To: <92922734221723.1596730568.324691772460444-another-30661-parent.reference@test-123.example.com>
```
[1] bpo-35805: https://bugs.python.org/issue35805
[2] python/cpython#13397 (comment)
[3] https://tools.ietf.org/html/rfc5322#section-2.1.1
X-original-commit: 02b78771 parent 1af543a commit ffd4359
2 files changed
+30
-11
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
33 | 33 | | |
34 | 34 | | |
35 | 35 | | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
36 | 51 | | |
37 | 52 | | |
38 | 53 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
450 | 450 | | |
451 | 451 | | |
452 | 452 | | |
453 | | - | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
454 | 462 | | |
455 | 463 | | |
456 | 464 | | |
457 | 465 | | |
458 | 466 | | |
459 | 467 | | |
| 468 | + | |
460 | 469 | | |
461 | 470 | | |
462 | 471 | | |
463 | | - | |
464 | | - | |
465 | | - | |
466 | | - | |
467 | | - | |
468 | 472 | | |
469 | 473 | | |
| 474 | + | |
470 | 475 | | |
471 | 476 | | |
472 | 477 | | |
473 | 478 | | |
474 | | - | |
475 | | - | |
476 | | - | |
477 | | - | |
478 | | - | |
479 | 479 | | |
480 | 480 | | |
481 | 481 | | |
482 | 482 | | |
483 | 483 | | |
484 | 484 | | |
| 485 | + | |
| 486 | + | |
| 487 | + | |
| 488 | + | |
485 | 489 | | |
486 | 490 | | |
487 | 491 | | |
| |||
0 commit comments