2023-02-21 15:28:06 +01:00
|
|
|
import re
|
2022-04-28 14:43:24 +02:00
|
|
|
from email import policy
|
|
|
|
from email.message import Message
|
|
|
|
|
2023-02-21 15:28:06 +01:00
|
|
|
from app.email import headers
|
2022-04-28 14:43:24 +02:00
|
|
|
from app.log import LOG
|
|
|
|
|
2023-02-21 15:28:06 +01:00
|
|
|
# Spam assassin might flag as spam with a different line length
|
|
|
|
BASE64_LINELENGTH = 76
|
|
|
|
|
2022-04-28 14:43:24 +02:00
|
|
|
|
|
|
|
def message_to_bytes(msg: Message) -> bytes:
|
|
|
|
"""replace Message.as_bytes() method by trying different policies"""
|
|
|
|
for generator_policy in [None, policy.SMTP, policy.SMTPUTF8]:
|
|
|
|
try:
|
|
|
|
return msg.as_bytes(policy=generator_policy)
|
2023-02-21 15:28:06 +01:00
|
|
|
except Exception:
|
2022-04-28 14:43:24 +02:00
|
|
|
LOG.w("as_bytes() fails with %s policy", policy, exc_info=True)
|
|
|
|
|
|
|
|
msg_string = msg.as_string()
|
|
|
|
try:
|
|
|
|
return msg_string.encode()
|
2023-02-21 15:28:06 +01:00
|
|
|
except Exception:
|
2022-04-28 14:43:24 +02:00
|
|
|
LOG.w("as_string().encode() fails", exc_info=True)
|
|
|
|
|
|
|
|
return msg_string.encode(errors="replace")
|
2023-02-21 15:28:06 +01:00
|
|
|
|
|
|
|
|
|
|
|
def message_format_base64_parts(msg: Message) -> Message:
|
|
|
|
for part in msg.walk():
|
|
|
|
if part.get(
|
|
|
|
headers.CONTENT_TRANSFER_ENCODING
|
|
|
|
) == "base64" and part.get_content_type() in ("text/plain", "text/html"):
|
|
|
|
# Remove line breaks
|
|
|
|
body = re.sub("[\r\n]", "", part.get_payload())
|
|
|
|
# Split in 80 column lines
|
|
|
|
chunks = [
|
|
|
|
body[i : i + BASE64_LINELENGTH]
|
|
|
|
for i in range(0, len(body), BASE64_LINELENGTH)
|
|
|
|
]
|
|
|
|
part.set_payload("\r\n".join(chunks))
|
|
|
|
return msg
|