Re: [exim] $header_X-xxx expansion not working in router sec…

Top Page
Delete this message
Reply to this message
Author: Chris Siebenmann
Date:  
To: Andreas Pflug
CC: exim-users
Subject: Re: [exim] $header_X-xxx expansion not working in router section
| Using exim 4.72 (debian squeeze), I'm trying to implement a NDR
| suppression in case the non-deliverable mail is marked as spam. Since
| the receiving exim instance is in a dmz, it cannot verify the recipient
| immediatly, so the bouncing happens after the mailscanner has processed
| the message and the local delivery fails.


As with other people, I strongly recommend that you arrange to
reject at SMTP time for invalid local recipients. Our external MX is
effectively in a DMZ, isolated from our main mail system, but we take
steps to generate a list of valid local addresses and push this list to
the external MX (along with a list of valid local domains and hosts).

There may be circumstances where you can't completely generate such
a list, but maybe you can generate lists of things like valid address
prefixes so that you can at least not accept clearly bad cases.

| To have NDRs on non-spam mails, my idea was to set errors_to to "" only 
| if the message has been marked as X-Spam-Status: Yes by mailscanner, 
| using this in the router section:
| 
| errors_to= ${if eq { $header_X-Spam-Status: }{"Yes"} {"ap@???"} 
| {$return_path}    }
| 
| Unfortunately, $header_X-Spam-Status: expands to empty. When debugging, 
| I found that standard headers do work (e.g. $header_Received: ) but not 
| non-standard headers. Same happens when I try this as condition to omit 
| the NDR from the outgoing router.


It's possible that this needs the custom header name in lower case.
We do a broadly similar thing here using a custom header and our check
for it uses '{def:h_x-original-subject:}'.

Our overall approach to the problem is somewhat different than yours.
Instead of trying to set errors_to in the router to a null-route, we
generate the bounce with a custom message-file that includes some
additional headers (in your case you would copy the X-Spam-Status line
in as, say, X-Original-Spam-Status), and the match, filter, and discard
the message with a very early router. Our setup uses an Exim filter
because this allows us to log more information about junked bounces.
The actual router then looks (for us) like:

eat_spam_bounces:
        debug_print = "R: eat_spam_bounces for $local_part@$domain"
        driver = redirect
    # local users always get bounces
        domains = ! +local_domains
        # The eating is done via an Exim filter, because it can
        # log more information in a distinctive way and spot.
        file = CFMSD/exim-bounce-filter
        allow_filter
        allow_freeze
        user = Debian-exim
        no_verify
        no_expn
    # match things that look very much like bounces
        condition = ${if and {{!eq{$interface_port}{25}} \
                {!def:return_path} {def:h_x-original-subject:} }}


(The exim-bounce-filter filter actually looks at the X-Original-Subject
for the 'it was spam' markers and discards if so.)

 We play similar tricks to suppress looping bounces; we have a custom
header included in bounces that is defined as:
    X-CS-Bounce-Count: I$h_x-cs-bounce-count


and then we have a router and filter that triggers if the header is too
big (again, we use a filter partly because it can log more information).

I can share the filter(s) if people would find them interesting or
useful.

    - cks
PS: we don't do this because we do accept-then-bounce; we do this because
    some of our users forward *all* of their mail, spam included, off to
    outside places which then reject the spam at SMTP time when we try to
    deliver it to them. We want to eat the bounces for such rejected
    forwarded spam.