Re: [exim] Exim 4.7, mailman and spamcheck/drop

Top Page
Delete this message
Reply to this message
Author: Todd Lyons
Date:  
To: Lars Schimmer
CC: exim-users
Subject: Re: [exim] Exim 4.7, mailman and spamcheck/drop
On Tue, Apr 23, 2013 at 6:24 AM, Lars Schimmer <l.schimmer@???> wrote:
>
> I think about a easy way to drop spams for mailinglists but not for users.
> Each mail is checked on incoming with exiscan and tagged with a SA score.
> Now I try to filter all mailman mailinglist spam with a score >5 to be
> dropped silently, but all spams with a score >5 to other mail users to
> be delivered.
> IMHO something like that in ACL should do the trick, or?
>
> deny message   = "SPAM"
>      senders   = :
>      domains   = +mm_domains
>      local_parts =
> \N^.*-(admin|join|leave|owner|request|subscribe|unsubscribe)$\N
>      condition = ${if >{$spam_score_int}{50}{1}{0}}

>
> But does this really work fine?


No, it will not work. The domains and local_parts conditions are only
usable in the RCPT acl. The spam score system is only usable in the
DATA acl.

> Anyone have a better idea?


In the DATA acl, you will have to construct a macro to iterate over
the $recipients variable and compare each of those to the regex. The
$recipients string expansion is all of the envelope recipients
separated by a comma and a space. That means that you will also need
to use the special sequence:
<,
which means to use the , as the separator instead of the default colon.

To be honest, I would probably do this in an embedded perl function
(if your build has that enabled) since I'm more at home in perl.
Something like:

sub detect_mm_local_parts {
my $recipients = Exim::expand_string('$recipients');
my @recipients = split ',' , $recipients;
my @mm_recips = grep
/.*-(admin|join|leave|owner|request|subscribe|unsubscribe)@.*/
@recipients;
# If number of items in array more than zero, return true
return( (scalar @mm_recips > 0) ? 1 : 0);
}

And then in the DATA acl, instead of your conditon, you would just call:
condition = ${perl{detect_mm_local_parts}}

You don't need to wrap it with an ${if condition, it will work as a
direct argument to the condition condition. There is also no need to
pass any data to the function, it extracts what it needs on its own.

I split each logical step of the function into individual variables to
make it clear what it is doing, but it could all be combined into one
big grep/split/expand_string if you wanted to. Whatever is easier to
grok months or years down the road (when it's not fresh) is my driving
force for code clarity.

...Todd
--
The total budget at all receivers for solving senders' problems is $0.
If you want them to accept your mail and manage it the way you want,
send it the way the spec says to. --John Levine