add ability to ignore sender hosts and/or networks
This commit is contained in:
@@ -49,6 +49,8 @@ The following configuration options are mandatory in each quarantine section:
|
|||||||
SMTP port
|
SMTP port
|
||||||
|
|
||||||
The following configuration options are optional in each quarantine section:
|
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**
|
* **reject_reason**
|
||||||
Reason to return to the client if action is set to reject.
|
Reason to return to the client if action is set to reject.
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,12 @@ preferred_quarantine_action = last
|
|||||||
|
|
||||||
|
|
||||||
[spam]
|
[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
|
# Option: regex
|
||||||
# Notes: Set the regular expression to match against email headers.
|
# Notes: Set the regular expression to match against email headers.
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ from Milter.utils import parse_addr
|
|||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from itertools import groupby
|
from itertools import groupby
|
||||||
|
from netaddr import IPAddress, IPNetwork
|
||||||
from pyquarantine import quarantines
|
from pyquarantine import quarantines
|
||||||
from pyquarantine import notifications
|
from pyquarantine import notifications
|
||||||
from pyquarantine import whitelists
|
from pyquarantine import whitelists
|
||||||
@@ -71,6 +71,20 @@ class QuarantineMilter(Milter.Base):
|
|||||||
def set_configfiles(config_files):
|
def set_configfiles(config_files):
|
||||||
QuarantineMilter._config_files = 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
|
@Milter.noreply
|
||||||
def envfrom(self, mailfrom, *str):
|
def envfrom(self, mailfrom, *str):
|
||||||
self.mailfrom = "@".join(parse_addr(mailfrom)).lower()
|
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
|
# check if optional config options are present in config
|
||||||
defaults = {
|
defaults = {
|
||||||
"reject_reason": "Message rejected"
|
"reject_reason": "Message rejected",
|
||||||
|
"ignore_hosts": ""
|
||||||
}
|
}
|
||||||
for option in defaults.keys():
|
for option in defaults.keys():
|
||||||
if option not in config.keys() and \
|
if option not in config.keys() and \
|
||||||
@@ -391,6 +406,22 @@ def generate_milter_config(configtest=False, config_files=[]):
|
|||||||
else:
|
else:
|
||||||
raise RuntimeError("{}: unknown action '{}'".format(quarantine_name, action))
|
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)
|
milter_config.append(config)
|
||||||
|
|
||||||
return global_config, milter_config
|
return global_config, milter_config
|
||||||
|
|||||||
Reference in New Issue
Block a user