fix encoding issues

This commit is contained in:
2021-09-06 22:34:00 +02:00
parent d20e868452
commit e27b5a77f6
3 changed files with 65 additions and 6 deletions

View File

@@ -34,7 +34,7 @@ from Milter.utils import parse_addr
from collections import defaultdict from collections import defaultdict
from email import message_from_binary_file from email import message_from_binary_file
from email.header import Header from email.header import Header
from email.policy import default as default_policy, SMTP from email.policy import SMTPUTF8
from io import BytesIO from io import BytesIO
from netaddr import IPNetwork, AddrFormatError from netaddr import IPNetwork, AddrFormatError
@@ -297,7 +297,7 @@ class ModifyMilter(Milter.Base):
try: try:
self.fp.seek(0) self.fp.seek(0)
self.msg = message_from_binary_file( self.msg = message_from_binary_file(
self.fp, _class=MilterMessage, policy=default_policy) self.fp, _class=MilterMessage, policy=SMTPUTF8)
self.msg_info = defaultdict(str) self.msg_info = defaultdict(str)
self.msg_info["ip"] = self.IP self.msg_info["ip"] = self.IP
@@ -316,7 +316,7 @@ class ModifyMilter(Milter.Base):
break break
if self._replacebody: if self._replacebody:
data = self.msg.as_bytes(policy=SMTP) data = self.msg.as_bytes()
body_pos = data.find(b"\r\n\r\n") + 4 body_pos = data.find(b"\r\n\r\n") + 4
self.logger.debug("milter: replacebody") self.logger.debug("milter: replacebody")
super().replacebody(data[body_pos:]) super().replacebody(data[body_pos:])

View File

@@ -90,6 +90,66 @@ setattr(email._header_value_parser, "DisplayName", DisplayName)
setattr(email._header_value_parser, "get_name_addr", get_name_addr) setattr(email._header_value_parser, "get_name_addr", get_name_addr)
# https://bugs.python.org/issue42484
#
# fix: https://github.com/python/cpython/pull/24669
from email._header_value_parser import DOT, ObsLocalPart, ValueTerminal, get_word
def get_obs_local_part(value):
""" obs-local-part = word *("." word)
"""
obs_local_part = ObsLocalPart()
last_non_ws_was_dot = False
while value and (value[0]=='\\' or value[0] not in PHRASE_ENDS):
if value[0] == '.':
if last_non_ws_was_dot:
obs_local_part.defects.append(errors.InvalidHeaderDefect(
"invalid repeated '.'"))
obs_local_part.append(DOT)
last_non_ws_was_dot = True
value = value[1:]
continue
elif value[0]=='\\':
obs_local_part.append(ValueTerminal(value[0],
'misplaced-special'))
value = value[1:]
obs_local_part.defects.append(errors.InvalidHeaderDefect(
"'\\' character outside of quoted-string/ccontent"))
last_non_ws_was_dot = False
continue
if obs_local_part and obs_local_part[-1].token_type != 'dot':
obs_local_part.defects.append(errors.InvalidHeaderDefect(
"missing '.' between words"))
try:
token, value = get_word(value)
last_non_ws_was_dot = False
except errors.HeaderParseError:
if value[0] not in CFWS_LEADER:
raise
token, value = get_cfws(value)
obs_local_part.append(token)
if not obs_local_part:
return obs_local_part, value
if (obs_local_part[0].token_type == 'dot' or
obs_local_part[0].token_type=='cfws' and
obs_local_part[1].token_type=='dot'):
obs_local_part.defects.append(errors.InvalidHeaderDefect(
"Invalid leading '.' in local part"))
if (obs_local_part[-1].token_type == 'dot' or
obs_local_part[-1].token_type=='cfws' and
obs_local_part[-2].token_type=='dot'):
obs_local_part.defects.append(errors.InvalidHeaderDefect(
"Invalid trailing '.' in local part"))
if obs_local_part.defects:
obs_local_part.token_type = 'invalid-obs-local-part'
return obs_local_part, value
setattr(email._header_value_parser, "get_obs_local_part", get_obs_local_part)
# https://bugs.python.org/issue30681 # https://bugs.python.org/issue30681
# #
# fix: https://github.com/python/cpython/pull/22090 # fix: https://github.com/python/cpython/pull/22090

View File

@@ -32,7 +32,6 @@ from collections import defaultdict
from copy import copy from copy import copy
from datetime import datetime from datetime import datetime
from email.message import MIMEPart from email.message import MIMEPart
from email.policy import SMTP
from pymodmilter import CustomLogger, BaseConfig from pymodmilter import CustomLogger, BaseConfig
from pymodmilter.conditions import ConditionsConfig, Conditions from pymodmilter.conditions import ConditionsConfig, Conditions
@@ -205,7 +204,7 @@ def _patch_message_body(milter, action, text_template, html_template, logger):
def _wrap_message(milter, logger): def _wrap_message(milter, logger):
attachment = MIMEPart() attachment = MIMEPart()
attachment.set_content(milter.msg.as_bytes(policy=SMTP), attachment.set_content(milter.msg.as_bytes(),
maintype="plain", subtype="text", maintype="plain", subtype="text",
disposition="attachment", disposition="attachment",
filename=f"{milter.qid}.eml", filename=f"{milter.qid}.eml",
@@ -331,7 +330,7 @@ def store(milter, directory, original=False, pretend=False,
milter.fp.seek(0) milter.fp.seek(0)
fp.write(milter.fp.read()) fp.write(milter.fp.read())
else: else:
fp.write(milter.msg.as_bytes(policy=SMTP)) fp.write(milter.msg.as_bytes())
except IOError as e: except IOError as e:
raise RuntimeError(f"unable to store message: {e}") raise RuntimeError(f"unable to store message: {e}")