Add dynamic template variables according to regex

This commit is contained in:
2019-05-01 13:02:41 +02:00
parent 4da5ee203d
commit f37b50eaac
4 changed files with 47 additions and 23 deletions

View File

@@ -119,9 +119,13 @@ class QuarantineMilter(Milter.Base):
# check email header against quarantine regex
self.logger.debug("{}: {}: checking header against regex '{}'".format(self.queueid, quarantine["name"], quarantine["regex"]))
if quarantine["regex_compiled"].match(header):
match = quarantine["regex_compiled"].search(header)
if match:
self.logger.debug("{}: {}: header matched regex".format(self.queueid, quarantine["name"]))
if "subgroups" not in quarantine.keys():
# save subgroups of match into the quarantine object for later use as template variables
quarantine["subgroups"] = match.groups(default="")
quarantine["named_subgroups"] = match.groupdict(default="")
# check for whitelisted recipients
whitelist = quarantine["whitelist_obj"]
if whitelist != None:
@@ -212,7 +216,8 @@ class QuarantineMilter(Milter.Base):
# add email to quarantine
self.logger.info("{}: adding to quarantine '{}' for: {}".format(self.queueid, quarantine["name"], ", ".join(recipients)))
try:
quarantine_id = quarantine["quarantine_obj"].add(self.queueid, self.mailfrom, recipients, self.subject, fp=self.fp)
quarantine_id = quarantine["quarantine_obj"].add(self.queueid, self.mailfrom, recipients, self.subject, self.fp,
quarantine["subgroups"], quarantine["named_subgroups"])
except RuntimeError as e:
self.logger.error("{}: unable to add to quarantine '{}': {}".format(self.queueid, quarantine["name"], e))
return Milter.TEMPFAIL
@@ -222,7 +227,8 @@ class QuarantineMilter(Milter.Base):
# notify
self.logger.info("{}: sending notification for quarantine '{}' to: {}".format(self.queueid, quarantine["name"], ", ".join(recipients)))
try:
quarantine["notification_obj"].notify(self.queueid, quarantine_id, self.subject, self.mailfrom, recipients, fp=self.fp)
quarantine["notification_obj"].notify(self.queueid, quarantine_id, self.subject, self.mailfrom, recipients, self.fp,
quarantine["subgroups"], quarantine["named_subgroups"])
except RuntimeError as e:
self.logger.error("{}: unable to send notification for quarantine '{}': {}".format(self.queueid, quarantine["name"], e))
return Milter.TEMPFAIL
@@ -316,7 +322,7 @@ def generate_milter_config(configtest=False, config_files=[]):
# pre-compile regex
logger.debug("{}: compiling regex '{}'".format(quarantine_name, config["regex"]))
config["regex_compiled"] = re.compile(config["regex"])
config["regex_compiled"] = re.compile(config["regex"], re.MULTILINE + re.DOTALL)
# create quarantine instance
quarantine_type = config["quarantine_type"].lower()

View File

@@ -33,7 +33,7 @@ class BaseNotification(object):
self.config = config
self.logger = logging.getLogger(__name__)
def notify(self, queueid, quarantine_id, subject, mailfrom, recipients, fp, synchronous=False):
def notify(self, queueid, quarantine_id, subject, mailfrom, recipients, fp, subgroups=None, named_subgroups=None, synchronous=False):
fp.seek(0)
pass
@@ -224,9 +224,9 @@ class EMailNotification(BaseNotification):
return soup
def notify(self, queueid, quarantine_id, subject, mailfrom, recipients, fp, synchronous=False):
def notify(self, queueid, quarantine_id, subject, mailfrom, recipients, fp, subgroups=None, named_subgroups=None, synchronous=False):
"Notify recipients via email."
super(EMailNotification, self).notify(queueid, quarantine_id, subject, mailfrom, recipients, fp, synchronous)
super(EMailNotification, self).notify(queueid, quarantine_id, subject, mailfrom, recipients, fp, subgroups, named_subgroups, synchronous)
# extract html text from email
self.logger.debug("{}: extraction email text from original email".format(queueid))
@@ -244,21 +244,29 @@ class EMailNotification(BaseNotification):
# sanitizing email text of original email
sanitized_text = self.sanitize(queueid, soup)
# escape possible html entities in subject
subject = escape(subject)
# sending email notifications
for recipient in recipients:
self.logger.debug("{}: generating notification email for '{}'".format(queueid, recipient))
self.logger.debug("{}: parsing email template".format(queueid))
htmltext = self.template.format( \
EMAIL_HTML_TEXT=sanitized_text, \
EMAIL_FROM=escape(mailfrom), \
EMAIL_TO=escape(recipient), \
EMAIL_SUBJECT=subject, \
EMAIL_QUARANTINE_ID=quarantine_id
)
# generate dict containing all template variables
variables = {
"EMAIL_HTML_TEXT": sanitized_text,
"EMAIL_FROM": escape(mailfrom),
"EMAIL_TO": escape(recipient),
"EMAIL_SUBJECT": escape(subject),
"EMAIL_QUARANTINE_ID": quarantine_id
}
if subgroups:
number = 0
for subgroup in subgroups:
variables["SUBGROUP_{}".format(number)] = escape(subgroup)
if named_subgroups:
for key, value in named_subgroups.items(): named_subgroups[key] = escape(value)
variables.update(named_subgroups)
# parse template
htmltext = self.template.format(**variables)
msg = MIMEMultipart('alternative')
msg["Subject"] = self.subject

View File

@@ -33,7 +33,7 @@ class BaseQuarantine(object):
self.config = config
self.logger = logging.getLogger(__name__)
def add(self, queueid, mailfrom, recipients, subject, fp):
def add(self, queueid, mailfrom, recipients, subject, fp, subgroups=None, named_subgroups=None):
"Add email to quarantine."
fp.seek(0)
return ""
@@ -109,9 +109,9 @@ class FileQuarantine(BaseQuarantine):
except IOError as e:
raise RuntimeError("unable to remove data file: {}".format(e))
def add(self, queueid, mailfrom, recipients, subject, fp):
def add(self, queueid, mailfrom, recipients, subject, fp, subgroups=None, named_subgroups=None):
"Add email to file quarantine and return quarantine-id."
super(FileQuarantine, self).add(queueid, mailfrom, recipients, subject, fp)
super(FileQuarantine, self).add(queueid, mailfrom, recipients, subject, fp, subgroups, named_subgroups)
quarantine_id = "{}_{}".format(datetime.now().strftime("%Y%m%d%H%M%S"), queueid)
# save mail
@@ -123,7 +123,9 @@ class FileQuarantine(BaseQuarantine):
"recipients": recipients,
"subject": subject,
"date": timegm(gmtime()),
"queue_id": queueid
"queue_id": queueid,
"subgroups": subgroups,
"named_subgroups": named_subgroups
}
try:
self._save_metafile(quarantine_id, metadata)
@@ -223,7 +225,8 @@ class FileQuarantine(BaseQuarantine):
datafile = os.path.join(self.directory, quarantine_id)
try:
with open(datafile, "rb") as fp:
self.config["notification_obj"].notify(metadata["queue_id"], quarantine_id, metadata["subject"], metadata["mailfrom"], recipients, fp, synchronous=True)
self.config["notification_obj"].notify(metadata["queue_id"], quarantine_id, metadata["subject"], metadata["mailfrom"], recipients, fp,
metadata["subgroups"], metadata["named_subgroups"], synchronous=True)
except IOError as e:
raise(RuntimeError("unable to read data file: {}".format(e)))