Add option to strip images from emails

This commit is contained in:
2019-10-21 18:48:04 +02:00
parent 228be9f4be
commit f0f2c6b742
3 changed files with 46 additions and 11 deletions

View File

@@ -87,7 +87,7 @@ The following configuration options are optional in each quarantine section:
* **{EMAIL_QUARANTINE_ID}** * **{EMAIL_QUARANTINE_ID}**
Quarantine-ID of the original e-mail if available, empty otherwise. Quarantine-ID of the original e-mail if available, empty otherwise.
* **{EMAIL_HTML_TEXT}** * **{EMAIL_HTML_TEXT}**
Sanitized version of the e-mail text part of the original e-mail. Only harmless HTML tags and attributes are included. Images are replaced with the image set by notification_email_replacement_img option. Sanitized version of the e-mail text part of the original e-mail. Only harmless HTML tags and attributes are included. Images are optionally stripped or replaced with the image set by notification_email_replacement_img option.
Some template variables are only available if the regex of the matching quarantine contains subgroups or named subgroups (python syntax). This is useful to include information (e.g. virus names, spam points, ...) of the matching header within the notification. Some template variables are only available if the regex of the matching quarantine contains subgroups or named subgroups (python syntax). This is useful to include information (e.g. virus names, spam points, ...) of the matching header within the notification.
The following dynamic template variables are available: The following dynamic template variables are available:
@@ -105,12 +105,17 @@ The following configuration options are optional in each quarantine section:
Notification e-mail subject. All e-mail template variable described above is usable. Notification e-mail subject. All e-mail template variable described above is usable.
* **notification_email_template** * **notification_email_template**
Path to the notification e-mail template. It is hold in memory during runtime. Path to the notification e-mail template. It is hold in memory during runtime.
* **notification_email_replacement_img**
Path to the image to replace images in e-mails. It is hold in memory during runtime. Leave it empty to disable.
* **notification_email_embedded_imgs** * **notification_email_embedded_imgs**
Comma-separated list of images to embed into the notification e-mail. The Content-ID of each image will be set to the filename, so you can reference it from the e-mail template. All images are hold in memory during runtime. Comma-separated list of images to embed into the notification e-mail. The Content-ID of each image will be set to the filename, so you can reference it from the e-mail template. All images are hold in memory during runtime.
Leave empty to disable. Leave empty to disable.
The following configuration options are optional for this notification type:
* **notification_email_strip_images**
Enable to strip images from e-mails. This option superseeds notification_email_replacement_img.
* **notification_email_replacement_img**
Path to an image to replace images in e-mails. It is hold in memory during runtime.
### Actions ### Actions
Every quarantine responds with a milter-action if an e-mail header matches the configured regular expression. Please think carefully what you set here or your MTA will do something you do not want. Every quarantine responds with a milter-action if an e-mail header matches the configured regular expression. Please think carefully what you set here or your MTA will do something you do not want.
The following actions are available: The following actions are available:

View File

@@ -117,10 +117,15 @@ notification_email_subject = Spam Quarantine Notification
# #
notification_email_template = templates/notification.template notification_email_template = templates/notification.template
# Option: notification_email_strip_images
# Notes: Optionally enable this option to strip img tags from emails.
# Values: [ TRUE|ON|YES|FALSE|OFF|NO ]
#
notification_email_strip_images = False
# Option: notification_email_replacement_img # Option: notification_email_replacement_img
# Notes: Set the path to the replacement image for img tags within emails. # Notes: Optionally set the path to a replacement image for img tags within emails.
# A relative path to this config file can be used. # A relative path to this config file can be used.
# This option is needed by notification type 'email'.
# Values: [ IMAGE_PATH ] # Values: [ IMAGE_PATH ]
# #
notification_email_replacement_img = templates/removed.png notification_email_replacement_img = templates/removed.png

View File

@@ -119,7 +119,6 @@ class EMailNotification(BaseNotification):
"notification_email_from", "notification_email_from",
"notification_email_subject", "notification_email_subject",
"notification_email_template", "notification_email_template",
"notification_email_replacement_img",
"notification_email_embedded_imgs"]: "notification_email_embedded_imgs"]:
if option not in self.config.keys() and option in self.global_config.keys(): if option not in self.config.keys() and option in self.global_config.keys():
self.config[option] = self.global_config[option] self.config[option] = self.global_config[option]
@@ -128,6 +127,18 @@ class EMailNotification(BaseNotification):
"mandatory option '{}' not present in config section '{}' or 'global'".format( "mandatory option '{}' not present in config section '{}' or 'global'".format(
option, self.quarantine_name)) option, self.quarantine_name))
# check if optional config options are present in config
defaults = {
"notification_email_replacement_img": "",
"notification_email_strip_images": "false"
}
for option in defaults.keys():
if option not in config.keys() and \
option in global_config.keys():
config[option] = global_config[option]
if option not in config.keys():
config[option] = defaults[option]
self.smtp_host = self.config["smtp_host"] self.smtp_host = self.config["smtp_host"]
self.smtp_port = self.config["smtp_port"] self.smtp_port = self.config["smtp_port"]
self.mailfrom = self.config["notification_email_envelope_from"] self.mailfrom = self.config["notification_email_envelope_from"]
@@ -160,13 +171,20 @@ class EMailNotification(BaseNotification):
except ValueError as e: except ValueError as e:
raise RuntimeError("error parsing template: {}".format(e)) raise RuntimeError("error parsing template: {}".format(e))
strip_images = self.config["notification_email_strip_images"].strip().upper()
if strip_images in ["TRUE", "ON", "YES"]:
self.strip_images = True
elif strip_images in ["FALSE", "OFF", "NO"]:
self.strip_images = False
else:
raise RuntimeError("error parsing notification_email_strip_images: unknown value")
# read email replacement image if specified # read email replacement image if specified
replacement_img_path = self.config["notification_email_replacement_img"].strip( replacement_img = self.config["notification_email_replacement_img"].strip()
) if not strip_images and replacement_img:
if replacement_img_path:
try: try:
self.replacement_img = MIMEImage( self.replacement_img = MIMEImage(
open(replacement_img_path, "rb").read()) open(replacement_img, "rb").read())
except IOError as e: except IOError as e:
raise RuntimeError( raise RuntimeError(
"error reading replacement image: {}".format(e)) "error reading replacement image: {}".format(e))
@@ -307,7 +325,14 @@ class EMailNotification(BaseNotification):
# replace picture sources # replace picture sources
image_replaced = False image_replaced = False
if self.replacement_img: if self.strip_images:
for element in soup("img"):
if "src" in element.attrs.keys():
self.logger.debug(
"{}: removing image: {}".format(
queueid, element["src"]))
element.extract()
elif self.replacement_img:
for element in soup("img"): for element in soup("img"):
if "src" in element.attrs.keys(): if "src" in element.attrs.keys():
self.logger.debug( self.logger.debug(