From dc085a713826e4a3b541ee6a47f62dd31dba00cd Mon Sep 17 00:00:00 2001 From: Thomas Oettli Date: Fri, 12 Jan 2024 14:46:48 +0100 Subject: [PATCH] fix multiple bugs --- README.md | 20 ++++++++-------- pyquarantine/config.py | 52 +++++++++++++++++++++++------------------ pyquarantine/notify.py | 16 +++++++------ pyquarantine/storage.py | 21 ++++++++--------- 4 files changed, 58 insertions(+), 51 deletions(-) diff --git a/README.md b/README.md index 2336f06..cd02f36 100644 --- a/README.md +++ b/README.md @@ -225,14 +225,14 @@ Options: ##### quarantine Quarantine e-mail. Options: -* **store** +* **storage** 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. * **smtp_host** SMTP host used to release e-mails from quarantine. * **smtp_port** SMTP port used to release e-mails from quarantine. -* **notify** (optional) +* **notification** (optional) Index of a Notification object in the global notifications object. * **milter_action** (optional) 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": { "virus": { "type": "file", - "directory": "/mnt/data/quarantine/virus", + "directory": "/mnt/data/quarantine/virus" }, "spam": { "type": "file", - "directory": "/mnt/data/quarantine/spam", + "directory": "/mnt/data/quarantine/spam" } }, "notifications": { @@ -371,11 +371,11 @@ In this example it is assumed, that another milter (e.g. Amavisd or Rspamd) adds "name": "virus", "type": "quarantine", "conditions": { - "headers": ["^X-Virus: Yes"], + "headers": ["^X-Virus: Yes"] }, "options": { - "store": "virus", - "notify": "virus", + "storage": "virus", + "notification": "virus", "smtp_host": "localhost", "smtp_port": 2525, "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"] }, "options": { - "store": "spam", - "notify": "spam", + "storage": "spam", + "notification": "spam", "smtp_host": "localhost", "smtp_port": 2525, "milter_action": "DISCARD" @@ -449,7 +449,7 @@ In this example it is assumed, that another milter (e.g. Amavisd or Rspamd) adds "orig": { "type": "file", "directory": "/mnt/data/incoming", - "original": true, + "original": true } }, "rules": [ diff --git a/pyquarantine/config.py b/pyquarantine/config.py index 8b94717..a36fc5c 100644 --- a/pyquarantine/config.py +++ b/pyquarantine/config.py @@ -219,6 +219,14 @@ class StoreConfig(BaseConfig): "properties": { "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): JSON_SCHEMA = { @@ -257,37 +265,45 @@ class NotifyConfig(BaseConfig): "properties": { "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): JSON_SCHEMA = { "type": "object", - "required": ["store", "smtp_host", "smtp_port"], + "required": ["storage", "smtp_host", "smtp_port"], "additionalProperties": False, "properties": { "name": {"type": "string"}, - "notify": {"type": "string"}, + "notification": {"type": "string"}, "milter_action": {"type": "string"}, "reject_reason": {"type": "string"}, "allowlist": {"type": "string"}, - "store": {"type": "string"}, + "storage": {"type": "string"}, "smtp_host": {"type": "string"}, "smtp_port": {"type": "number"}}} def __init__(self, config, milter_config, rec=True): super().__init__(config) - storage = self["store"] + storage = self["storage"] try: - self["store"] = milter_config["storages"][storage] + self["storage"] = milter_config["storages"][storage] except KeyError: raise RuntimeError(f"storage '{storage}' not found") - if "metadata" not in self["store"]: - self["store"]["metadata"] = True - if "notify" in self: - notify = self["notify"] + if "metadata" not in self["storage"]: + self["storage"]["metadata"] = True + if "notification" in self: + notification = self["notification"] try: - self["notify"] = milter_config["notifications"][notify] + self["notification"] = milter_config["notifications"][notification] except KeyError: - raise RuntimeError(f"notification '{notify}' not found") + raise RuntimeError(f"notification '{notification}' not found") if "allowlist" in self: allowlist = self["allowlist"] try: @@ -331,19 +347,9 @@ class ActionConfig(BaseConfig): self["conditions"] = ConditionsConfig(self["conditions"], lists) if self["type"] == "store": - storage = StoreConfig(self["options"])["storage"] - try: - self["action"] = milter_config["storages"][storage] - except KeyError: - raise RuntimeError(f"storage '{storage}' not found") - + storage = StoreConfig(self["options"], milter_config)["storage"] elif self["type"] == "notify": - notify = NotifyConfig(self["options"])["notification"] - try: - self["action"] = milter_config["notifications"][notify] - except KeyError: - raise RuntimeError(f"notification '{notify}' not found") - + notify = NotifyConfig(self["options"], milter_config)["notification"] else: self["action"] = self.ACTION_TYPES[self["type"]]( self["options"], milter_config) diff --git a/pyquarantine/notify.py b/pyquarantine/notify.py index 107aeb6..799aa6b 100644 --- a/pyquarantine/notify.py +++ b/pyquarantine/notify.py @@ -331,19 +331,21 @@ class Notify: def __init__(self, cfg, local_addrs, debug): self.cfg = cfg - self.name = cfg["name"] self.logger = logging.getLogger(cfg["name"]) - del cfg["name"] self.logger.setLevel(cfg.get_loglevel(debug)) - del cfg["loglevel"] - nodification_type = cfg["type"] - del cfg["type"] - self._notification = self.NOTIFICATION_TYPES[nodification_type](**cfg) + + self.name = f"{cfg['name']}: {cfg['options']['notification']['name']}" + del cfg["options"]["notification"]["name"] + + 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 def __str__(self): cfg = [] - for key, value in self.cfg.items(): + for key, value in self.cfg["options"]["notification"].items(): cfg.append(f"{key}={value}") class_name = type(self._notification).__name__ return f"{class_name}(" + ", ".join(cfg) + ")" diff --git a/pyquarantine/storage.py b/pyquarantine/storage.py index 2ee7e41..04d8f23 100644 --- a/pyquarantine/storage.py +++ b/pyquarantine/storage.py @@ -371,19 +371,21 @@ class Store: def __init__(self, cfg, local_addrs, debug): self.cfg = cfg - self.name = cfg["name"] self.logger = logging.getLogger(cfg["name"]) - del cfg["name"] self.logger.setLevel(cfg.get_loglevel(debug)) - del cfg["loglevel"] - storage_type = cfg["type"] - del cfg["type"] - self._storage = self.STORAGE_TYPES[storage_type](**cfg) + + self.name = f"{cfg['name']}: {cfg['options']['storage']['name']}" + del cfg["options"]["storage"]["name"] + + 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 def __str__(self): cfg = [] - for key, value in self.cfg.items(): + for key, value in self.cfg["options"]["storage"].items(): cfg.append(f"{key}={value}") class_name = type(self._storage).__name__ return f"{class_name}(" + ", ".join(cfg) + ")" @@ -406,10 +408,7 @@ class Quarantine: self.logger = logging.getLogger(cfg["name"]) self.logger.setLevel(cfg.get_loglevel(debug)) - name = cfg["options"]["store"]["name"] - cfg["options"]["store"]["name"] = f"{cfg['name']}: {name}" - cfg["options"]["store"]["loglevel"] = cfg["loglevel"] - self._storage = Store(cfg["options"]["store"], local_addrs, debug) + self._storage = Store(cfg, local_addrs, debug) self.smtp_host = cfg["options"]["smtp_host"] self.smtp_port = cfg["options"]["smtp_port"]