spamprox - The barely SMTP-capable spam proxy
spamprox is a really stupid proxy that just about allows Postfix to use SpamAssassin as a before-queue content filter.
It speaks enough SMTP
- to send a "220" greeting
- to respond to everything up to a "DATA" command with "250 Ok"
- to respond to a "DATA" command with "354" and then wait for the terminating "."
- to pass the resulting email to SpamAssassin and respond with a "250", "554" or "TODO" result
- to respond to a "QUIT" with a "221 Bye"
- to respond to anything else between "DATA" and "QUIT" with "503 Bad sequence of commands"
Fortunately Postfix is already doing general validation on the incoming mail from the internet, so we should be able to trust that the input follows a consistent SMTP command order that we can predict, and not have to worry too much about being subverted from that direction.
Still, this should probably be written in python3
, or some other language with
a proper SMTP library. But this was my 4th attempted approach at getting Postfix
to be able to reject (rather than bounce) spammy emails and I was in the mood
for an ugly hack. Also, when I started I thought I'd just be able to slurp in
the whole command stream and pass a single "250"/"554" back at the end. I
figured the whole thing would be about 10-15 lines long, which is OK for a
shell script.
I didn't realise that Postfix wanted a proper SMTP conversation with the proxy, and by the time I did realise it I was the first 90% of the way there. I probably should have realised it from the start, but hey, learn something new every day. Heck, when I realised that I needed to clear IFS (the Input Field Separators special variable) to get the thing to work, that should have been a big flag to turn around and rewrite it in another language, but at that point I was the second 90% of the way there and I didn't want to throw away the work...
Oh yeah - writing it in a langauge that allows it to run as a proper daemon
might be a good idea too. Instead of it just being a script that runs off of a
systemd
socket unit,
or an (x)inetd
service.
Either that, or implement the spampd TODO of "Add configurable option for rejecting mail outright based on spam score." so I can just use that (as I at one time had planned to) instead.