email.generator.Generator ignores policy when using `multipart/signed` → ruins signing
まだ誰も着手していません。
- 主要言語
- Python
- スター
- 77.2k
- フォーク
- 36k
- PR マージ指標
- PR 指標を取得中
説明
Bug report
EmailMessage behaves differently when being set to multipart/signed mimetype.
from email.message import EmailMessage
inner = EmailMessage()
inner.add_attachment("some data", "text/plain", filename="*"*35)
outer1 = EmailMessage()
outer1.set_type("multipart/signed") # affected by generator.py/_handle_multipart_signed
outer1.attach(inner)
outer2 = EmailMessage()
outer2.set_type("multipart/signeX") # not affected by generator.py/_handle_multipart_signed
outer2.attach(inner)
# When accessing given submessage, nothing weird happens
outer1.get_payload()[0].as_string() == outer2.get_payload()[0].as_string() # True
# However, when accessing whole message at once, headers folding change for the outer1 `multipart/signed` message
inner.as_string() in outer1.as_string() # !False!
inner.as_string() in outer2.as_string() # True
This is due to a 13 years old generator.py code that for an unknown reason rewrites the policy so that no header was folded:
def _handle_multipart_signed(self, msg):
# The contents of signed parts has to stay unmodified in order to keep
# the signature intact per RFC1847 2.1, so we disable header wrapping.
# RDM: This isn't enough to completely preserve the part, but it helps.
p = self.policy
self.policy = p.clone(max_line_length=0)
try:
self._handle_multipart(msg)
finally:
self.policy = p
As a result, when I GPG-sign the inner message and attach it to a wrapping-outer message along with the signature (which is the right thing), the signature is void because policy being ignored, the headers folding got disabled on the output. I understand the method _handle_multipart_signed should help the message signing but it ruins it instead. One dirty solution would be to set the policy to max_line_length=0 which fails for whatever reason:
from email import policy
pol = policy.default.clone(max_line_length=0)
inner = EmailMessage(policy=pol)
inner.add_attachment("some data", "text/plain", filename="*"*35) # ValueError: maxlinelen must be at least 4
Therefore, I am not able to sign the inner message with the headers fold (as it is output unfold), not I am able to sign the inner message with the headers unfold (as ValueError prevents me to set the policy to not stop folding headers).
So my proposal is to remove _handle_multipart_signed altogether (which would be sufficient) or to find a use-case where it does make sense (I could not find any).
Your environment
- CPython versions tested on: Python 3.10.6
- Operating system and architecture: Ubuntu 22.04.1 LTS x86_64
Linked PRs
- gh-100204
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
調査の方向性
Lib/email/generator.py の _handle_multipart_signed から始め、multipart/signed と長いファイル名を使用した EmailMessage の例で問題を再現します。gh-100204 にリンクされた作業と、email パッケージの関連テストを確認します。完了の条件は、既存の multipart の動作を壊すことなく、署名付きパートが意図した policy とヘッダーのシリアライズを保持することです。
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- python
- 領域
- backend
- issue の種類
- バグ
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 活発さ
- 停滞
- 明瞭さ
- 明確に書かれている
- 初心者へのやさしさ
- 25/100