1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
# spamprox - The barely SMTP-capable spam proxy
spamprox is a really stupid proxy that just about allows
[Postfix](http://www.postfix.org/) to use
[SpamAssassin](https://spamassassin.apache.org/) as a
[before-queue content filter](http://www.postfix.org/SMTPD_PROXY_README.html).
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](https://manpages.debian.org/stable/dash/dash.1.en.html#ENVIRONMENT)
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](https://manpages.debian.org/stable/systemd/systemd.socket.5.en.html),
or an `(x)inetd`
[service](https://manpages.debian.org/stable/xinetd/xinetd.conf.5.en.html).
Either that, or implement the
[spampd](https://manpages.debian.org/stable/spampd/spampd.8.en.html#To_Do) 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.
|