Skip to content

email.generator.Generator ignores policy when using multipart/signed → ruins signing#99533

@e3rd

Description

@e3rd

Bug report

EmailMessage behaves differently when being set to multipart/signed mimetype.

fromemail.messageimportEmailMessageinner=EmailMessage() inner.add_attachment("some data", "text/plain", filename="*"*35) outer1=EmailMessage() outer1.set_type("multipart/signed") # affected by generator.py/_handle_multipart_signedouter1.attach(inner) outer2=EmailMessage() outer2.set_type("multipart/signeX") # not affected by generator.py/_handle_multipart_signedouter2.attach(inner) # When accessing given submessage, nothing weird happensouter1.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` messageinner.as_string() inouter1.as_string() # !False!inner.as_string() inouter2.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.policyself.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:

fromemailimportpolicypol=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

Metadata

Metadata

Assignees

No one assigned

    Labels

    stdlibStandard Library Python modules in the Lib/ directorytopic-emailtype-bugAn unexpected behavior, bug, or error

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions