improve conditions handling

This commit is contained in:
2021-09-14 01:36:32 +02:00
parent ef025d758c
commit e34e85af6b
4 changed files with 70 additions and 77 deletions

View File

@@ -199,6 +199,33 @@ class ModifyMilter(Milter.Base):
self.logger.debug( self.logger.debug(
f"accepted milter connection from {self.IP} " f"accepted milter connection from {self.IP} "
f"port {self.port}") f"port {self.port}")
# pre-filter rules and actions by the host condition
# also check if the mail body is needed by any upcoming action.
self.rules = []
self._headersonly = True
for rule in ModifyMilter._rules:
if rule.conditions is None or \
rule.conditions.match_host(self.IP):
actions = []
for action in rule.actions:
if action.conditions is None or \
action.conditions.match_host(self.IP):
actions.append(action)
if not action.headersonly():
self._headersonly = False
if actions:
# copy needed rules to preserve configured actions
rule = copy(rule)
rule.actions = actions
self.rules.append(rule)
if not self.rules:
self.logger.debug(
"host is ignored by all rules, skip further processing")
return Milter.ACCEPT
except Exception as e: except Exception as e:
self.logger.exception( self.logger.exception(
f"an exception occured in connect method: {e}") f"an exception occured in connect method: {e}")
@@ -244,37 +271,6 @@ class ModifyMilter(Milter.Base):
self.logger = CustomLogger( self.logger = CustomLogger(
self.logger, {"qid": self.qid, "name": "milter"}) self.logger, {"qid": self.qid, "name": "milter"})
self.logger.debug("received queue-id from MTA") self.logger.debug("received queue-id from MTA")
# pre-filter rules and actions by the host condition, other
# conditions (headers, envelope-from, envelope-to) may get
# changed by executed actions later on.
# also check if the mail body is needed by any upcoming action.
self.rules = []
self._headersonly = True
for rule in ModifyMilter._rules:
if rule.conditions is None or \
rule.conditions.match(host=self.IP, qid=self.qid):
actions = []
for action in rule.actions:
if action.conditions is None or \
action.conditions.match(host=self.IP,
qid=self.qid):
actions.append(action)
if not action.headersonly():
self._headersonly = False
if actions:
# copy needed rules to preserve configured actions
rule = copy(rule)
rule.actions = actions
self.rules.append(rule)
if not self.rules:
self.logger.debug(
"message is ignored by all rules, skip further processing")
return Milter.ACCEPT
self.fp = BytesIO() self.fp = BytesIO()
except Exception as e: except Exception as e:
self.logger.exception( self.logger.exception(
@@ -341,7 +337,7 @@ class ModifyMilter(Milter.Base):
refold_source='none')) refold_source='none'))
self.msginfo = { self.msginfo = {
"mailfrom": self.mailfrom, "mailfrom": self.mailfrom,
"rcpts": self.rcpts, "rcpts": [*self.rcpts],
"vars": {}} "vars": {}}
self._replacebody = False self._replacebody = False

View File

@@ -194,9 +194,6 @@ class Action:
logger = CustomLogger( logger = CustomLogger(
self.logger, {"qid": milter.qid, "name": self._name}) self.logger, {"qid": milter.qid, "name": self._name})
if self.conditions is None or \ if self.conditions is None or \
self.conditions.match(envfrom=milter.mailfrom, self.conditions.match(milter):
envto=[*milter.rcpts],
headers=milter.msg.items(),
qid=milter.qid):
return self._class.execute( return self._class.execute(
milter=milter, pretend=self.pretend, logger=logger) milter=milter, pretend=self.pretend, logger=logger)

View File

@@ -81,15 +81,10 @@ class Conditions:
self._args = cfg["args"] self._args = cfg["args"]
self.logger = cfg.logger self.logger = cfg.logger
def match(self, host=None, envfrom=None, envto=None, headers=None, def match_host(self, host):
qid=None):
if qid is None:
logger = self.logger
else:
logger = CustomLogger( logger = CustomLogger(
self.logger, {"qid": qid, "name": self._name}) self.logger, {"name": self._name})
if host:
ip = IPAddress(host) ip = IPAddress(host)
if "local" in self._args: if "local" in self._args:
@@ -124,6 +119,13 @@ class Conditions:
logger.debug( logger.debug(
f"condition hosts matches for host {host}") f"condition hosts matches for host {host}")
return True
def match(self, milter):
logger = CustomLogger(
self.logger, {"qid": milter.qid, "name": self._name})
envfrom = milter.msginfo["mailfrom"]
if envfrom and "envfrom" in self._args: if envfrom and "envfrom" in self._args:
if not self._args["envfrom"].match(envfrom): if not self._args["envfrom"].match(envfrom):
logger.debug( logger.debug(
@@ -135,6 +137,7 @@ class Conditions:
f"condition envfrom matches for " f"condition envfrom matches for "
f"envelope-from address {envfrom}") f"envelope-from address {envfrom}")
envto = milter.msginfo["rcpts"]
if envto and "envto" in self._args: if envto and "envto" in self._args:
if not isinstance(envto, list): if not isinstance(envto, list):
envto = [envto] envto = [envto]
@@ -150,9 +153,9 @@ class Conditions:
f"condition envto matches for " f"condition envto matches for "
f"envelope-to address {envto}") f"envelope-to address {envto}")
if headers and "header" in self._args: if "header" in self._args:
match = None match = None
for field, value in headers: for field, value in milter.msg.items():
header = f"{field}: {value}" header = f"{field}: {value}"
match = self._args["header"].search(header) match = self._args["header"].search(header)
if match: if match:

View File

@@ -86,10 +86,7 @@ class Rule:
def execute(self, milter): def execute(self, milter):
"""Execute all actions of this rule.""" """Execute all actions of this rule."""
if self.conditions is None or \ if self.conditions is None or \
self.conditions.match(envfrom=milter.mailfrom, self.conditions.match(milter):
envto=[*milter.rcpts],
headers=milter.msg.items(),
qid=milter.qid):
for action in self.actions: for action in self.actions:
milter_action = action.execute(milter) milter_action = action.execute(milter)
if milter_action is not None: if milter_action is not None: