fix multiple bugs

This commit is contained in:
2024-01-12 14:46:48 +01:00
parent 6389bf6668
commit dc085a7138
4 changed files with 58 additions and 51 deletions

View File

@@ -225,14 +225,14 @@ Options:
##### quarantine ##### quarantine
Quarantine e-mail. Quarantine e-mail.
Options: Options:
* **store** * **storage**
Index of a Storage object in the global storages object. Index of a Storage object in the global storages object.
If the option **metadata** is not specifically set for this storage, it will be set to true. If the option **metadata** is not specifically set for this storage, it will be set to true.
* **smtp_host** * **smtp_host**
SMTP host used to release e-mails from quarantine. SMTP host used to release e-mails from quarantine.
* **smtp_port** * **smtp_port**
SMTP port used to release e-mails from quarantine. SMTP port used to release e-mails from quarantine.
* **notify** (optional) * **notification** (optional)
Index of a Notification object in the global notifications object. Index of a Notification object in the global notifications object.
* **milter_action** (optional) * **milter_action** (optional)
Milter action to perform. If set, no further rules or actions will be processed. Milter action to perform. If set, no further rules or actions will be processed.
@@ -331,11 +331,11 @@ In this example it is assumed, that another milter (e.g. Amavisd or Rspamd) adds
"storages": { "storages": {
"virus": { "virus": {
"type": "file", "type": "file",
"directory": "/mnt/data/quarantine/virus", "directory": "/mnt/data/quarantine/virus"
}, },
"spam": { "spam": {
"type": "file", "type": "file",
"directory": "/mnt/data/quarantine/spam", "directory": "/mnt/data/quarantine/spam"
} }
}, },
"notifications": { "notifications": {
@@ -371,11 +371,11 @@ In this example it is assumed, that another milter (e.g. Amavisd or Rspamd) adds
"name": "virus", "name": "virus",
"type": "quarantine", "type": "quarantine",
"conditions": { "conditions": {
"headers": ["^X-Virus: Yes"], "headers": ["^X-Virus: Yes"]
}, },
"options": { "options": {
"store": "virus", "storage": "virus",
"notify": "virus", "notification": "virus",
"smtp_host": "localhost", "smtp_host": "localhost",
"smtp_port": 2525, "smtp_port": 2525,
"milter_action": "REJECT", "milter_action": "REJECT",
@@ -388,8 +388,8 @@ In this example it is assumed, that another milter (e.g. Amavisd or Rspamd) adds
"headers": ["^X-Spam: Yes"] "headers": ["^X-Spam: Yes"]
}, },
"options": { "options": {
"store": "spam", "storage": "spam",
"notify": "spam", "notification": "spam",
"smtp_host": "localhost", "smtp_host": "localhost",
"smtp_port": 2525, "smtp_port": 2525,
"milter_action": "DISCARD" "milter_action": "DISCARD"
@@ -449,7 +449,7 @@ In this example it is assumed, that another milter (e.g. Amavisd or Rspamd) adds
"orig": { "orig": {
"type": "file", "type": "file",
"directory": "/mnt/data/incoming", "directory": "/mnt/data/incoming",
"original": true, "original": true
} }
}, },
"rules": [ "rules": [

View File

@@ -219,6 +219,14 @@ class StoreConfig(BaseConfig):
"properties": { "properties": {
"storage": {"type": "string"}}} "storage": {"type": "string"}}}
def __init__(self, config, milter_config):
super().__init__(config)
storage = self["storage"]
try:
self["storage"] = milter_config["storages"][storage]
except KeyError:
raise RuntimeError(f"storage '{storage}' not found")
class NotificationConfig(BaseConfig): class NotificationConfig(BaseConfig):
JSON_SCHEMA = { JSON_SCHEMA = {
@@ -257,37 +265,45 @@ class NotifyConfig(BaseConfig):
"properties": { "properties": {
"notification": {"type": "string"}}} "notification": {"type": "string"}}}
def __init__(self, config, milter_config):
super().__init__(config)
notification = self["notification"]
try:
self["notification"] = milter_config["notifications"][notification]
except KeyError:
raise RuntimeError(f"notification '{notification}' not found")
class QuarantineConfig(BaseConfig): class QuarantineConfig(BaseConfig):
JSON_SCHEMA = { JSON_SCHEMA = {
"type": "object", "type": "object",
"required": ["store", "smtp_host", "smtp_port"], "required": ["storage", "smtp_host", "smtp_port"],
"additionalProperties": False, "additionalProperties": False,
"properties": { "properties": {
"name": {"type": "string"}, "name": {"type": "string"},
"notify": {"type": "string"}, "notification": {"type": "string"},
"milter_action": {"type": "string"}, "milter_action": {"type": "string"},
"reject_reason": {"type": "string"}, "reject_reason": {"type": "string"},
"allowlist": {"type": "string"}, "allowlist": {"type": "string"},
"store": {"type": "string"}, "storage": {"type": "string"},
"smtp_host": {"type": "string"}, "smtp_host": {"type": "string"},
"smtp_port": {"type": "number"}}} "smtp_port": {"type": "number"}}}
def __init__(self, config, milter_config, rec=True): def __init__(self, config, milter_config, rec=True):
super().__init__(config) super().__init__(config)
storage = self["store"] storage = self["storage"]
try: try:
self["store"] = milter_config["storages"][storage] self["storage"] = milter_config["storages"][storage]
except KeyError: except KeyError:
raise RuntimeError(f"storage '{storage}' not found") raise RuntimeError(f"storage '{storage}' not found")
if "metadata" not in self["store"]: if "metadata" not in self["storage"]:
self["store"]["metadata"] = True self["storage"]["metadata"] = True
if "notify" in self: if "notification" in self:
notify = self["notify"] notification = self["notification"]
try: try:
self["notify"] = milter_config["notifications"][notify] self["notification"] = milter_config["notifications"][notification]
except KeyError: except KeyError:
raise RuntimeError(f"notification '{notify}' not found") raise RuntimeError(f"notification '{notification}' not found")
if "allowlist" in self: if "allowlist" in self:
allowlist = self["allowlist"] allowlist = self["allowlist"]
try: try:
@@ -331,19 +347,9 @@ class ActionConfig(BaseConfig):
self["conditions"] = ConditionsConfig(self["conditions"], lists) self["conditions"] = ConditionsConfig(self["conditions"], lists)
if self["type"] == "store": if self["type"] == "store":
storage = StoreConfig(self["options"])["storage"] storage = StoreConfig(self["options"], milter_config)["storage"]
try:
self["action"] = milter_config["storages"][storage]
except KeyError:
raise RuntimeError(f"storage '{storage}' not found")
elif self["type"] == "notify": elif self["type"] == "notify":
notify = NotifyConfig(self["options"])["notification"] notify = NotifyConfig(self["options"], milter_config)["notification"]
try:
self["action"] = milter_config["notifications"][notify]
except KeyError:
raise RuntimeError(f"notification '{notify}' not found")
else: else:
self["action"] = self.ACTION_TYPES[self["type"]]( self["action"] = self.ACTION_TYPES[self["type"]](
self["options"], milter_config) self["options"], milter_config)

View File

@@ -331,19 +331,21 @@ class Notify:
def __init__(self, cfg, local_addrs, debug): def __init__(self, cfg, local_addrs, debug):
self.cfg = cfg self.cfg = cfg
self.name = cfg["name"]
self.logger = logging.getLogger(cfg["name"]) self.logger = logging.getLogger(cfg["name"])
del cfg["name"]
self.logger.setLevel(cfg.get_loglevel(debug)) self.logger.setLevel(cfg.get_loglevel(debug))
del cfg["loglevel"]
nodification_type = cfg["type"] self.name = f"{cfg['name']}: {cfg['options']['notification']['name']}"
del cfg["type"] del cfg["options"]["notification"]["name"]
self._notification = self.NOTIFICATION_TYPES[nodification_type](**cfg)
nodification_type = cfg["options"]["notification"]["type"]
del cfg["options"]["notification"]["type"]
self._notification = self.NOTIFICATION_TYPES[nodification_type](**cfg["options"]["notification"])
self._headersonly = self._notification._headersonly self._headersonly = self._notification._headersonly
def __str__(self): def __str__(self):
cfg = [] cfg = []
for key, value in self.cfg.items(): for key, value in self.cfg["options"]["notification"].items():
cfg.append(f"{key}={value}") cfg.append(f"{key}={value}")
class_name = type(self._notification).__name__ class_name = type(self._notification).__name__
return f"{class_name}(" + ", ".join(cfg) + ")" return f"{class_name}(" + ", ".join(cfg) + ")"

View File

@@ -371,19 +371,21 @@ class Store:
def __init__(self, cfg, local_addrs, debug): def __init__(self, cfg, local_addrs, debug):
self.cfg = cfg self.cfg = cfg
self.name = cfg["name"]
self.logger = logging.getLogger(cfg["name"]) self.logger = logging.getLogger(cfg["name"])
del cfg["name"]
self.logger.setLevel(cfg.get_loglevel(debug)) self.logger.setLevel(cfg.get_loglevel(debug))
del cfg["loglevel"]
storage_type = cfg["type"] self.name = f"{cfg['name']}: {cfg['options']['storage']['name']}"
del cfg["type"] del cfg["options"]["storage"]["name"]
self._storage = self.STORAGE_TYPES[storage_type](**cfg)
storage_type = cfg["options"]["storage"]["type"]
del cfg["options"]["storage"]["type"]
self._storage = self.STORAGE_TYPES[storage_type](**cfg["options"]["storage"])
self._headersonly = self._storage._headersonly self._headersonly = self._storage._headersonly
def __str__(self): def __str__(self):
cfg = [] cfg = []
for key, value in self.cfg.items(): for key, value in self.cfg["options"]["storage"].items():
cfg.append(f"{key}={value}") cfg.append(f"{key}={value}")
class_name = type(self._storage).__name__ class_name = type(self._storage).__name__
return f"{class_name}(" + ", ".join(cfg) + ")" return f"{class_name}(" + ", ".join(cfg) + ")"
@@ -406,10 +408,7 @@ class Quarantine:
self.logger = logging.getLogger(cfg["name"]) self.logger = logging.getLogger(cfg["name"])
self.logger.setLevel(cfg.get_loglevel(debug)) self.logger.setLevel(cfg.get_loglevel(debug))
name = cfg["options"]["store"]["name"] self._storage = Store(cfg, local_addrs, debug)
cfg["options"]["store"]["name"] = f"{cfg['name']}: {name}"
cfg["options"]["store"]["loglevel"] = cfg["loglevel"]
self._storage = Store(cfg["options"]["store"], local_addrs, debug)
self.smtp_host = cfg["options"]["smtp_host"] self.smtp_host = cfg["options"]["smtp_host"]
self.smtp_port = cfg["options"]["smtp_port"] self.smtp_port = cfg["options"]["smtp_port"]