change header handling in add_disclaimer and store
This commit is contained in:
@@ -220,8 +220,8 @@ class ModifyMilter(Milter.Base):
|
|||||||
|
|
||||||
if not self.rules:
|
if not self.rules:
|
||||||
self.logger.debug(
|
self.logger.debug(
|
||||||
f"envelope-to addresses are ignored by all rules, "
|
"envelope-to addresses are ignored by all rules, "
|
||||||
f"skip further processing")
|
"skip further processing")
|
||||||
return Milter.ACCEPT
|
return Milter.ACCEPT
|
||||||
|
|
||||||
self.qid = self.getsymval('i')
|
self.qid = self.getsymval('i')
|
||||||
@@ -229,7 +229,7 @@ class ModifyMilter(Milter.Base):
|
|||||||
self.logger.debug("received queue-id from MTA")
|
self.logger.debug("received queue-id from MTA")
|
||||||
|
|
||||||
self.fields = None
|
self.fields = None
|
||||||
self.fields_data = None
|
self.fields_bytes = None
|
||||||
self.body_data = None
|
self.body_data = None
|
||||||
needs = []
|
needs = []
|
||||||
for rule in self.rules:
|
for rule in self.rules:
|
||||||
@@ -238,8 +238,8 @@ class ModifyMilter(Milter.Base):
|
|||||||
if "fields" in needs:
|
if "fields" in needs:
|
||||||
self.fields = []
|
self.fields = []
|
||||||
|
|
||||||
if "original_fields" in needs:
|
if "fields_bytes" in needs:
|
||||||
self.fields_data = BytesIO()
|
self.fields_bytes = []
|
||||||
|
|
||||||
if "body" in needs:
|
if "body" in needs:
|
||||||
self.body_data = BytesIO()
|
self.body_data = BytesIO()
|
||||||
@@ -253,13 +253,10 @@ class ModifyMilter(Milter.Base):
|
|||||||
|
|
||||||
def header(self, name, value):
|
def header(self, name, value):
|
||||||
try:
|
try:
|
||||||
if self.fields_data != None:
|
if self.fields_data is not None:
|
||||||
self.fields_data.write(
|
self.fields_bytes.append(
|
||||||
name.encode("ascii", errors="surrogateescape"))
|
(name.encode("ascii", errors="surrogateescape"),
|
||||||
self.fields_data.write(b": ")
|
value.encode("ascii", errors="surrogateescape")))
|
||||||
self.fields_data.write(
|
|
||||||
value.encode("ascii", errors="surrogateescape"))
|
|
||||||
self.fields_data.write(b"\r\n")
|
|
||||||
|
|
||||||
if self.fields is not None:
|
if self.fields is not None:
|
||||||
# remove surrogates from value
|
# remove surrogates from value
|
||||||
|
|||||||
@@ -87,8 +87,8 @@ def mod_header(field, value, milter, search=None, pretend=False,
|
|||||||
|
|
||||||
if not new_v:
|
if not new_v:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
f"mod_header: resulting value is empty, "
|
"mod_header: resulting value is empty, "
|
||||||
f"skip modification")
|
"skip modification")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
header = f"{f}: {v}"
|
header = f"{f}: {v}"
|
||||||
@@ -279,19 +279,15 @@ def add_disclaimer(text, html, action, policy, milter, pretend=False,
|
|||||||
milter.body_data.seek(0)
|
milter.body_data.seek(0)
|
||||||
fp = BytesFeedParser(policy=default_policy)
|
fp = BytesFeedParser(policy=default_policy)
|
||||||
|
|
||||||
for field, value in milter.fields:
|
for field, value in milter.fields_bytes:
|
||||||
field_lower = field.lower()
|
field_lower = field.encode("ascii").lower()
|
||||||
if not field_lower.startswith("content-") and \
|
if not field_lower.startswith("content-") and \
|
||||||
field_lower != "mime-version":
|
field_lower != "mime-version":
|
||||||
continue
|
continue
|
||||||
logger.debug(
|
logger.debug(
|
||||||
f"feed content header to message object: {field}: {value}")
|
f"feed content header to message object: "
|
||||||
encoded_value = _replace_illegal_chars(
|
f"{field.encode()}: {value.encode()}")
|
||||||
Header(s=value).encode())
|
fp.feed(field + b": " + value + b"\r\n")
|
||||||
fp.feed(field.encode("ascii", errors="replace"))
|
|
||||||
fp.feed(b": ")
|
|
||||||
fp.feed(encoded_value.encode("ascii", errors="replace"))
|
|
||||||
fp.feed(b"\r\n")
|
|
||||||
|
|
||||||
fp.feed(b"\r\n")
|
fp.feed(b"\r\n")
|
||||||
logger.debug(f"feed body to message object: {field}: {value}")
|
logger.debug(f"feed body to message object: {field}: {value}")
|
||||||
@@ -318,13 +314,13 @@ def add_disclaimer(text, html, action, policy, milter, pretend=False,
|
|||||||
logger.warning(e)
|
logger.warning(e)
|
||||||
if policy == "ignore":
|
if policy == "ignore":
|
||||||
logger.info(
|
logger.info(
|
||||||
f"unable to add disclaimer to message body, "
|
"unable to add disclaimer to message body, "
|
||||||
f"ignore error according to policy")
|
"ignore error according to policy")
|
||||||
return
|
return
|
||||||
elif policy == "reject":
|
elif policy == "reject":
|
||||||
logger.info(
|
logger.info(
|
||||||
f"unable to add disclaimer to message body, "
|
"unable to add disclaimer to message body, "
|
||||||
f"reject message according to policy")
|
"reject message according to policy")
|
||||||
return [
|
return [
|
||||||
("reject", "Message rejected due to error")]
|
("reject", "Message rejected due to error")]
|
||||||
|
|
||||||
@@ -391,13 +387,13 @@ def store(directory, milter, pretend=False,
|
|||||||
timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
|
timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
|
||||||
store_id = f"{timestamp}_{milter.qid}"
|
store_id = f"{timestamp}_{milter.qid}"
|
||||||
datafile = os.path.join(directory, store_id)
|
datafile = os.path.join(directory, store_id)
|
||||||
milter.fields_data.seek(0)
|
|
||||||
milter.body_data.seek(0)
|
milter.body_data.seek(0)
|
||||||
logger.info(f"store message in file {datafile}")
|
logger.info(f"store message in file {datafile}")
|
||||||
try:
|
try:
|
||||||
with open(datafile, "wb") as fp:
|
with open(datafile, "wb") as fp:
|
||||||
copyfileobj(milter.fields_data, fp)
|
for field, value in milter.fields_bytes:
|
||||||
fp.write(b"\r\n")
|
fp.write(field + b": " + value + b"\r\n")
|
||||||
|
|
||||||
copyfileobj(milter.body_data, fp)
|
copyfileobj(milter.body_data, fp)
|
||||||
except IOError as e:
|
except IOError as e:
|
||||||
raise RuntimeError(f"unable to store message: {e}")
|
raise RuntimeError(f"unable to store message: {e}")
|
||||||
@@ -410,7 +406,7 @@ class Action:
|
|||||||
"del_header": ["fields"],
|
"del_header": ["fields"],
|
||||||
"mod_header": ["fields"],
|
"mod_header": ["fields"],
|
||||||
"add_disclaimer": ["fields", "body"],
|
"add_disclaimer": ["fields", "body"],
|
||||||
"store": ["original_fields", "body"]}
|
"store": ["fields_bytes", "body"]}
|
||||||
|
|
||||||
def __init__(self, name, local_addrs, conditions, action_type, args,
|
def __init__(self, name, local_addrs, conditions, action_type, args,
|
||||||
loglevel=logging.INFO, pretend=False):
|
loglevel=logging.INFO, pretend=False):
|
||||||
@@ -489,7 +485,7 @@ class Action:
|
|||||||
self._func = store
|
self._func = store
|
||||||
if args["storage_type"] not in ["file"]:
|
if args["storage_type"] not in ["file"]:
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
f"invalid storage_type 'args['storage_type']'")
|
"invalid storage_type 'args['storage_type']'")
|
||||||
|
|
||||||
if args["storage_type"] == "file":
|
if args["storage_type"] == "file":
|
||||||
self._args["directory"] = args["directory"]
|
self._args["directory"] = args["directory"]
|
||||||
|
|||||||
@@ -125,8 +125,8 @@ def main():
|
|||||||
socket = config["global"]["socket"]
|
socket = config["global"]["socket"]
|
||||||
else:
|
else:
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
f"listening socket is neither specified on the command line "
|
"listening socket is neither specified on the command line "
|
||||||
f"nor in the configuration file")
|
"nor in the configuration file")
|
||||||
|
|
||||||
if "local_addrs" in config["global"]:
|
if "local_addrs" in config["global"]:
|
||||||
local_addrs = config["global"]["local_addrs"]
|
local_addrs = config["global"]["local_addrs"]
|
||||||
@@ -140,7 +140,7 @@ def main():
|
|||||||
|
|
||||||
if "rules" not in config:
|
if "rules" not in config:
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
f"mandatory config section 'rules' not found")
|
"mandatory config section 'rules' not found")
|
||||||
|
|
||||||
if not config["rules"]:
|
if not config["rules"]:
|
||||||
raise RuntimeError("no rules configured")
|
raise RuntimeError("no rules configured")
|
||||||
|
|||||||
Reference in New Issue
Block a user