improve conditions handling
This commit is contained in:
@@ -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
|
||||||
@@ -356,7 +352,7 @@ class ModifyMilter(Milter.Base):
|
|||||||
if self._replacebody:
|
if self._replacebody:
|
||||||
data = self.msg.as_bytes()
|
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("replacebody")
|
self.logger.debug("replace body")
|
||||||
super().replacebody(data[body_pos:])
|
super().replacebody(data[body_pos:])
|
||||||
del data
|
del data
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -81,49 +81,51 @@ 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):
|
logger = CustomLogger(
|
||||||
if qid is None:
|
self.logger, {"name": self._name})
|
||||||
logger = self.logger
|
|
||||||
else:
|
|
||||||
logger = CustomLogger(
|
|
||||||
self.logger, {"qid": qid, "name": self._name})
|
|
||||||
|
|
||||||
if host:
|
ip = IPAddress(host)
|
||||||
ip = IPAddress(host)
|
|
||||||
|
|
||||||
if "local" in self._args:
|
if "local" in self._args:
|
||||||
is_local = False
|
is_local = False
|
||||||
for addr in self._local_addrs:
|
for addr in self._local_addrs:
|
||||||
if ip in addr:
|
if ip in addr:
|
||||||
is_local = True
|
is_local = True
|
||||||
break
|
break
|
||||||
|
|
||||||
if is_local != self._args["local"]:
|
|
||||||
logger.debug(
|
|
||||||
f"ignore host {host}, "
|
|
||||||
f"condition local does not match")
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
if is_local != self._args["local"]:
|
||||||
logger.debug(
|
logger.debug(
|
||||||
f"condition local matches for host {host}")
|
f"ignore host {host}, "
|
||||||
|
f"condition local does not match")
|
||||||
|
return False
|
||||||
|
|
||||||
if "hosts" in self._args:
|
logger.debug(
|
||||||
found = False
|
f"condition local matches for host {host}")
|
||||||
for addr in self._args["hosts"]:
|
|
||||||
if ip in addr:
|
|
||||||
found = True
|
|
||||||
break
|
|
||||||
|
|
||||||
if not found:
|
if "hosts" in self._args:
|
||||||
logger.debug(
|
found = False
|
||||||
f"ignore host {host}, "
|
for addr in self._args["hosts"]:
|
||||||
f"condition hosts does not match")
|
if ip in addr:
|
||||||
return False
|
found = True
|
||||||
|
break
|
||||||
|
|
||||||
|
if not found:
|
||||||
logger.debug(
|
logger.debug(
|
||||||
f"condition hosts matches for host {host}")
|
f"ignore host {host}, "
|
||||||
|
f"condition hosts does not match")
|
||||||
|
return False
|
||||||
|
|
||||||
|
logger.debug(
|
||||||
|
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:
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
Reference in New Issue
Block a user