Re: [exim] spam acl condition syntax

Top Page
Delete this message
Reply to this message
Author: W B Hacker
Date:  
To: exim users
Subject: Re: [exim] spam acl condition syntax
Stuart Gall wrote:

> On 13 Oct 2006, at 11:56, W B Hacker wrote:
>
>
>>Stuart Gall wrote:
>>
>>*snip*
>>
>>

*snip*
>
>
> OK I realy don't see how this can work
> the data acl is only called once - right -


- MOST information is available from the phase at which it is first
furnished/ascertainable - and not before - but remaoisn available until either
completion of the data phase OR it is altered/over-written - for example by
successive 'Mail From', each with potentially (but rarely) multiple 'Recpt to'
within a single conenction.

acl_smtp_rcpt and acl_smtp_data will be entered once for each message.

> so if the email is
> addressed to multiple recipients with different rejection thresholds
> how can it handle that.


It needs to pull the 'per-recipient' parameters during acl_smtp_rcpt, the
earliest phase that the recipient can be known.

We do it as the last clause in acl_smtp_rcpt.

Loading pre-existing information from an acl_c(x) variable (such as rDNS fail if
not a system 'global' reject) into acl_m(x) variables, putting additional
information gleaned within acl_smtp_rcpt phase into acl_m(x) variables, makes it
easier to track these through the data phase.

This *also* lets you load 'defaults' or over-rides, do cumulative point-scoring
in fewer variables, and perform any/all of true/false, lookup, or 'degrees' of
goodness/badness, which is harder to do with direct use of most tests.

Ex: Test several RBL's, adding '4' for a hit on the ones you trust most,
'2' for average, and '1' for less-trusted, then test against a user-pref where
less-than 1 might be allowed to pass for paranoid@???, less-than 2 for
curious@???, and less-than 8 for ganymede@???.

>
> From the manual referring to data and predata
> For both of these ACLs, it is not possible to reject individual
> recipients. An error response rejects the entire message.
>


Yes BUT.... (and you will need to look extensively at enhanced logs to be sure
if this fits your situation)

- Exim *can* be told to accept messages only one-at-a-time. We have not so far
needed to do that, because;

A) Most zombies - the ones we are setting up to 'reject' as it happens - will
arrive QMail-style. Multiple connections, even if each tries to deliver to one
valid address and 2 dozen forged/dictionary attempts.

As each coennection spawns a different Exim child process, there is no concern
about mixing between/among those.

Even so, 'require verify = recipient' rejects most w/o need of SA scanning.

If you have the luxury of not suffering fools, a 'drop' on that clause instead
of a 'deny' kills the whole connection.

B) Most 'good' mail is either NOT batched to multiple recipients, OR is to staff
in the same domain/office who have fairly similar settings, AND/OR is 'clean'
enough that even the ruleset of the strictest recipient would not reject it,
merely score and flag it. No harm.

IOW - the 'problem' just has not been a problem.

>
>>NOT SHOWN in first port was what we DO with the (cached) spam
>>score, on per-user
>>basis.. Per-user prefs are pulled by a lookup at the end of
>>acl_smtp_recpt or
>>first thing in acl_smtp_predata and loaded into acl_m variables.
>
>
> Care to post that part, how do you deal with multiple recipients you
> must just be picking the first or last perhaps.
>


Think this through. How can SpamAssassin put a different score on each of
several messages, or an acl a differetn header on each of several messages if
they were all being handled as a 'mailbag' instead of one-at-a-time.

Set yourself up a couple of test accounts in each of several domains and try it.

Dummy .scr, .pif, .exe attachments that you scan for make good 'triggers'.

Here is our code:

===

# RCPT_7: SELECT per-recipient limits from DB for spam and rudeness checking
   #
   warn
     condition  = ${if eq{$acl_m10}{t}}
     set acl_m6  = ${lookup pgsql{SELECT pg_rudelimit from mailprof \
                   WHERE pg_active AND pg_domain='${quote_pgsql:$domain}' \
                   AND pg_local_part='${quote_pgsql:$local_part}'}}
     set acl_m7  =  ${lookup pgsql{SELECT pg_spamwarnint from mailprof \
                   WHERE pg_active AND pg_domain='${quote_pgsql:$domain}' \
                   AND pg_local_part='${quote_pgsql:$local_part}'}}
     set acl_m8  =  ${lookup pgsql{SELECT pg_spammodint from mailprof \
                   WHERE pg_active AND pg_domain='${quote_pgsql:$domain}' \
                   AND pg_local_part='${quote_pgsql:$local_part}'}}
     set acl_m9  =  ${lookup pgsql{SELECT pg_spamlimitint from mailprof \
                   WHERE pg_active AND pg_domain='${quote_pgsql:$domain}' \
                   AND pg_local_part='${quote_pgsql:$local_part}'}}
     set acl_m11 =  ${lookup pgsql{SELECT pg_rfc from mailprof \
                   WHERE pg_active AND pg_domain='${quote_pgsql:$domain}' \
                   AND pg_local_part='${quote_pgsql:$local_part}'}}
     set acl_m12 =  ${lookup pgsql{SELECT pg_bl from mailprof \
                   WHERE pg_active AND pg_domain='${quote_pgsql:$domain}' \
                   AND pg_local_part='${quote_pgsql:$local_part}'}}


====

Where:

acl_m10 is false for system/alias accounts. Handled elsewhere.
The rest are integers.

Code is simpler for a cdb, DB, or flat-file repository.

>
>>You might find something you can more easily adapt in these:
>>## note that I am leaving a spamd call in ALL of them but it only
>>need be called
>>## ONCE
>>## you may remove that call from all but the first of whatever you
>>use.
>>## note also that these do NOT use headers or reports from SA,
>>## you'd need to add those
>>
>>=====
>>   # DATA_SCAN_11: Put headers in messages when score is over per- 
>>recipient limits
>>   #
>>   warn
>>   # logwrite    = DS11 Spam Bars $spam_score
>>     !condition  = ${if eq{$acl_m0}{1}}
>>     spam        = spamd:true
>>     condition   = ${if >{$spam_score_int}{${eval:$acl_m7}}{1}{0}}

>
>
> this is only run once so $acl_m7 has a unique value, if there are
> multiple recipients one must override the others.
>


It is run once *per message*. All, or all but a select few accounts in each
domain have the same settings. Corporate Policy, not a technical limit.

A 'sales' or 'info' role account is more open than individual staff.

At which point non grantum rodentum ano about further differentiation.

It works 'well enough'.

> BUT you have given me an idea to do something very similar.
> I can set $acl_m1 if receipt to postmaster happens
> and $acl_m2 if receipt to other happens then do the test
> in the data_acl
> If the message is ONLY to postmaster ignore spam checks
>


Well - since we have finally motored back to *that* point - 'postmaster' doesn't
even traverse these rules at all. Given a 'get out of jail free' card very
early in acl_smtp_rcpt. Postmaster will even accept mail by ip_literal.

Hint: research the effect of 'endpass' early in an acl_smtp_<phase>

> OK - this is going to work
>
> TVM
>


has been for years.....

;-)

Bill