add ability to ignore sender hosts and/or networks

This commit is contained in:
2019-09-02 15:56:12 +02:00
parent 5ffae608ff
commit a7d472af68
3 changed files with 41 additions and 2 deletions

View File

@@ -49,6 +49,8 @@ The following configuration options are mandatory in each quarantine section:
SMTP port
The following configuration options are optional in each quarantine section:
* **ignore_hosts**
Comma-separated list of host and network addresses to be ignored by this quarantine.
* **reject_reason**
Reason to return to the client if action is set to reject.

View File

@@ -30,6 +30,12 @@ preferred_quarantine_action = last
[spam]
# Option: ignore_hosts
# Notes: Set a list of host and network addresses to be ignored by this quarantine.
# All the common host/network notations are supported, including IPv6.
# Value: [ HOST ]
#
ignore_hosts = 10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
# Option: regex
# Notes: Set the regular expression to match against email headers.

View File

@@ -25,7 +25,7 @@ from Milter.utils import parse_addr
from collections import defaultdict
from io import BytesIO
from itertools import groupby
from netaddr import IPAddress, IPNetwork
from pyquarantine import quarantines
from pyquarantine import notifications
from pyquarantine import whitelists
@@ -71,6 +71,20 @@ class QuarantineMilter(Milter.Base):
def set_configfiles(config_files):
QuarantineMilter._config_files = config_files
def connect(self, IPname, family, hostaddr):
self.logger.debug("accepted milter connection from {} port {}".format(*hostaddr))
ip = IPAddress(hostaddr[0])
for quarantine in self.config.copy():
for ignore in quarantine["ignore_hosts_list"]:
if ip in ignore:
self.logger.debug("host {} is ignored by quarantine {}".format(hostaddr[0], quarantine["name"]))
self.config.remove(quarantine)
break
if not self.config:
self.logger.debug("host {} is ignored by all quarantines, skip further processing", hostaddr[0])
return Milter.ACCEPT
return Milter.CONTINUE
@Milter.noreply
def envfrom(self, mailfrom, *str):
self.mailfrom = "@".join(parse_addr(mailfrom)).lower()
@@ -325,7 +339,8 @@ def generate_milter_config(configtest=False, config_files=[]):
# check if optional config options are present in config
defaults = {
"reject_reason": "Message rejected"
"reject_reason": "Message rejected",
"ignore_hosts": ""
}
for option in defaults.keys():
if option not in config.keys() and \
@@ -391,6 +406,22 @@ def generate_milter_config(configtest=False, config_files=[]):
else:
raise RuntimeError("{}: unknown action '{}'".format(quarantine_name, action))
# create host/network whitelist
config["ignore_hosts_list"] = []
ignored = set([ p.strip() for p in config["ignore_hosts"].split(",") if p])
for ignore in ignored:
if not ignore:
continue
# parse network notation
try:
net = IPNetwork(ignore)
except AddrFormatError as e:
raise RuntimeError("error parsing ignore_hosts: {}".format(e))
else:
config["ignore_hosts_list"].append(net)
if config["ignore_hosts_list"]:
logger.debug("{}: ignore hosts: {}".format(quarantine_name, ", ".join(ignored)))
milter_config.append(config)
return global_config, milter_config