email.generator.Generator ignores policy when using `multipart/signed` → ruins signing
Chưa có ai nhận issue này.
- 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
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- 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.
- Fork repository và làm thay đổi trên một nhánh.
- 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