diff --git a/docker/postfix/rootfs/etc/postfix/master.cf b/docker/postfix/rootfs/etc/postfix/master.cf index 48735fa4..101bb090 100644 --- a/docker/postfix/rootfs/etc/postfix/master.cf +++ b/docker/postfix/rootfs/etc/postfix/master.cf @@ -1,172 +1,186 @@ # Postfix master process configuration file. For details on the format # of the file, see the master(5) manual page (command: "man 5 master"). # Do not forget to execute "postfix reload" after editing this file. # ============================================================================== # service type private unpriv chroot wakeup maxproc command # (yes) (yes) (yes) (never) (100) + args # ============================================================================== postlog unix-dgram n - n - 1 postlogd # Inbound, port 25, no tls 10025 inet n - n - - smtpd + -o content_filter=smtp-amavis:[AMAVIS_HOST]:13024 + -o cleanup_service_name=cleanup_inbound # Internal Submission, no tls, no starttls 10587 inet n - - - - smtpd -o syslog_name=postfix/submission -o cleanup_service_name=cleanup_submission -o content_filter=smtp-amavis:[AMAVIS_HOST]:13026 -o smtpd_sasl_auth_enable=yes -o smtpd_client_restrictions=permit_sasl_authenticated,reject -o smtpd_data_restrictions=$submission_data_restrictions -o smtpd_recipient_restrictions=$submission_recipient_restrictions -o smtpd_sender_restrictions=$submission_sender_restrictions -o smtpd_client_restrictions=$submission_client_restrictions -o smtpd_helo_restrictions=$submission_helo_restrictions -o smtpd_helo_required=yes -o smtpd_peername_lookup=no + +# External submission, starttls +0.0.0.0:11587 inet n - n - - smtpd + -o cleanup_service_name=cleanup_submission + -o syslog_name=postfix/submission + -o content_filter=smtp-amavis:[AMAVIS_HOST]:13026 + #-o smtpd_tls_security_level=encrypt + -o smtpd_sasl_auth_enable=yes + -o smtpd_sasl_authenticated_header=yes + -o smtpd_client_restrictions=permit_sasl_authenticated,reject + -o smtpd_data_restrictions=$submission_data_restrictions + -o smtpd_recipient_restrictions=$submission_recipient_restrictions + -o smtpd_sender_restrictions=$submission_sender_restrictions + +# External submission, ssl +0.0.0.0:11465 inet n - n - - smtpd + -o cleanup_service_name=cleanup_submission + -o rewrite_service_name=rewrite_submission + -o syslog_name=postfix/smtps + -o content_filter=smtp-amavis:[AMAVIS_HOST]:13026 + -o mydestination= + -o local_recipient_maps= + -o relay_domains= + -o relay_recipient_maps= + -o smtpd_tls_security_level=encrypt + -o smtpd_tls_wrappermode=yes + -o smtpd_sasl_auth_enable=yes + -o smtpd_sasl_authenticated_header=yes + -o smtpd_client_restrictions=permit_sasl_authenticated,reject + -o smtpd_sender_restrictions=$submission_sender_restrictions + -o smtpd_recipient_restrictions=$submission_recipient_restrictions + -o smtpd_data_restrictions=$submission_data_restrictions + pickup fifo n - n 60 1 pickup + # This avoids that we have an endless loop after our script content filter + -o content_filter= cleanup unix n - n - 0 cleanup +cleanup_inbound unix n - n - 0 cleanup -o header_checks=regexp:/etc/postfix/header_checks.inbound -o mime_header_checks=regexp:/etc/postfix/header_checks.inbound cleanup_submission unix n - n - 0 cleanup -o header_checks=regexp:/etc/postfix/header_checks.submission -o mime_header_checks=regexp:/etc/postfix/header_checks.submission cleanup_internal unix n - n - 0 cleanup -o header_checks=regexp:/etc/postfix/header_checks.internal -o mime_header_checks=regexp:/etc/postfix/header_checks.internal qmgr fifo n - n 300 1 qmgr tlsmgr unix - - n 1000? 1 tlsmgr rewrite unix - - n - - trivial-rewrite bounce unix - - n - 0 bounce defer unix - - n - 0 bounce trace unix - - n - 0 bounce verify unix - - n - 1 verify flush unix n - n 1000? 0 flush proxymap unix - - n - - proxymap proxywrite unix - - n - 1 proxymap smtp unix - - n - - smtp relay unix - - n - - smtp showq unix n - n - - showq error unix - - n - - error retry unix - - n - - error discard unix - - n - - discard local unix - n n - - local virtual unix - n n - - virtual lmtp unix - - n - - lmtp anvil unix - - n - 1 anvil scache unix - - n - 1 scache # Filter email through Amavisd smtp-amavis unix - - n - 3 smtp -o smtp_data_done_timeout=1800 -o disable_dns_lookups=yes -o smtp_send_xforward_command=yes -o max_use=20 # -o smtp_bind_address=127.0.0.1 # Listener to re-inject email from Amavisd into Postfix 0.0.0.0:13025 inet n - n - 100 smtpd -o cleanup_service_name=cleanup_internal -o local_recipient_maps= -o relay_recipient_maps= - -o content_filter= + # To disable the kolab content filter, set an empty content filter here. + -o content_filter=policy_mailfilter:dummy + # -o content_filter= -o smtpd_restriction_classes= -o smtpd_client_restrictions= -o smtpd_helo_restrictions= -o smtpd_sender_restrictions= -o smtpd_recipient_restrictions=permit_mynetworks,reject -o mynetworks=MYNETWORKS -o smtpd_authorized_xforward_hosts=MYNETWORKS -o syslog_name=postfix/amavis # Filter email through Wallace # smtp-wallace unix - - n - 3 smtp # -o default_destination_recipient_limit=1 # -o smtp_data_done_timeout=1800 # -o disable_dns_lookups=yes # -o smtp_send_xforward_command=yes # -o max_use=20 # Listener to re-inject email from Wallace into Postfix # 127.0.0.1:10028 inet n - n - 100 smtpd # -o cleanup_service_name=cleanup_internal # -o content_filter= # -o local_recipient_maps= # -o relay_recipient_maps= # -o smtpd_restriction_classes= # -o smtpd_client_restrictions= # -o smtpd_helo_restrictions= # -o smtpd_sender_restrictions= # -o smtpd_recipient_restrictions=permit_mynetworks,reject # -o mynetworks=127.0.0.0/8 # -o smtpd_authorized_xforward_hosts=127.0.0.0/8 # Filter email through Amavisd # amavis unix - - n - 3 smtp # -o disable_dns_lookups=yes # -o max_use=20 # -o smtp_bind_address=127.0.0.1 # -o smtp_data_done_timeout=1800 # -o smtp_send_xforward_command=yes # -o smtp_tls_security_level=none # Reinjection from amavis # 127.0.0.1:10025 inet n - n - 100 smtpd # -o cleanup_service_name=cleanup_outbound # -o content_filter= # -o local_recipient_maps= # -o mydestination= # -o mynetworks=127.0.0.0/8 # -o relay_domains= # -o relay_recipient_maps= # -o smtpd_authorized_xforward_hosts=127.0.0.0/8 # -o smtpd_restriction_classes= # -o smtpd_client_restrictions= # -o smtpd_data_restrictions= # -o smtpd_helo_restrictions= # -o smtpd_sender_restrictions= # -o smtpd_recipient_restrictions=permit_mynetworks,reject # -o syslog_name=postfix/amavis # Outbound policy_ratelimit unix - n n - - spawn user=nobody argv=/usr/libexec/postfix/kolab_policy_ratelimit # Inbound policy_greylist unix - n n - - spawn user=nobody argv=/usr/libexec/postfix/kolab_policy_greylist # Inbound policy_spf unix - n n - - spawn user=nobody argv=/usr/libexec/postfix/kolab_policy_spf -# External submission, starttls -0.0.0.0:11587 inet n - n - - smtpd - -o cleanup_service_name=cleanup_submission - -o syslog_name=postfix/submission - -o content_filter=smtp-amavis:[AMAVIS_HOST]:13026 - #-o smtpd_tls_security_level=encrypt - -o smtpd_sasl_auth_enable=yes - -o smtpd_sasl_authenticated_header=yes - -o smtpd_client_restrictions=permit_sasl_authenticated,reject - -o smtpd_data_restrictions=$submission_data_restrictions - -o smtpd_recipient_restrictions=$submission_recipient_restrictions - -o smtpd_sender_restrictions=$submission_sender_restrictions +# Mailfilter via commandline, to be reinjected via sendmail. +policy_mailfilter unix - n n - 10 pipe + flags=Rq user=nobody null_sender= + argv=/usr/libexec/postfix/kolab_contentfilter_cli.py -f ${sender} -- ${recipient} -# External submission, ssl -0.0.0.0:11465 inet n - n - - smtpd - -o cleanup_service_name=cleanup_submission - -o rewrite_service_name=rewrite_submission - -o syslog_name=postfix/smtps - -o content_filter=smtp-amavis:[AMAVIS_HOST]:13026 - -o mydestination= - -o local_recipient_maps= - -o relay_domains= - -o relay_recipient_maps= - -o smtpd_tls_security_level=encrypt - -o smtpd_tls_wrappermode=yes - -o smtpd_sasl_auth_enable=yes - -o smtpd_sasl_authenticated_header=yes - -o smtpd_client_restrictions=permit_sasl_authenticated,reject - -o smtpd_sender_restrictions=$submission_sender_restrictions - -o smtpd_recipient_restrictions=$submission_recipient_restrictions - -o smtpd_data_restrictions=$submission_data_restrictions diff --git a/docker/postfix/rootfs/reload.sh b/docker/postfix/rootfs/reload.sh new file mode 100755 index 00000000..41ed5c59 --- /dev/null +++ b/docker/postfix/rootfs/reload.sh @@ -0,0 +1,5 @@ +#!/bin/bash +set -e + +postfix check +postfix reload diff --git a/docker/postfix/rootfs/usr/libexec/postfix/kolab_contentfilter_cli.py b/docker/postfix/rootfs/usr/libexec/postfix/kolab_contentfilter_cli.py new file mode 100755 index 00000000..e81932c7 --- /dev/null +++ b/docker/postfix/rootfs/usr/libexec/postfix/kolab_contentfilter_cli.py @@ -0,0 +1,68 @@ +#!/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 +from subprocess import Popen, PIPE + +SUCCESS = 0 +# Postfix will bounce and not retry +BOUNCE = 69 +# Postfix will retry +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) + + +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 + 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 + + +(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') + + +# logging.debug("From : %s, to : %r" % (cli_from, cli_to)) + +content = ''.join(sys.stdin.readlines()) +#TODO send content to kolab4 + +sys.exit(reinject(content, cli_from, cli_to)) +