From 10f25158bfeb450ed7e03d57e43128f46a06caae Mon Sep 17 00:00:00 2001 From: revsuine Date: Thu, 14 Nov 2024 19:05:21 +0000 Subject: [PATCH 1/3] try to decode w/o boundary --- gpgmymail | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/gpgmymail b/gpgmymail index 41f6813..d5e3033 100755 --- a/gpgmymail +++ b/gpgmymail @@ -36,6 +36,7 @@ import email.mime.message import typing # for decode_email: import quopri +import base64 # see: https://gnupg.readthedocs.io/en/latest/ import gnupg @@ -60,7 +61,8 @@ def decode_email(message: email.message.Message) -> email.message.Message: # this is a kinda hacky way to do this by manipulating the message as a # string but i couldn't get it to work any other way # decoding needed: - decoded_bytes = message.as_bytes() + # as_string() gives us str, encode() gives us bytes + decoded_bytes = message.as_string().encode() decoded_bytes = quopri.decodestring(decoded_bytes) # replace any instances of the Content-Transfer-Encoding header @@ -78,15 +80,20 @@ def decode_email(message: email.message.Message) -> email.message.Message: # lol quopri_decoded_message = email.message_from_bytes(decoded_bytes) if quopri_decoded_message.is_multipart(): + most_recent_boundary = None for part in quopri_decoded_message.walk(): - if not part.is_multipart(): + # multipart and has boundary (not None) + if part.is_multipart() and part.get_boundary(): + most_recent_boundary = part.get_boundary() + else: if part.get("Content-Transfer-Encoding") == "base64": - new_part = part - new_part.replace_header("Content-Transfer-Encoding", "7bit") - new_part.set_payload(part.get_payload(decode=True)) + b64_str = part.get_payload() + # remove the boundary as we don't want to change this + b64_str = b64_str.replace(most_recent_boundary, "") + decoded_b64_str = base64.b64decode(b64_str) decoded_bytes = decoded_bytes.replace( - part.as_bytes(), - new_part.as_bytes() + b64_str, + decoded_b64_str ) else: # TODO From f559fef2ed11e69f766e928bbc3a927135ea5eed Mon Sep 17 00:00:00 2001 From: revsuine Date: Thu, 14 Nov 2024 19:15:37 +0000 Subject: [PATCH 2/3] strip trailing hyphens from base64 --- gpgmymail | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/gpgmymail b/gpgmymail index d5e3033..4329858 100755 --- a/gpgmymail +++ b/gpgmymail @@ -36,7 +36,6 @@ import email.mime.message import typing # for decode_email: import quopri -import base64 # see: https://gnupg.readthedocs.io/en/latest/ import gnupg @@ -90,7 +89,13 @@ def decode_email(message: email.message.Message) -> email.message.Message: b64_str = part.get_payload() # remove the boundary as we don't want to change this b64_str = b64_str.replace(most_recent_boundary, "") - decoded_b64_str = base64.b64decode(b64_str) + # sometimes we have leftover hyphens from a boundary, so strip: + # hyphens not in base64 so we know not to use them + # strip whitespace first + b64_str = b64_str.strip() + b64_str = b64_str.strip('-') + b64_str = b64_str.encode() # turn into bytes-like object + decoded_b64_str = part.get_payload(decode=True) decoded_bytes = decoded_bytes.replace( b64_str, decoded_b64_str From f1a07cb1e0af372b11ebc5d756aa3a22a1e1ddac Mon Sep 17 00:00:00 2001 From: revsuine Date: Thu, 14 Nov 2024 19:23:51 +0000 Subject: [PATCH 3/3] use message_from_string instead of message_from_bytes cause message_from_bytes bizarrely changes it back to base64 --- gpgmymail | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/gpgmymail b/gpgmymail index 4329858..e7c6073 100755 --- a/gpgmymail +++ b/gpgmymail @@ -61,7 +61,7 @@ def decode_email(message: email.message.Message) -> email.message.Message: # string but i couldn't get it to work any other way # decoding needed: # as_string() gives us str, encode() gives us bytes - decoded_bytes = message.as_string().encode() + decoded_bytes = message.as_bytes() decoded_bytes = quopri.decodestring(decoded_bytes) # replace any instances of the Content-Transfer-Encoding header @@ -108,8 +108,10 @@ def decode_email(message: email.message.Message) -> email.message.Message: b'Content-Transfer-Encoding: base64', b'Content-Transfer-Encoding: 7bit' ) - - return email.message_from_bytes(decoded_bytes) + + # if i do message_from_bytes it bizarrely changes it back to base64? + # utf-8 has encoding issues so do latin1 + return email.message_from_string(decoded_bytes.decode("latin1")) def encrypt( message: email.message.Message,