#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Label a message (add a header) according to certain rules # Rules are stored in a file with the format # field:match:folder:priority import logging from logging.handlers import SysLogHandler from logging.handlers import RotatingFileHandler import sys import pprint import re import os import io import email from email.message import EmailMessage from email.parser import HeaderParser from subprocess import Popen, PIPE messagecontent="".join(sys.stdin.readlines()) log = logging.getLogger() log.addHandler(SysLogHandler()) handler = RotatingFileHandler('/var/spool/filter/labeler.log', maxBytes=1000000, backupCount=5) formatter = logging.Formatter('%(asctime)s %(name)-12s %(levelname)-8s %(message)s') handler.setFormatter(formatter) log.addHandler(handler) log.setLevel(logging.DEBUG) log.info('Writing {} bytes of message in /var/spool/filter/last_message.eml...'.format(len(messagecontent))) if not os.path.exists('/var/spool/filter'): log.error('Path /var/spool/filter not found.') else: with io.open('/var/spool/filter/last_message.eml', 'w') as fp: try: fp.write(messagecontent) except UnicodeEncodeError as e: log.error('There was an Unicode encode error writting file. {}'.format(e)) parser = HeaderParser() log.debug('Obtaining headers from message...') msg = email.message_from_string(messagecontent) headers = parser.parsestr(messagecontent) log.debug('Headers: {}'.format(", ".join(headers.keys()))) log.debug('From: {}'.format(headers.get('From',''))) log.debug('To: {}'.format(headers.get('To',''))) log.debug('Subject: {}'.format(headers.get('Subject',''))) if 'Message-ID' not in headers.keys(): if 'Message-Id' not in headers.keys(): log.warning('Malformed header (no message-id).') else: log.debug('Processing message with ID: {}'.format(headers['Message-Id'])) else: log.debug('Processing message with ID: {}'.format(headers['Message-ID'])) with open('/etc/postfix/filter_rules.conf','r') as fp: strrules = fp.read() log.debug('Reading general filter rules...') rules = list() for rule in strrules.split('\n'): if rule != "": lrule = rule.split(':') field = lrule[0] match = lrule[1] folder = lrule[2] priority = lrule[4] rules.append(lrule) if field in headers.keys(): m = re.search(match, headers[field]) if m is None: a = 1 else: msg['X-AD-Label'] = "{}:{}".format(folder, priority) log.info('Added label "{}" due to rule "{}"'.format(folder, rule)) messagecontent=msg.as_string() if not os.path.exists('/var/spool/filter'): log.error('Path /var/spool/filter not found.') else: log.info('Writing {} bytes of message in /var/spool/filter/last_message_altered.eml...'.format(len(messagecontent))) with open('/var/spool/filter/last_message_altered.eml', 'w', encoding='utf8') as fp: fp.write(messagecontent) args = list() args = ["/usr/sbin/sendmail"] + sys.argv args.pop(1) log.debug('Running sendmail with command line: {}'.format(' '.join(args))) if not os.path.exists("/usr/sbin/sendmail"): log.error('Not found sendmail in "/usr/sbin/sendmail"') else: p = Popen(args, stdin=PIPE) p.communicate(bytearray(messagecontent, 'utf-8'))