change config structure
This commit is contained in:
@@ -27,7 +27,7 @@ __all__ = [
|
|||||||
"list",
|
"list",
|
||||||
"QuarantineMilter"]
|
"QuarantineMilter"]
|
||||||
|
|
||||||
__version__ = "2.0.8"
|
__version__ = "2.1.0"
|
||||||
|
|
||||||
from pyquarantine import _runtime_patches
|
from pyquarantine import _runtime_patches
|
||||||
|
|
||||||
|
|||||||
@@ -39,8 +39,7 @@ class Action:
|
|||||||
self.conditions["loglevel"] = cfg["loglevel"]
|
self.conditions["loglevel"] = cfg["loglevel"]
|
||||||
self.conditions = Conditions(self.conditions, local_addrs, debug)
|
self.conditions = Conditions(self.conditions, local_addrs, debug)
|
||||||
|
|
||||||
action_type = cfg["type"]
|
self.action = self.ACTION_TYPES[cfg["type"]](
|
||||||
self.action = self.ACTION_TYPES[action_type](
|
|
||||||
cfg, local_addrs, debug)
|
cfg, local_addrs, debug)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|||||||
@@ -21,28 +21,31 @@ import logging.handlers
|
|||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from pyquarantine.config import get_milter_config, ActionConfig, ListConfig
|
from pyquarantine.action import Action
|
||||||
|
from pyquarantine.config import get_milter_config, ActionConfig, StorageConfig, NotificationConfig, ListConfig
|
||||||
from pyquarantine.storage import Quarantine
|
from pyquarantine.storage import Quarantine
|
||||||
from pyquarantine.list import DatabaseList
|
from pyquarantine.list import DatabaseList
|
||||||
from pyquarantine import __version__ as version
|
from pyquarantine import __version__ as version
|
||||||
|
|
||||||
|
|
||||||
def _get_quarantines(cfg):
|
def _get_quarantines(milter_cfg):
|
||||||
quarantines = []
|
quarantines = []
|
||||||
for rule in cfg["rules"]:
|
for rule in milter_cfg["rules"]:
|
||||||
for action in rule["actions"]:
|
for action in rule["actions"]:
|
||||||
if action["type"] == "quarantine":
|
if action["type"] == "quarantine":
|
||||||
quarantines.append(action)
|
quarantines.append(action)
|
||||||
return quarantines
|
return quarantines
|
||||||
|
|
||||||
|
|
||||||
def _get_quarantine(cfg, name, debug):
|
def _get_quarantine(milter_cfg, name, debug):
|
||||||
try:
|
try:
|
||||||
quarantine = next(
|
quarantine = next(
|
||||||
(q for q in _get_quarantines(cfg) if q["name"] == name))
|
(q for q in _get_quarantines(milter_cfg) if q["name"] == name))
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
raise RuntimeError(f"invalid quarantine '{name}'")
|
raise RuntimeError(f"invalid quarantine '{name}'")
|
||||||
return Quarantine(ActionConfig(quarantine, cfg["lists"]), [], debug)
|
|
||||||
|
cfg = ActionConfig(quarantine, milter_cfg)
|
||||||
|
return Quarantine(cfg, [], debug)
|
||||||
|
|
||||||
|
|
||||||
def _get_notification(cfg, name, debug):
|
def _get_notification(cfg, name, debug):
|
||||||
@@ -55,7 +58,7 @@ def _get_notification(cfg, name, debug):
|
|||||||
|
|
||||||
def _get_list(cfg, name, debug):
|
def _get_list(cfg, name, debug):
|
||||||
try:
|
try:
|
||||||
list_cfg = ListConfig(cfg["lists"][name], {})
|
list_cfg = cfg["lists"][name]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise RuntimeError(f"list '{name}' is not configured")
|
raise RuntimeError(f"list '{name}' is not configured")
|
||||||
|
|
||||||
@@ -107,7 +110,7 @@ def print_table(columns, rows):
|
|||||||
print(row_format.format(*row))
|
print(row_format.format(*row))
|
||||||
|
|
||||||
|
|
||||||
def list_quarantines(cfg, args):
|
def llist(cfg, args):
|
||||||
quarantines = _get_quarantines(cfg)
|
quarantines = _get_quarantines(cfg)
|
||||||
if args.batch:
|
if args.batch:
|
||||||
print("\n".join([q["name"] for q in quarantines]))
|
print("\n".join([q["name"] for q in quarantines]))
|
||||||
@@ -115,32 +118,33 @@ def list_quarantines(cfg, args):
|
|||||||
qlist = []
|
qlist = []
|
||||||
for q in quarantines:
|
for q in quarantines:
|
||||||
qcfg = q["options"]
|
qcfg = q["options"]
|
||||||
storage_type = qcfg["store"]["type"]
|
|
||||||
|
|
||||||
if "notify" in cfg:
|
if "notify" in qcfg:
|
||||||
notification_type = qcfg["notify"]["type"]
|
notification = cfg["notifications"][qcfg["notify"]]["name"]
|
||||||
else:
|
else:
|
||||||
notification_type = "NONE"
|
notification = "NONE"
|
||||||
|
|
||||||
if "lists" in qcfg:
|
if "allowlist" in qcfg:
|
||||||
lists_type = qcfg["lists"]
|
allowlist = qcfg["allowlist"]
|
||||||
else:
|
else:
|
||||||
lists_type = "NONE"
|
allowlist = "NONE"
|
||||||
|
|
||||||
if "milter_action" in qcfg:
|
if "milter_action" in qcfg:
|
||||||
milter_action = qcfg["milter_action"]
|
milter_action = qcfg["milter_action"]
|
||||||
else:
|
else:
|
||||||
milter_action = "NONE"
|
milter_action = "NONE"
|
||||||
|
|
||||||
|
storage_name = cfg["storages"][qcfg["store"]]["name"]
|
||||||
|
|
||||||
qlist.append({
|
qlist.append({
|
||||||
"name": q["name"],
|
"name": q["name"],
|
||||||
"storage": storage_type,
|
"storage": storage_name,
|
||||||
"notification": notification_type,
|
"notification": notification,
|
||||||
"lists": lists_type,
|
"lists": allowlist,
|
||||||
"action": milter_action})
|
"action": milter_action})
|
||||||
|
|
||||||
print_table(
|
print_table(
|
||||||
[("Name", "name"),
|
[("Quarantine", "name"),
|
||||||
("Storage", "storage"),
|
("Storage", "storage"),
|
||||||
("Notification", "notification"),
|
("Notification", "notification"),
|
||||||
("Allowlist", "lists"),
|
("Allowlist", "lists"),
|
||||||
@@ -148,6 +152,48 @@ def list_quarantines(cfg, args):
|
|||||||
qlist
|
qlist
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if "storages" in cfg:
|
||||||
|
storages = []
|
||||||
|
for name, options in cfg["storages"].items():
|
||||||
|
storages.append({
|
||||||
|
"name": name,
|
||||||
|
"type": options["type"]})
|
||||||
|
|
||||||
|
print("\n")
|
||||||
|
print_table(
|
||||||
|
[("Storage", "name"),
|
||||||
|
("Type", "type")],
|
||||||
|
storages
|
||||||
|
)
|
||||||
|
|
||||||
|
if "notifications" in cfg:
|
||||||
|
notifications = []
|
||||||
|
for name, options in cfg["notifications"].items():
|
||||||
|
notifications.append({
|
||||||
|
"name": name,
|
||||||
|
"type": options["type"]})
|
||||||
|
|
||||||
|
print("\n")
|
||||||
|
print_table(
|
||||||
|
[("Notification", "name"),
|
||||||
|
("Type", "type")],
|
||||||
|
notifications
|
||||||
|
)
|
||||||
|
|
||||||
|
if "lists" in cfg:
|
||||||
|
lst_list = []
|
||||||
|
for name, options in cfg["lists"].items():
|
||||||
|
lst_list.append({
|
||||||
|
"name": name,
|
||||||
|
"type": options["type"]})
|
||||||
|
|
||||||
|
print("\n")
|
||||||
|
print_table(
|
||||||
|
[("List", "name"),
|
||||||
|
("Type", "type")],
|
||||||
|
lst_list
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def list_quarantine_emails(cfg, args):
|
def list_quarantine_emails(cfg, args):
|
||||||
storage = _get_quarantine(cfg, args.quarantine, args.debug).storage
|
storage = _get_quarantine(cfg, args.quarantine, args.debug).storage
|
||||||
@@ -364,7 +410,7 @@ def main():
|
|||||||
"-b", "--batch",
|
"-b", "--batch",
|
||||||
help="Print results using only quarantine names, each on a new line.",
|
help="Print results using only quarantine names, each on a new line.",
|
||||||
action="store_true")
|
action="store_true")
|
||||||
list_parser.set_defaults(func=list_quarantines)
|
list_parser.set_defaults(func=llist)
|
||||||
|
|
||||||
# quarantine command group
|
# quarantine command group
|
||||||
quar_parser = subparsers.add_parser(
|
quar_parser = subparsers.add_parser(
|
||||||
@@ -638,7 +684,7 @@ def main():
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
logger.debug("read milter configuration")
|
logger.debug("read milter configuration")
|
||||||
cfg = get_milter_config(args.config, raw=True)
|
cfg = get_milter_config(args.config, rec=False)
|
||||||
|
|
||||||
if "rules" not in cfg or not cfg["rules"]:
|
if "rules" not in cfg or not cfg["rules"]:
|
||||||
raise RuntimeError("no rules configured")
|
raise RuntimeError("no rules configured")
|
||||||
|
|||||||
@@ -20,7 +20,9 @@ __all__ = [
|
|||||||
"DelHeaderConfig",
|
"DelHeaderConfig",
|
||||||
"AddDisclaimerConfig",
|
"AddDisclaimerConfig",
|
||||||
"RewriteLinksConfig",
|
"RewriteLinksConfig",
|
||||||
|
"StorageConfig",
|
||||||
"StoreConfig",
|
"StoreConfig",
|
||||||
|
"NotificationConfig",
|
||||||
"NotifyConfig",
|
"NotifyConfig",
|
||||||
"ListConfig",
|
"ListConfig",
|
||||||
"QuarantineConfig",
|
"QuarantineConfig",
|
||||||
@@ -43,7 +45,7 @@ class BaseConfig:
|
|||||||
"properties": {
|
"properties": {
|
||||||
"loglevel": {"type": "string", "default": "info"}}}
|
"loglevel": {"type": "string", "default": "info"}}}
|
||||||
|
|
||||||
def __init__(self, config, lists):
|
def __init__(self, config, *args, **kwargs):
|
||||||
required = self.JSON_SCHEMA["required"]
|
required = self.JSON_SCHEMA["required"]
|
||||||
properties = self.JSON_SCHEMA["properties"]
|
properties = self.JSON_SCHEMA["properties"]
|
||||||
for p in properties.keys():
|
for p in properties.keys():
|
||||||
@@ -126,15 +128,13 @@ class ConditionsConfig(BaseConfig):
|
|||||||
"list": {"type": "string"}}}
|
"list": {"type": "string"}}}
|
||||||
|
|
||||||
def __init__(self, config, lists, rec=True):
|
def __init__(self, config, lists, rec=True):
|
||||||
super().__init__(config, lists)
|
super().__init__(config)
|
||||||
if "list" in self:
|
if "list" in self:
|
||||||
lst = self["list"]
|
lst = self["list"]
|
||||||
try:
|
try:
|
||||||
self["list"] = lists[lst]
|
self["list"] = lists[lst]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise RuntimeError(f"list '{lst}' is not configured")
|
raise RuntimeError(f"list '{lst}' not found in config")
|
||||||
if not rec:
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
class AddHeaderConfig(BaseConfig):
|
class AddHeaderConfig(BaseConfig):
|
||||||
@@ -190,7 +190,7 @@ class RewriteLinksConfig(BaseConfig):
|
|||||||
"repl": {"type": "string"}}}
|
"repl": {"type": "string"}}}
|
||||||
|
|
||||||
|
|
||||||
class StoreConfig(BaseConfig):
|
class StorageConfig(BaseConfig):
|
||||||
JSON_SCHEMA = {
|
JSON_SCHEMA = {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": ["type"],
|
"required": ["type"],
|
||||||
@@ -203,6 +203,7 @@ class StoreConfig(BaseConfig):
|
|||||||
"additionalProperties": False,
|
"additionalProperties": False,
|
||||||
"properties": {
|
"properties": {
|
||||||
"type": {"type": "string"},
|
"type": {"type": "string"},
|
||||||
|
"name": {"type": "string"},
|
||||||
"directory": {"type": "string"},
|
"directory": {"type": "string"},
|
||||||
"mode": {"type": "string"},
|
"mode": {"type": "string"},
|
||||||
"metavar": {"type": "string"},
|
"metavar": {"type": "string"},
|
||||||
@@ -210,7 +211,16 @@ class StoreConfig(BaseConfig):
|
|||||||
"original": {"type": "boolean", "default": False}}}}
|
"original": {"type": "boolean", "default": False}}}}
|
||||||
|
|
||||||
|
|
||||||
class NotifyConfig(BaseConfig):
|
class StoreConfig(BaseConfig):
|
||||||
|
JSON_SCHEMA = {
|
||||||
|
"type": "object",
|
||||||
|
"required": ["storage"],
|
||||||
|
"additionalProperties": False,
|
||||||
|
"properties": {
|
||||||
|
"storage": {"type": "string"}}}
|
||||||
|
|
||||||
|
|
||||||
|
class NotificationConfig(BaseConfig):
|
||||||
JSON_SCHEMA = {
|
JSON_SCHEMA = {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": ["type"],
|
"required": ["type"],
|
||||||
@@ -224,6 +234,7 @@ class NotifyConfig(BaseConfig):
|
|||||||
"additionalProperties": False,
|
"additionalProperties": False,
|
||||||
"properties": {
|
"properties": {
|
||||||
"type": {"type": "string"},
|
"type": {"type": "string"},
|
||||||
|
"name": {"type": "string"},
|
||||||
"smtp_host": {"type": "string"},
|
"smtp_host": {"type": "string"},
|
||||||
"smtp_port": {"type": "number"},
|
"smtp_port": {"type": "number"},
|
||||||
"envelope_from": {"type": "string"},
|
"envelope_from": {"type": "string"},
|
||||||
@@ -238,6 +249,15 @@ class NotifyConfig(BaseConfig):
|
|||||||
"default": []}}}}
|
"default": []}}}}
|
||||||
|
|
||||||
|
|
||||||
|
class NotifyConfig(BaseConfig):
|
||||||
|
JSON_SCHEMA = {
|
||||||
|
"type": "object",
|
||||||
|
"required": ["notification"],
|
||||||
|
"additionalProperties": False,
|
||||||
|
"properties": {
|
||||||
|
"notification": {"type": "string"}}}
|
||||||
|
|
||||||
|
|
||||||
class QuarantineConfig(BaseConfig):
|
class QuarantineConfig(BaseConfig):
|
||||||
JSON_SCHEMA = {
|
JSON_SCHEMA = {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -245,29 +265,38 @@ class QuarantineConfig(BaseConfig):
|
|||||||
"additionalProperties": False,
|
"additionalProperties": False,
|
||||||
"properties": {
|
"properties": {
|
||||||
"name": {"type": "string"},
|
"name": {"type": "string"},
|
||||||
"notify": {"type": "object"},
|
"notify": {"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": "object"},
|
"store": {"type": "string"},
|
||||||
"smtp_host": {"type": "string"},
|
"smtp_host": {"type": "string"},
|
||||||
"smtp_port": {"type": "number"}}}
|
"smtp_port": {"type": "number"}}}
|
||||||
|
|
||||||
def __init__(self, config, lists, rec=True):
|
def __init__(self, config, milter_config, rec=True):
|
||||||
super().__init__(config, lists)
|
super().__init__(config)
|
||||||
if not rec:
|
storage = self["store"]
|
||||||
return
|
try:
|
||||||
|
self["store"] = milter_config["storages"][storage]
|
||||||
|
except KeyError:
|
||||||
|
raise RuntimeError(f"storage '{storage}' not found")
|
||||||
if "metadata" not in self["store"]:
|
if "metadata" not in self["store"]:
|
||||||
self["store"]["metadata"] = True
|
self["store"]["metadata"] = True
|
||||||
self["store"] = StoreConfig(self["store"], lists)
|
|
||||||
if "notify" in self:
|
if "notify" in self:
|
||||||
self["notify"] = NotifyConfig(self["notify"], lists)
|
notify = self["notify"]
|
||||||
|
try:
|
||||||
|
self["notify"] = milter_config["notifications"][notify]
|
||||||
|
except KeyError:
|
||||||
|
raise RuntimeError(f"notification '{notify}' not found")
|
||||||
if "allowlist" in self:
|
if "allowlist" in self:
|
||||||
allowlist = self["allowlist"]
|
allowlist = self["allowlist"]
|
||||||
try:
|
try:
|
||||||
self["allowlist"] = lists[allowlist]
|
self["allowlist"] = milter_config["lists"][allowlist]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise RuntimeError(f"list '{allowlist}' is not configured")
|
raise RuntimeError(f"list '{allowlist}' not found")
|
||||||
|
|
||||||
|
if not rec:
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
class ActionConfig(BaseConfig):
|
class ActionConfig(BaseConfig):
|
||||||
@@ -293,14 +322,31 @@ class ActionConfig(BaseConfig):
|
|||||||
"type": {"enum": list(ACTION_TYPES.keys())},
|
"type": {"enum": list(ACTION_TYPES.keys())},
|
||||||
"options": {"type": "object"}}}
|
"options": {"type": "object"}}}
|
||||||
|
|
||||||
def __init__(self, config, lists, rec=True):
|
def __init__(self, config, milter_config, rec=True):
|
||||||
super().__init__(config, lists)
|
super().__init__(config)
|
||||||
if not rec:
|
if not rec:
|
||||||
return
|
return
|
||||||
|
lists = milter_config["lists"]
|
||||||
if "conditions" in self:
|
if "conditions" in self:
|
||||||
self["conditions"] = ConditionsConfig(self["conditions"], lists)
|
self["conditions"] = ConditionsConfig(self["conditions"], lists)
|
||||||
self["action"] = self.ACTION_TYPES[self["type"]](
|
|
||||||
self["options"], 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")
|
||||||
|
|
||||||
|
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")
|
||||||
|
|
||||||
|
else:
|
||||||
|
self["action"] = self.ACTION_TYPES[self["type"]](
|
||||||
|
self["options"], milter_config)
|
||||||
|
|
||||||
|
|
||||||
class RuleConfig(BaseConfig):
|
class RuleConfig(BaseConfig):
|
||||||
@@ -315,10 +361,11 @@ class RuleConfig(BaseConfig):
|
|||||||
"conditions": {"type": "object"},
|
"conditions": {"type": "object"},
|
||||||
"actions": {"type": "array"}}}
|
"actions": {"type": "array"}}}
|
||||||
|
|
||||||
def __init__(self, config, lists, rec=True):
|
def __init__(self, config, milter_config, rec=True):
|
||||||
super().__init__(config, lists)
|
super().__init__(config)
|
||||||
if not rec:
|
if not rec:
|
||||||
return
|
return
|
||||||
|
lists = milter_config["lists"]
|
||||||
if "conditions" in self:
|
if "conditions" in self:
|
||||||
self["conditions"] = ConditionsConfig(self["conditions"], lists)
|
self["conditions"] = ConditionsConfig(self["conditions"], lists)
|
||||||
|
|
||||||
@@ -328,7 +375,7 @@ class RuleConfig(BaseConfig):
|
|||||||
action["loglevel"] = config["loglevel"]
|
action["loglevel"] = config["loglevel"]
|
||||||
if "pretend" not in action:
|
if "pretend" not in action:
|
||||||
action["pretend"] = config["pretend"]
|
action["pretend"] = config["pretend"]
|
||||||
actions.append(ActionConfig(action, lists, rec))
|
actions.append(ActionConfig(action, milter_config, rec))
|
||||||
self["actions"] = actions
|
self["actions"] = actions
|
||||||
|
|
||||||
|
|
||||||
@@ -350,29 +397,52 @@ class QuarantineMilterConfig(BaseConfig):
|
|||||||
"192.168.0.0/16"]},
|
"192.168.0.0/16"]},
|
||||||
"loglevel": {"type": "string", "default": "info"},
|
"loglevel": {"type": "string", "default": "info"},
|
||||||
"pretend": {"type": "boolean", "default": False},
|
"pretend": {"type": "boolean", "default": False},
|
||||||
"rules": {"type": "array"},
|
"lists": {
|
||||||
"lists": {"type": "array",
|
"type": "object",
|
||||||
"default": []}}}
|
"patternProperties": {"^(.+)$": {"type": "object"}},
|
||||||
|
"additionalProperties": False,
|
||||||
|
"default": {}},
|
||||||
|
"storages": {
|
||||||
|
"type": "object",
|
||||||
|
"patternProperties": {"^(.+)$": {"type": "object"}},
|
||||||
|
"additionalProperties": False,
|
||||||
|
"default": {}},
|
||||||
|
"notifications": {
|
||||||
|
"type": "object",
|
||||||
|
"patternProperties": {"^(.+)$": {"type": "object"}},
|
||||||
|
"additionalProperties": False,
|
||||||
|
"default": {}},
|
||||||
|
"rules": {"type": "array"}}}
|
||||||
|
|
||||||
def __init__(self, config, rec=True):
|
def __init__(self, config, rec=True):
|
||||||
super().__init__(config, {})
|
super().__init__(config)
|
||||||
|
for param in ["lists", "storages", "notifications"]:
|
||||||
|
for name, cfg in self[param].items():
|
||||||
|
if "name" not in cfg:
|
||||||
|
cfg["name"] = name
|
||||||
|
for name, cfg in self["lists"].items():
|
||||||
|
self["lists"][name] = ListConfig(cfg)
|
||||||
|
|
||||||
|
for name, cfg in self["storages"].items():
|
||||||
|
self["storages"][name] = StorageConfig(cfg)
|
||||||
|
|
||||||
|
for name, cfg in self["notifications"].items():
|
||||||
|
self["notifications"][name] = NotificationConfig(cfg)
|
||||||
|
|
||||||
if not rec:
|
if not rec:
|
||||||
return
|
return
|
||||||
lists = {}
|
|
||||||
for lst in self["lists"]:
|
|
||||||
lists[lst["name"]] = ListConfig(lst, rec)
|
|
||||||
self["lists"] = lists
|
|
||||||
rules = []
|
rules = []
|
||||||
for rule in self["rules"]:
|
for rule in self["rules"]:
|
||||||
if "loglevel" not in rule:
|
if "loglevel" not in rule:
|
||||||
rule["loglevel"] = config["loglevel"]
|
rule["loglevel"] = config["loglevel"]
|
||||||
if "pretend" not in rule:
|
if "pretend" not in rule:
|
||||||
rule["pretend"] = config["pretend"]
|
rule["pretend"] = config["pretend"]
|
||||||
rules.append(RuleConfig(rule, lists, rec))
|
rules.append(RuleConfig(rule, self, rec))
|
||||||
self["rules"] = rules
|
self["rules"] = rules
|
||||||
|
|
||||||
|
|
||||||
def get_milter_config(cfgfile, raw=False):
|
def get_milter_config(cfgfile, rec=True):
|
||||||
try:
|
try:
|
||||||
with open(cfgfile, "r") as fh:
|
with open(cfgfile, "r") as fh:
|
||||||
# remove lines with leading # (comments), they
|
# remove lines with leading # (comments), they
|
||||||
@@ -387,10 +457,4 @@ def get_milter_config(cfgfile, raw=False):
|
|||||||
cfg_text = [f"{n+1}: {l}" for n, l in enumerate(cfg.splitlines())]
|
cfg_text = [f"{n+1}: {l}" for n, l in enumerate(cfg.splitlines())]
|
||||||
msg = "\n".join(cfg_text)
|
msg = "\n".join(cfg_text)
|
||||||
raise RuntimeError(f"{e}\n{msg}")
|
raise RuntimeError(f"{e}\n{msg}")
|
||||||
if raw:
|
return QuarantineMilterConfig(cfg, rec)
|
||||||
lists = {}
|
|
||||||
for lst in cfg["lists"]:
|
|
||||||
lists[lst["name"]] = lst
|
|
||||||
cfg["lists"] = lists
|
|
||||||
return cfg
|
|
||||||
return QuarantineMilterConfig(cfg)
|
|
||||||
|
|||||||
@@ -331,18 +331,17 @@ class Notify:
|
|||||||
def __init__(self, cfg, local_addrs, debug):
|
def __init__(self, cfg, local_addrs, debug):
|
||||||
self.cfg = cfg
|
self.cfg = cfg
|
||||||
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["options"]["type"]
|
nodification_type = cfg["type"]
|
||||||
del cfg["options"]["type"]
|
del cfg["type"]
|
||||||
cfg["options"]["pretend"] = cfg["pretend"]
|
self._notification = self.NOTIFICATION_TYPES[nodification_type](**cfg)
|
||||||
self._notification = self.NOTIFICATION_TYPES[nodification_type](
|
|
||||||
**cfg["options"])
|
|
||||||
self._headersonly = self._notification._headersonly
|
self._headersonly = self._notification._headersonly
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
cfg = []
|
cfg = []
|
||||||
for key, value in self.cfg["options"].items():
|
for key, value in self.cfg.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) + ")"
|
||||||
|
|||||||
@@ -46,8 +46,9 @@ class Rule:
|
|||||||
actions = []
|
actions = []
|
||||||
for action in self.actions:
|
for action in self.actions:
|
||||||
actions.append(str(action))
|
actions.append(str(action))
|
||||||
cfg.append("actions=[" + ", ".join(actions) + "]")
|
cfg.append("actions=[\n " +
|
||||||
return "Rule(" + ", ".join(cfg) + ")"
|
",\n ".join(actions) + "\n ]")
|
||||||
|
return "Rule(\n " + ",\n ".join(cfg) + "\n)"
|
||||||
|
|
||||||
def execute(self, milter):
|
def execute(self, milter):
|
||||||
"""Execute all actions of this rule."""
|
"""Execute all actions of this rule."""
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ from time import gmtime
|
|||||||
|
|
||||||
from pyquarantine import mailer
|
from pyquarantine import mailer
|
||||||
from pyquarantine.base import CustomLogger, MilterMessage
|
from pyquarantine.base import CustomLogger, MilterMessage
|
||||||
from pyquarantine.config import ActionConfig
|
|
||||||
from pyquarantine.list import DatabaseList
|
from pyquarantine.list import DatabaseList
|
||||||
from pyquarantine.notify import Notify
|
from pyquarantine.notify import Notify
|
||||||
|
|
||||||
@@ -373,18 +372,17 @@ class Store:
|
|||||||
def __init__(self, cfg, local_addrs, debug):
|
def __init__(self, cfg, local_addrs, debug):
|
||||||
self.cfg = cfg
|
self.cfg = cfg
|
||||||
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["options"]["type"]
|
storage_type = cfg["type"]
|
||||||
del cfg["options"]["type"]
|
del cfg["type"]
|
||||||
cfg["options"]["pretend"] = cfg["pretend"]
|
self._storage = self.STORAGE_TYPES[storage_type](**cfg)
|
||||||
self._storage = self.STORAGE_TYPES[storage_type](
|
|
||||||
**cfg["options"])
|
|
||||||
self._headersonly = self._storage._headersonly
|
self._headersonly = self._storage._headersonly
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
cfg = []
|
cfg = []
|
||||||
for key, value in self.cfg["options"].items():
|
for key, value in self.cfg.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) + ")"
|
||||||
@@ -407,29 +405,17 @@ 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))
|
||||||
|
|
||||||
storage_cfg = ActionConfig(
|
cfg["options"]["store"]["loglevel"] = cfg["loglevel"]
|
||||||
{
|
self._storage = Store(cfg["options"]["store"], local_addrs, debug)
|
||||||
"name": cfg["name"],
|
|
||||||
"loglevel": cfg["loglevel"],
|
|
||||||
"pretend": cfg["pretend"],
|
|
||||||
"type": "store",
|
|
||||||
"options": cfg["options"]["store"].get_config()},
|
|
||||||
{})
|
|
||||||
self._storage = Store(storage_cfg, 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"]
|
||||||
|
|
||||||
self._notification = None
|
self._notification = None
|
||||||
if "notify" in cfg["options"]:
|
if "notify" in cfg["options"]:
|
||||||
notify_cfg = ActionConfig({
|
cfg["options"]["notify"]["loglevel"] = cfg["loglevel"]
|
||||||
"name": cfg["name"],
|
self._notification = Notify(
|
||||||
"loglevel": cfg["loglevel"],
|
cfg["options"]["notify"], local_addrs, debug)
|
||||||
"pretend": cfg["pretend"],
|
|
||||||
"type": "notify",
|
|
||||||
"options": cfg["options"]["notify"].get_config()},
|
|
||||||
{})
|
|
||||||
self._notification = Notify(notify_cfg, local_addrs, debug)
|
|
||||||
|
|
||||||
self._allowlist = None
|
self._allowlist = None
|
||||||
if "allowlist" in cfg["options"]:
|
if "allowlist" in cfg["options"]:
|
||||||
|
|||||||
Reference in New Issue
Block a user