regexfilterprocmail

Procmail regex to mark anything that doesn't contain a specific string in To: field


I'm pretty good in regex... but can't solve this Procmail problem.

:0
* ^Subject:.*Derila.*
/dev/null

filters out everything that contains Derila in subject line. working. But how do I filter out - or even better: mark as spam in header - when the recipient DOESN't contain a certain string like myname?

I tried many variations, none working. Could it be Procmail can't do negative lookahead?

:0
* ^To:.*((?!myname).)*$
/dev/null

I tested at least 20 different regexes in vain.


Solution

  • Indeed, the regex implementation in Procmail does not support lookarounds, or other Perl features. In fact, the documentation mentions that the regex features are those of egrep, although this isn't strictly speaking exactly true.

    But the overall rule syntax allows you to say this, easily:

    :0
    * ! ^To:.*myname
    /dev/null
    

    There is a convenience macro ^TO_ which lets you examine Cc:, Resent-to: etc in one go;

    :0
    * ! ^TO_myname
    /dev/null
    

    (Perhaps notice also how you don't need a trailing .*; the rule fires if the regex matches anywhere on any line.)

    To add a header instead of discarding the message, run it through formail. Here's how you'd prepend a string to the Subject: header:

    :0fhw
    * ! ^TO_myname
    *   ^Subject: *\/.*
    | formail -I "Subject: [spam?] $MATCH"
    

    Here, the trailing .* is useful because anything after the special token \/ which is matched by the regex is captured in $MATCH. This is one of the peculiarities where Procmail differs from egrep.

    Of course, any mailing list or Bcc: message will not have your address in any visible headers; I would strongly advise against discarding those messages blindly.