don't decode base64 non-text parts

This commit is contained in:
revsuine 2024-11-16 15:44:27 +00:00
parent 52405bf067
commit 638f622f24
Signed by: revsuine
GPG key ID: 3F257B68F5BC9339

View file

@ -87,7 +87,7 @@ def decode_email(message: email.message.Message) -> email.message.Message:
decoded_bytes = message.as_string().encode() decoded_bytes = message.as_string().encode()
# if email doesn't need decoding # if email doesn't need decoding
has_quopri = b'Content-Transfer-Encoding: quoted-printable' in decoded_bytes 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): if not (has_quopri or has_base64):
return message return message
decoded_bytes = quopri.decodestring(decoded_bytes) decoded_bytes = quopri.decodestring(decoded_bytes)
@ -117,7 +117,7 @@ def decode_email(message: email.message.Message) -> email.message.Message:
) -> bytes: ) -> bytes:
""" """
change decoded_bytes such that part is decoded if base64 (unchanged if 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 see usage below for examples
@ -128,7 +128,8 @@ def decode_email(message: email.message.Message) -> email.message.Message:
don't overwrite this don't overwrite this
:return: bytes of decoded_bytes with part decoded if base64 :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() b64_str = part.get_payload()
# remove the boundary as we don't want to change this # remove the boundary as we don't want to change this
if most_recent_boundary: if most_recent_boundary:
@ -197,6 +198,25 @@ def set_email_header(
else: else:
message.add_header(name, value) 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( def encrypt(
message: email.message.Message, message: email.message.Message,
recipients: typing.List[str], recipients: typing.List[str],
@ -236,7 +256,7 @@ def encrypt(
if is_message_encrypted(message): if is_message_encrypted(message):
return message.as_string() return message.as_string()
# bc i just have a bunch of issues w b64 # 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() return message.as_string()
# make necessary changes to message # make necessary changes to message