add action to store message in file

This commit is contained in:
2020-06-17 15:04:25 +02:00
parent 3c40776542
commit d592ca59cf
2 changed files with 37 additions and 5 deletions

View File

@@ -13,16 +13,17 @@
# #
import logging import logging
import os
import re import re
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
from collections import defaultdict from collections import defaultdict
from copy import copy from copy import copy
from datetime import datetime
from email.header import Header from email.header import Header
from email.parser import BytesFeedParser from email.parser import BytesFeedParser
from email.message import MIMEPart from email.message import MIMEPart
from email.policy import default as default_policy, SMTP from email.policy import default as default_policy, SMTP
from os import linesep
from pymodmilter import CustomLogger, Conditions from pymodmilter import CustomLogger, Conditions
@@ -384,13 +385,36 @@ def add_disclaimer(text, html, action, policy, milter, pretend=False,
milter=milter, pretend=pretend, logger=logger) milter=milter, pretend=pretend, logger=logger)
def store(directory, milter, pretend=False,
logger=logging.getLogger(__name__)):
timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
store_id = f"{timestamp}_{milter.qid}"
datafile = os.path.join(directory, store_id)
milter.fp.seek(0)
logger.info("store message in file {datafile}")
try:
with open(datafile, "wb") as fp:
for field, value in milter.fields:
encoded_value = _replace_illegal_chars(
Header(s=value).encode())
fp.write(field.encode("ascii", errors="replace"))
fp.write(b": ")
fp.write(encoded_value.encode("ascii", errors="replace"))
fp.write(b"\r\n")
fp.write(b"\r\n")
fp.write(milter.fp.read())
except IOError as e:
raise RuntimeError(f"unable to store message: {e}")
class Action: class Action:
"""Action to implement a pre-configured action to perform on e-mails.""" """Action to implement a pre-configured action to perform on e-mails."""
_types = { _types = {
"add_header": ["fields"], "add_header": ["fields"],
"del_header": ["fields"], "del_header": ["fields"],
"mod_header": ["fields"], "mod_header": ["fields"],
"add_disclaimer": ["fields", "body"]} "add_disclaimer": ["fields", "body"],
"store": ["fields", "body"]}
def __init__(self, name, local_addrs, conditions, action_type, args, def __init__(self, name, local_addrs, conditions, action_type, args,
loglevel=logging.INFO, pretend=False): loglevel=logging.INFO, pretend=False):
@@ -406,7 +430,7 @@ class Action:
self._args = {} self._args = {}
if action_type not in self._types: if action_type not in self._types:
raise RuntimeError(f"invalid action_type '{action_type}'") raise RuntimeError(f"invalid action type '{action_type}'")
self._needs = self._types[action_type] self._needs = self._types[action_type]
try: try:
@@ -465,8 +489,16 @@ class Action:
self._args["text"] = f.read() self._args["text"] = f.read()
except IOError as e: except IOError as e:
raise RuntimeError(f"unable to read template: {e}") raise RuntimeError(f"unable to read template: {e}")
elif action_type == "store":
self._func = store
if args["storage_type"] not in ["file"]:
raise RuntimeError(
f"invalid storage_type 'args['storage_type']'")
if args["storage_type"] == "file":
self._args["directory"] = args["directory"]
else: else:
raise RuntimeError(f"unknown action type: {action_type}") raise RuntimeError(f"invalid action type: {action_type}")
except KeyError as e: except KeyError as e:
raise RuntimeError( raise RuntimeError(

View File

@@ -1 +1 @@
__version__ = "1.0.7" __version__ = "1.0.8"