diff --git a/docker/postfix/rootfs/init.sh b/docker/postfix/rootfs/init.sh index 337e57fd..ca5ca870 100755 --- a/docker/postfix/rootfs/init.sh +++ b/docker/postfix/rootfs/init.sh @@ -1,56 +1,60 @@ #!/bin/bash set -e if [[ -f ${SSL_CERTIFICATE} ]]; then cat ${SSL_CERTIFICATE} ${SSL_CERTIFICATE_FULLCHAIN} ${SSL_CERTIFICATE_KEY} > /etc/pki/tls/private/postfix.pem chown postfix:mail /etc/pki/tls/private/postfix.pem chmod 655 /etc/pki/tls/private/postfix.pem fi chown -R postfix:mail /var/lib/postfix chown -R postfix:mail /var/spool/postfix /usr/sbin/postfix set-permissions sed -i -r \ -e "s|APP_SERVICES_DOMAIN|$APP_SERVICES_DOMAIN|g" \ -e "s|SERVICES_PORT|$SERVICES_PORT|g" \ /etc/saslauthd.conf /usr/sbin/saslauthd -m /run/saslauthd -a httpform -d & # If host mounting /var/spool/postfix, we need to delete old pid file before # starting services rm -f /var/spool/postfix/pid/master.pid /usr/libexec/postfix/aliasesdb /usr/libexec/postfix/chroot-update sed -i -r \ -e "s|LMTP_DESTINATION|${LMTP_DESTINATION:?"env required"}|g" \ -e "s|APP_DOMAIN|${APP_DOMAIN:?"env required"}|g" \ -e "s|MYNETWORKS|${MYNETWORKS:?"env required"}|g" \ -e "s|AMAVIS_HOST|${AMAVIS_HOST:?"env required"}|g" \ /etc/postfix/main.cf sed -i -r \ -e "s|MYNETWORKS|${MYNETWORKS:?"env requried"}|g" \ -e "s|AMAVIS_HOST|${AMAVIS_HOST:?"env requried"}|g" \ /etc/postfix/master.cf sed -i -r \ -e "s|SERVICES_HOST|http://$APP_SERVICES_DOMAIN:$SERVICES_PORT|g" \ /usr/libexec/postfix/kolab_policy* +sed -i -r \ + -e "s|SERVICES_HOST|http://$APP_SERVICES_DOMAIN:$SERVICES_PORT|g" \ + /usr/libexec/postfix/kolab_contentfilter* + sed -i -r \ -e "s|DB_HOST|${DB_HOST:?"env required"}|g" \ -e "s|DB_USERNAME|${DB_USERNAME:?"env required"}|g" \ -e "s|DB_PASSWORD|${DB_PASSWORD:?"env required"}|g" \ -e "s|DB_DATABASE|${DB_DATABASE:?"env required"}|g" \ /etc/postfix/sql/* # echo "/$APP_DOMAIN/ lmtp:$LMTP_DESTINATION" >> /etc/postfix/transport # postmap /etc/postfix/transport /usr/sbin/postfix check exec /usr/sbin/postfix -c /etc/postfix start-fg diff --git a/docker/postfix/rootfs/usr/libexec/postfix/kolab_contentfilter_cli.py b/docker/postfix/rootfs/usr/libexec/postfix/kolab_contentfilter_cli.py index e81932c7..2029e54e 100755 --- a/docker/postfix/rootfs/usr/libexec/postfix/kolab_contentfilter_cli.py +++ b/docker/postfix/rootfs/usr/libexec/postfix/kolab_contentfilter_cli.py @@ -1,68 +1,103 @@ #!/usr/bin/python3 # Test like so: cat test.mime | /usr/libexec/postfix/kolab_contentfilter_cli.py -f admin@kolab.local -- noreply@kolab.local -# from email import Parser -# import smtplib import sys import logging +import requests from subprocess import Popen, PIPE -SUCCESS = 0 +EX_SUCCESS = 0 # Postfix will bounce and not retry -BOUNCE = 69 -# Postfix will retry -TEMPFAIL = 75 +EX_UNAVAILABLE = 69 +# Postfix will retry via deferred queue +EX_TEMPFAIL = 75 verbose = True def get_args(): try: if verbose: logging.debug("ARGV : %r" % sys.argv) cli_from = sys.argv[2].lower() cli_to = sys.argv[4:] return (cli_from, cli_to) except Exception: if verbose: logging.error("Invalid to / from : %r" % sys.argv) - sys.exit(BOUNCE) + sys.exit(EX_UNAVAILABLE) def reinject(content, sender, to): command = ["/usr/sbin/sendmail", "-G", "-i", "-f", sender] + to stdout = '' stderr = '' retval = 0 try: process = Popen(command, stdin=PIPE) (stdout, stderr) = process.communicate(content.encode()) retval = process.wait() if retval == 0: if verbose: logging.debug("Mail resent via sendmail, stdout: %s, stderr: %s" % (stdout, stderr)) - return SUCCESS + return EX_SUCCESS else: raise Exception("retval not zero - %s" % retval) except Exception as e: print(f"Error re-injecting via {command}") if verbose: logging.error("Exception while re-injecting mail: %s -- stdout:%s, stderr:%s, retval: %s" % (e, stdout, stderr, retval)) logging.error(f"Commandline used: {command}") - return TEMPFAIL + return EX_TEMPFAIL -(cli_from, cli_to) = get_args() +if __name__ == "__main__": + (cli_from, cli_to) = get_args() -if verbose: - logging.basicConfig(level=logging.DEBUG, - format='%(asctime)s %(levelname)s %(message)s', - filename='/tmp/content-filter.log', - filemode='a') + if verbose: + logging.basicConfig(level=logging.DEBUG, + format='%(asctime)s %(levelname)s %(message)s', + filename='/tmp/content-filter.log', + filemode='a') + content = ''.join(sys.stdin.readlines()) -# logging.debug("From : %s, to : %r" % (cli_from, cli_to)) + URL = 'SERVICES_HOST/api/webhooks/policy/mail/filter' + try: + response = requests.post( + URL + f"?recipient={cli_to}", + data=content, + verify=True + ) -content = ''.join(sys.stdin.readlines()) -#TODO send content to kolab4 + if response.status_code == 201: + if verbose: + logging.warning("No changes requested, reinjecting original content.") + print("Unmodified email") + elif response.status_code == 200: + if verbose: + logging.warning("Updating content.") + print("Modified email") + content = response.text + elif response.status_code == 460: + if verbose: + logging.warning("Rejecting email.") + print("Rejecting email") + sys.exit(EX_UNAVAILABLE) + elif response.status_code == 461: + if verbose: + logging.warning("Ignoring email.") + print("Dropping email") + sys.exit(EX_SUCCESS) + else: + if verbose: + logging.warning(f"Unknown status code {response.status_code}.") + print("Unknown status code") + sys.exit(EX_TEMPFAIL) -sys.exit(reinject(content, cli_from, cli_to)) + # pylint: disable=broad-except + except Exception: + if verbose: + logging.warning("Request failed.") + print("Request failed") + sys.exit(EX_TEMPFAIL) + sys.exit(reinject(content, cli_from, cli_to))