Skip to content

gh-98188: Fix EmailMessage.get_payload to decode data #127547

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jan 6, 2025
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion Lib/email/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
# Intrapackage imports
from email import utils
from email import errors
from email import headerregistry
from email._policybase import compat32
from email import charset as _charset
from email._encoded_words import decode_b
Expand Down Expand Up @@ -286,8 +287,11 @@ def get_payload(self, i=None, decode=False):
if i is not None and not isinstance(self._payload, list):
raise TypeError('Expected list, got %s' % type(self._payload))
payload = self._payload
cte = self.get('content-transfer-encoding', '')
if isinstance(cte, headerregistry.ContentTransferEncodingHeader):
cte = cte.cte
# cte might be a Header, so for now stringify it.
cte = str(self.get('content-transfer-encoding', '')).lower()
cte = str(cte).strip().lower()
# payload may be bytes here.
if not decode:
if isinstance(payload, str) and utils._has_surrogates(payload):
Expand Down
5 changes: 5 additions & 0 deletions Lib/test/test_email/test_headerregistry.py
Original file line number Diff line number Diff line change
Expand Up @@ -837,6 +837,11 @@ def cte_as_value(self,
'7bit',
[errors.InvalidHeaderDefect]),

'extra_space_after_cte': (
'base64 ',
'base64',
[]),

}


Expand Down
32 changes: 32 additions & 0 deletions Lib/test/test_email/test_message.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from email.errors import InvalidHeaderDefect
import textwrap
import unittest
from email import message_from_bytes, message_from_string, policy
Expand Down Expand Up @@ -1054,6 +1055,37 @@ def test_string_payload_with_multipart_content_type(self):
attachments = msg.iter_attachments()
self.assertEqual(list(attachments), [])

def test_string_payload_with_base64_cte(self):
msg = message_from_string(textwrap.dedent("""\
Content-Transfer-Encoding: base64

SGVsbG8uIFRlc3Rpbmc=
"""), policy=policy.default)
self.assertEqual(msg.get_payload(decode=True), b"Hello. Testing")
self.assertDefectsEqual(msg['content-transfer-encoding'].defects, [])

def test_string_payload_with_extra_space_after_cte(self):
# https://github.com/python/cpython/issues/98188
cte = "base64 "
msg = message_from_string(textwrap.dedent(f"""\
Content-Transfer-Encoding: {cte}

SGVsbG8uIFRlc3Rpbmc=
"""), policy=policy.default)
self.assertEqual(msg.get_payload(decode=True), b"Hello. Testing")
self.assertDefectsEqual(msg['content-transfer-encoding'].defects, [])

def test_string_payload_with_extra_text_after_cte(self):
msg = message_from_string(textwrap.dedent("""\
Content-Transfer-Encoding: base64 some text

SGVsbG8uIFRlc3Rpbmc=
"""), policy=policy.default)
self.assertEqual(msg.get_payload(decode=True), b"Hello. Testing")
cte = msg['content-transfer-encoding']
self.assertDefectsEqual(cte.defects, [InvalidHeaderDefect])



if __name__ == '__main__':
unittest.main()
1 change: 1 addition & 0 deletions Misc/ACKS
Original file line number Diff line number Diff line change
Expand Up @@ -1127,6 +1127,7 @@ Gregor Lingl
Everett Lipman
Mirko Liss
Alexander Liu
Hui Liu
Yuan Liu
Nick Lockwood
Stephanie Lockwood
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix an issue in :meth:`email.message.Message.get_payload` where data
cannot be decoded if there is a trailing whitespace and/or texts following the mechanism.
Loading