From 638f622f243e40db8938debec0773f75b00ec525 Mon Sep 17 00:00:00 2001 From: revsuine Date: Sat, 16 Nov 2024 15:44:27 +0000 Subject: [PATCH] don't decode base64 non-text parts --- gpgmymail | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/gpgmymail b/gpgmymail index 8622548..92fded4 100755 --- a/gpgmymail +++ b/gpgmymail @@ -87,7 +87,7 @@ def decode_email(message: email.message.Message) -> email.message.Message: decoded_bytes = message.as_string().encode() # if email doesn't need decoding has_quopri = b'Content-Transfer-Encoding: quoted-printable' in decoded_bytes - has_base64 = b'Content-Transfer-Encoding: base64' in decoded_bytes + has_base64 = is_base64_text(message) # we don't want to decode non-text if not (has_quopri or has_base64): return message decoded_bytes = quopri.decodestring(decoded_bytes) @@ -117,7 +117,7 @@ def decode_email(message: email.message.Message) -> email.message.Message: ) -> bytes: """ change decoded_bytes such that part is decoded if base64 (unchanged if - not) + not) and text (so will not decode base64 images etc) see usage below for examples @@ -128,7 +128,8 @@ def decode_email(message: email.message.Message) -> email.message.Message: don't overwrite this :return: bytes of decoded_bytes with part decoded if base64 """ - if part.get("Content-Transfer-Encoding") == "base64": + if part.get("Content-Transfer-Encoding") == "base64" and \ + part.get_content_maintype() == "text": b64_str = part.get_payload() # remove the boundary as we don't want to change this if most_recent_boundary: @@ -197,6 +198,25 @@ def set_email_header( else: message.add_header(name, value) +def is_base64_text(message: email.message.Message) -> bool: + """ + Return whether or not there is base64-encoded text in a multipart + message, i.e. will be False if it's only e.g. images that are encoded as + base64. + + :param message: the email Message to check + :return: True if there is a text part that's base64 encoded, False if not + """ + if message.is_multipart(): + for part in message.walk(): + if part.get('Content-Transfer-Encoding') == "base64" and \ + part.get_content_maintype() == "text": + return True + return False + else: + return message.get('Content-Transfer-Encoding') == "base64" and \ + message.get_content_maintype() == "text" + def encrypt( message: email.message.Message, recipients: typing.List[str], @@ -236,7 +256,7 @@ def encrypt( if is_message_encrypted(message): return message.as_string() # bc i just have a bunch of issues w b64 - if "Content-Transfer-Encoding: base64" in message.as_string(): + if is_base64_text(message): return message.as_string() # make necessary changes to message