Exim SpamAssassin at SMTP time
What's that?
mail from: merlin@gandalf
250 OK
rcpt to: merlin@gandalf
250 Accepted
data
354 Enter message, ending with "." on a line by itself
From: merlin@gandalf
To: merlin@gandalf
Subject: $$$ Make Money Fast $$$ !!!
viagra 100% GARANTEE AMAZING FULL REFUND
This is not spam
.
550-Heuristics guessed that this message was spam:
550 hits=14.8 required=1.0 trigger=12.0
An example of teergrub would return this instead
data
354 Enter message, ending with "." on a line by itself
(...)
body SEE_FOR_YOURSELF /See (?:for|it) yourself\b/i
describe SEE_FOR_YOURSELF See for yourself
body ORDER_NOW /\border (?:now|soon|fast|quickly|while)\b/i
describe ORDER_NOW Encourages you to waste no time in ordering
.
451- wait for more output (hits=28.2 required=7.0 trigger=25.0)
451- wait for more output (hits=28.2 required=7.0 trigger=25.0)
451- wait for more output (hits=28.2 required=7.0 trigger=25.0)
(... one line every 10 secs, 15 minutes elapse ...)
450 How a bout you try again later for a little more teergrub? (hits=28.2 required=7.0 trigger=25.0)
The idea here is to stall and waste the resources of the remote sender
Why?
SpamAssassin can be run inside exim after the mail has been accepted, as shown
here,
but if you're not going to use my patch and you just want to run SA as an exim
transport,
this
version is recommended
Now, while this will work, we can do better, hence the reason for my code
(just to make things clear, you do not want to run both my code, and dman's
transports. It'd work, but you'd be scanning the message twice)
The reason why I wanted SpamAssassin in local scan is that I don't want to
accept the damn spam in the first place.
- While my code lets you do that, I don't like to send mails to the bit
bucket, so you need to bounce them.
- Once you accept the spam, you can't bounce it half the time, or you
bounce it to an innocent whose Email was forged as an envelope sender
(some spam even forges the bounce address to you)
- If I refuse spam at SMTP time, it will remove the spam addresses from at
least a few lists (they gotta clean their lists eventually otherwise they'd
spend more time Emailing dead addresses than good ones)
- I have the option of toying with spammers and stall their connections and
waste their resources (see the following page for details on
teergrubing
Note that you can also use this code to simply run SA on all your mails (or
portion thereof as configured with SAEximRunCond) without having to configure SA
in your exim.conf. In other words, this code can be configured to not reject
any mails.
SpamAssassin? What's that?
Ah, you need to visit this page first
then
How does it work, what knobs are there?
You need to configure spamassassin to flags mails as spam after a certain
threshold (7 for instance). After that, this code can be configured to
- Pretend to be processing the Email and send continuation lines to the
remote server until it gives up (aka
teergrubing)
- Never acknowledge the DATA phase (i.e sleep until the other side gives up)
- Accept but not deliver mail with a high threshold (i.e. devnull the mail)
- Reject mail with a lower threshold
- Temporarily reject mail with a still lower threshold (you can then inspect
your logs to decide if you want to tweak SA so that next time the mail
is sent, you can receive it)
- In all 5 cases, mail can be optionally saved to disk so that you can
inspect all the mails you've rejected or /dev/nulled
For more details, you should look at the self-documented
config file and you can see
some sample rejects and what you get in the logs
Ok, where's the code?
As explained in the archive, you can either copy sa-exim.c over exim's
src/local_scan.c You need to copy local_scan in src in the exim source
tree and rebuild it, or you can build sa-exim as a loadable module (you need
to patch exim to support loadable modules though)
If you use Debian Linux, I unofficially maintain an exim4 package. See
this page for details
You can also browse all my exim files here
Mailing list
You should probably subscribe to this low traffic
mailing list if
you download the code to keep apprised of bug fixes and enhancements
Integration with Exim 4
This code works without anything in the exim conf, but you probably want to use
some knobs to disable scanning for some users (like setting
X-SA-Do-Not-Rej or X-SA-Do-Not-Run in the rcpt ACL and
removing those headers in the right places).
See my exim4 conf tree
and more specifically the
exim4.conf
file
Changelog
- 2002/10/13 - v2.1
- Default mail config is now in /etc/exim instead of /etc/mail
- Fixed SAstallsender so that exim doesn't leave spool files behind
- Fixed comparison for spam values as suggested by Patrice Fournier
- Returned a header saying whether SA-Exim was able to scan the mail
or not (based on a suggestion from Patrice Fournier)
- Added support for teergrubing as suggested by Robert Strickler
(see
http://www.iks-jena.de/mitarb/lutz/usenet/teergrube.en.html)
- We now make sure that we feed spamc a little more data than it's
willing to accept. That way, we don't feed a truncated message
- spamassassin.conf now appends /new on save directories so that they
are valid maildir spool and you can run mutt -f dirname to read
- Small cleanups
- 2002/07/07 - v2.0.1
- Removed unneeded ## concatenation in macro
- Fixed lseek call, as reported by Peter N Lewis
- Improved Makefile for documentation
- Suggestion from dman to allow for config options overrides in Makefile
- Fixed all the compiler warnings that were fixable
- Handle more kinds of Message-Id as suggested by Patrice Fournier
- 2002/06/14 - v2.0
- Allow for stalling SMTP sessions from spammers (caution)
- Support X-Spam-Status from SA pre 2.30
- Build patches from Norm
- Documented that spamd shouldn't be run with -c
- dman's patch to allow for this to be a shared library
- dman's indirect request for saved files to be 660
- 2002/06/01 - v2.0b1
This is how 1.0 would have been if I had done it right :-)
- We now attempt to create directories we write to
(suggestion from Patrice Fournier)
- Log envelope sender, receipients and connecting host
on rejected messages (suggestion from Patrice Fournier)
- We can now save non rejected messages whether they were
flagged as spam or not (based on request from Patrice)
- Each save rule now has its own condition that lets you
decide which messages you want to save or not
- Fixed parsing of Message-Id. May not parse all of them
but won't do anything stupid with bad input
- Fixed a buglet where we removed old headers before knowing
whether they were going to be replaced.
- Added much needed internal alarm so that we don't run
too long
- I added lots of options, but weren't able to test all
of them and their combinations, please reports problems
you may notice and documentation issues (in config file)
- Thanks also go to dman for his plentiful feedback
- 2002/05/21 - v1.3
- We now close the files we create on disk. Duh!
- 2002/05/17 - v1.2.2
- SA options are now kept in memory. Small cleanups
- 2002/05/13 - v1.2.1
- v1.2 (unreleased) didn't work right: it tagged messages
properly, but failed to see what was marked as spam and
couldn't reject messages. Fixed.
- Stripped newlines in header lines (better for logging)
- fixed header_add bug if headers contained '%'
- 2002/05/12 - v1.2 (unreleased)
- According to Craig R Hughes, any X-Spam header can be multiline.
Let's parse them accordingly
- 2002/05/08 - v1.1.1
- Added fake envelope from to mails that we save on disk
so that they can be opened with MUAs (idea from dman)
- 2002/05/07 - v1.1
- Cleaned up and fixed multiline header parsing
- Added parsing of Subject back from Spamc (suggestion from dman)
- We now log how long spamc took, and all messages processed
by spamc get logged in mainlog so that we know the outcome
- Added custom header compare function to handle mixed case headers
- 2002/05/06 - v1.0.1
- Fixed problems with reading Content-Type back from spamc
(we used to read whole body too, ooops...)
- Handle multi-line Content-Type headers.
- All log entries now start with "SA: "
- If SA gets run twice, we drop the previous X-Spam headers
- Support for X-Spam-Prev-Content-Transfer-Encoding
- 2002/05/05 - v1.0
- *Many* changes. This is now a real program with hopefully
most of the configuration options people could need
- Fully configurable through external config file
- Condition to run or not run SA against a message
- 3 Levels of spam handling
- Option to save messages that are rejected or cause errors
- Very complete error checking
- 2002/04/17 - v0.9.1
- Added a few checks for possible failures
- 2002/04/16 - v0.9
More generally, all the files can also be found here
Feedback is appreciated
Acknowledgements
While I wrote SA-Exim after realizing that I didn't want to accept Spam in the
first place, this package would not have been put together without the help
and contributions of the following people:
- Philip Hazel
We wouldn't have exim without him :-)
- Justin Mason, Craig R Hughes, and the rest of the SpamAssassin crew
- Derrick 'dman' Hudson
Early adopter, feedback, ideas, first integration with localscan_dlopen
- David Woodhouse
Excellent localscan_dlopen patch for exim 4
- Norm
Build patches and trailing slash problem for mkdir on netbsd
- Patrice Fournier
Several suggestions, including adding the X-SA-Exim-Scanned header
- Peter N Lewis
Spotted a buglet in lseek call
- Robert Strickler
Suggested that I add teergrub support
- Your name here
If you contribute or if I forgot your name (sorry, let me know)
Email
Link to Home Page
2002/05/06 (09:47): Version 1.0. Initial version
2002/05/06 (11:21): Version 1.1. Minor typos and fixes
2002/05/06 (23:52): Version 1.2. Version 1.0.1 released
2002/05/08 (01:33): Version 1.3. Version 1.1 released
2002/05/08 (23:02): Version 1.4. Version 1.1.1 released
2002/05/13 (23:49): Version 1.4. Version 1.2.1 released
2002/05/16 (10:30): Version 1.5. Made it clear that the patch is self sufficent
2002/05/19 (17:41): Version 1.6. Version 1.2.2 released
2002/05/21 (00:11): Version 1.7. Version 1.3 released
2002/06/02 (00:45): Version 1.8. Version 2.0b1 released
2002/06/14 (09:57): Version 1.9. Version 2.0 released
2002/10/14 (R10:51: Version 2.0. Version 2.1 released