python / python/cpython

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

Đang mở
#99,533 0 bình luận 0 reaction 0 người được giao Xem trên GitHub

Chưa có ai nhận issue này.

stdlib topic-email type-bug
Ngôn ngữ chính
Python
Star
77.2k
Fork
36k
Merge trung bình
1 ngày 9 giờ
Pull request đã merge (30 ngày)
558

Mô tả

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

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Hướng nghiên cứu

Bắt đầu với Lib/email/generator.py tại _handle_multipart_signed và tái hiện vấn đề bằng ví dụ EmailMessage với multipart/signed và tên tệp dài. Kiểm tra công việc được liên kết trong gh-100204 và các bài kiểm thử liên quan của gói email; được xem là hoàn tất khi phần đã ký giữ nguyên policy dự kiến và việc tuần tự hóa header mà không làm hỏng hành vi multipart hiện có.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Đánh giá

Công nghệ
python
Lĩnh vực
backend
Loại issue
Lỗi
Độ khó
4/5
Thời gian dự kiến
3-5 ngày
Mức độ hoạt động
Đình trệ
Độ rõ ràng
Đặc tả rõ ràng
Mức phù hợp với người mới
25/100

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.