Background & Requirements
I’ve found a number of reference docs and Q&A post relating to this topic but I’ve not been able to figure out a key area of the design.
I would like to reject an inbound email based on a custom analysis algorithm – simply I have a python script that does the analysis and I’m currently testing by invoking it as a mail filter from Gnome Evolution. This all seems to work more-or-less as expected. Seems to be a couple of nuances with return codes in python vs. the interpretation by Evolutions mail filter system but otherwise operational.
At this stage not tied to a technology or system other than it must be open source. Ideally it should run on Debian (or Ubuntu) so Postfix seems to be the best fit.
The Problem Area
I’ve been looking at gateways et al such as Postfix in order to design an integration that works on a more autonomous level – and to prevent the need to waste time filtering email in inboxes. I can see the lightweight before queue filters (for example here) and I can see how to call a script from these hooks e.g. here, but not acquire any return codes from the script.
What I can’t seem to find in the documentation is how you would a apply a result code / return code from the script to Postfix in order for it to determine whether or not to allow or reject the message.
Note that the solution relies on being able to reject an email message, not discard it (for reasons I unfortunately cannot go into here). I thought about a cron job that inspects a list of collated data items collected from email added to the queue, and appending more filters to the Postfix configurations automatically. This only solves part of the problem and means something will run on the server even if there is no new email.
TL;DR So my questions are:
- How can I call a script from the MTA and get the script / call result? e.g. call
scan.pyand get either a
- What mechanism in Postfix (or other similar open source system) should I refer to in documentation to then bind this result to an action?
This could probably be achieved by setting up your script as a milter – see MILTER_README. It might be a non-trivial task though. Maybe worth seeing if someone else has already implemented something good enough for your purpose e.g. here.