Grepular

Accessing Rejected Spam Solution

Written 16 years ago by Mike Cardwell

I run CommuniGate Pro for my email. All incoming and outgoing email passes through my Exim server.

Exim rejects a lot of incoming email due to it being spam. I wanted to continue to reject at SMTP time, but I also wanted to store a copy of all rejected email, for each of my users. I’ve heared of cases where spam is stored in a different system which a user can access via webmail, and systems where users get reports of rejected spam each day/week. Neither of those sounded ideal. I wanted just another folder in the users IMAP client containing the spam, which was read only. Messages in it should also expire after a week.

In CommuniGate I created a special account which we’ll refer to as “admin”. All spam was to be stored within this account in folders named after the users. Eg, for my user “mike” there was a folder called:

~admin/Spam/mike

I then gave my self read access to that folder, and created what is known within CommuniGate as a Mailbox Alias. I pointed “~mike/Junk E-mail” at it. I chose “Junk E-mail” as that is the default that Thunderbird seems to like to use for spam. This system should work with pretty much any IMAP server, but I’m using CommuniGate and that’s all I’ve tested with so far.

Now I just needed to get Exim to deliver the spam into that folder:

First of all, I moved all of my ACL level rejections into the acl_smtp_data acl. That way I knew I’d have access to the full email message including the body, before doing the rejection.

Secondly, I changed all of my “deny” options to “accept” and added “control = fakereject” to them. That way, the connecting client would get a rejection message, yet the message would still reach the Exim routers. I also added “set acl_m1 = REJECT” into these config sections so I would know in the routers to deliver the message to the relevant spam folder only.

I then added an Exim router:

rejected_store:
    driver    = accept
    condition = ${if eq{$acl_m1}{REJECT}}
    transport = store_rejected_pipe
    no_verify

And an Exim transport:

store_rejected_pipe:
        driver      = pipe
        user        = Debian-exim
        group       = mail
        temp_errors = *
        command     = /etc/exim4/pipe2imap.pl \
                         user admin@example.com \
                         pass ********** \
                         folder Spam/$local_part \
                         create $local_part=lrs \
                         flags 'Junk \\seen'
        log_defer_output = true

This combination of router and transport delivers the message in to the folder via IMAP. I actually wrote the pipe2imap.pl script myself, for this project. I’ve released it under the GPL so you’re free to download it and use it as you see fit.

In the above example, it actually creates the folder and adds the read permissions automatically. It also marks each spam message as read, and applies the “Junk” flag to it as well. Thunderbird uses this flag. I don’t know if other clients do.

To expire the email over a certain age, I wrote a separate script that would log in via IMAP on a daily basis and search for and delete the messages. It’s called IMAPExpire.

So as a user, what do I gain? If I’m expecting a message and I haven’t received it, I can just have a quick scan of the “Junk E-mail” folder. I don’t need to manage that folder in any other way. If I’ve just bought something online or signed up for a forum, or am waiting for someone to send me a document, I don’t have to worry about the spam filter eating the message as I know I will still be able to access it if needed.

Want to leave a tip?BitcoinMoneroZcashPaypalYou can follow this Blog using RSS. To read more, visit my blog index.