Fix MIME content sub-type handling for non-plain text messages
This commit is contained in:
parent
bc92d7a31c
commit
61cf50effe
4 changed files with 33 additions and 16 deletions
|
@ -179,35 +179,42 @@ def _encrypt_all_payloads_mime(message: EmailMessage, gpg_to_cmdline):
|
|||
boundary = _make_boundary()
|
||||
|
||||
if isinstance(message.get_payload(), str):
|
||||
LOG.debug('Rewrapping a flat, text-only message')
|
||||
wrapped_payload = _rewrap_payload(message)
|
||||
encrypted_part.set_payload(wrapped_payload.as_string())
|
||||
|
||||
_set_type_and_boundary(message, boundary)
|
||||
|
||||
return [pgp_ver_part, _encrypt_payload(encrypted_part, gpg_to_cmdline, True)]
|
||||
check_nested = True
|
||||
else:
|
||||
processed_payloads = _generate_message_from_payloads(message)
|
||||
encrypted_part.set_payload(processed_payloads.as_string())
|
||||
|
||||
_set_type_and_boundary(message, boundary)
|
||||
|
||||
return [pgp_ver_part, _encrypt_payload(encrypted_part, gpg_to_cmdline, False)]
|
||||
check_nested = False
|
||||
|
||||
return [pgp_ver_part, _encrypt_payload(encrypted_part, gpg_to_cmdline, check_nested)]
|
||||
|
||||
|
||||
def _rewrap_payload(message: EmailMessage) -> MIMEPart:
|
||||
# In PGP/MIME (RFC 3156), the payload has to be a valid MIME entity. In
|
||||
# other words, we need to wrap text/plain message's payload in a new MIME
|
||||
# other words, we need to wrap text/* message's payload in a new MIME
|
||||
# entity.
|
||||
|
||||
pld = MIMEPart()
|
||||
pld.set_type(message.get_content_type())
|
||||
pld.set_content(message.get_content())
|
||||
wrapper = MIMEPart(policy=SMTPUTF8)
|
||||
content = message.get_content()
|
||||
wrapper.set_content(content)
|
||||
|
||||
# Make sure all Content-Type parameters are included.
|
||||
for (k, v) in message.get_params():
|
||||
pld.set_param(k, v)
|
||||
wrapper.set_type(message.get_content_type())
|
||||
|
||||
return pld
|
||||
# Copy all Content-Type parameters.
|
||||
for (pname, pvalue) in message.get_params():
|
||||
# Skip MIME type that's also returned by get_params().
|
||||
if not '/' in pname:
|
||||
wrapper.set_param(pname, pvalue)
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
def _make_boundary():
|
||||
|
@ -242,8 +249,6 @@ def _encrypt_payload(payload: EmailMessage, recipients, check_nested=True, **kwa
|
|||
|
||||
if isAttachment:
|
||||
_append_gpg_extension(payload)
|
||||
if not (payload.get('Content-Transfer-Encoding') is None):
|
||||
payload.replace_header('Content-Transfer-Encoding', "7bit")
|
||||
|
||||
return payload
|
||||
|
||||
|
|
|
@ -90,12 +90,10 @@ class RecipientList:
|
|||
|
||||
def emails(self):
|
||||
"""Return list of recipients."""
|
||||
LOG.debug('Recipient emails from: %s', self._recipients)
|
||||
return [r.email() for r in self._recipients]
|
||||
|
||||
def keys(self):
|
||||
"""Return list of GPG identities."""
|
||||
LOG.debug('Recipient keys from: %s', self._recipients)
|
||||
return [r.key() for r in self._recipients]
|
||||
|
||||
def __iadd__(self, recipient: GpgRecipient):
|
||||
|
@ -116,6 +114,10 @@ class RecipientList:
|
|||
"""
|
||||
return len(self._recipients)
|
||||
|
||||
def __repr__(self):
|
||||
"""Returns textual object representation."""
|
||||
return '<RecipientList %d %s>' % (len(self._recipients), ','.join(self.emails()))
|
||||
|
||||
|
||||
def identify_gpg_recipients(recipients, keys: kcache.KeyCache):
|
||||
"""Split recipient list into GPG and non-GPG ones."""
|
||||
|
|
|
@ -173,6 +173,14 @@ class EmailTest(unittest.TestCase):
|
|||
_ = mp.as_string()
|
||||
self.assertFalse(mp.get_boundary() is None)
|
||||
|
||||
def test_content_type_params_include_mime_type(self):
|
||||
p = email.message.MIMEPart()
|
||||
p.set_type('text/plain')
|
||||
p.set_param('charset', 'UTF-8')
|
||||
p.set_param('format', 'flowed')
|
||||
|
||||
self.assertIn(('text/plain', ''), p.get_params())
|
||||
|
||||
|
||||
class RawConfigParserTest(unittest.TestCase):
|
||||
def test_config_parser_returns_str(self):
|
||||
|
|
|
@ -36,5 +36,7 @@ class LacreCoreTest(unittest.TestCase):
|
|||
|
||||
rewrapped = lacre.core._rewrap_payload(m)
|
||||
|
||||
self.assertFalse('Subject' in rewrapped)
|
||||
self.assertEqual(rewrapped.get_content_type(), m.get_content_type())
|
||||
self.assertFalse('Subject' in rewrapped,
|
||||
'only content and content-type should be copied')
|
||||
self.assertEqual(rewrapped.get_content_type(), 'text/plain',
|
||||
'rewrapped part should have initial message\'s content-type')
|
||||
|
|
Loading…
Reference in a new issue