python / python/cpython

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

Ouverte
#99,533 0 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

stdlib topic-email type-bug
Langage dominant
Python
Étoiles
77.2k
Forks
36k
Métriques de merge des PR
Métriques de PR en attente

Description

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

Guide de contribution

Ouvrir le guide de contribution

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Piste de recherche

Commencez par Lib/email/generator.py à _handle_multipart_signed et reproduisez le problème en utilisant l’exemple EmailMessage avec multipart/signed et un nom de fichier long. Vérifiez le travail associé dans gh-100204 ainsi que les tests pertinents du paquet email ; le travail est terminé lorsque la partie signée conserve la policy prévue et la sérialisation des en-têtes sans perturber le comportement multipart existant.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
python
Domaine
backend
Type d'issue
Bug
Difficulté
4/5
Temps estimé
3-5 jours
Activité
À l'abandon
Clarté
Clairement spécifiée
Accessibilité débutants
25/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.