procmail

get header in variable and use it to match rule


I have a procmail rule that works perfectly for me:

:0
* ^To:.*anonymized
* ^Subject:.*Report domain: anonymized Submitter: [^ ]* Report-ID:
{
LOG="1"
:0 cw
* ^To:\/.+
| /etc/procmail/process_dmarc_report.sh "$MATCH"
}

But the subject is sometimes encoded, which breaks the rule. Based on https://stackoverflow.com/a/29715987/13463349

I wanted to replace the test on the Subject header with a test on the SUBJECT variable containing the possibly decoded subject, as follows:

:0
* ^Subject:.*=\?utf-8\?B\?
SUBJECT=`formail -cXSubject: | perl -MMIME::Base64 -ne 's/^=\?utf-8\?B\?(.*?)\?=$/print decode_base64($1)/e'`
:0 E
SUBJECT=`formail -cXSubject:`
:0
* ^To:.*anonymized
* SUBJECT ?? Subject:.*Report domain: anonymized Submitter: [^ ]* Report-ID:.*

The subject is correctly decoded, but I'm doing it wrong because I have an error in the logs:

procmail: Skipped "[Preview] Report Domain: anonymized Submitter: enterprise.protection.outlook.com Report-ID: c136884d7adc4f5c82e2fdbbde75e2ab"

And the email is delivered to Folder: SUBJECT=Subject:.

I tried with -x instead of -X and not including Subject: in the test, and several other small adaptations, but without success. I can't find my mistake. It may be simple, but I can't seem to get it right.

If, as suggested, I do something like:

:0
* ^Subject:.*=\?utf-8\?B\?
SUBJECT=| formail -cXSubject: | perl -MMIME::Base64 -ne 's/^=\?utf-8\?B\?(.*?)\?=$/print decode_base64($1)/e'

:0 E
SUBJECT=| formail -cXSubject:

$SUBJECT is empty

My entire rule (not working) at the moment:

:0
* ^Subject:.*=\?utf-8\?B\?
SUBJECT=`formail -cXSubject: | perl -MMIME::Base64 -ne 's/^=\?utf-8\?B\?(.*?)\?=$/print decode_base64($1)/e'`
:0 E
SUBJECT=`formail -cXSubject:`
:0
* ^To:.*anonymized
* SUBJECT ?? Subject:.*Report domain: anonymized Submitter: [^ ]* Report-ID:.*
{
        LOG="1"
        :0 cw
        * ^To:\/.+
        | /etc/procmail/process_dmarc_report.sh "$MATCH"
}

Solution

  • The problem was about the variable test:

    * ^Subject:.*Report domain: anonymized Submitter: [^ ]* Report-ID:
    

    won't work because of [^ ]*
    but

    * ^Subject:.*Report domain: anonymized Submitter: .* Report-ID:
    

    works !

    * variable ?? regex
    Test the value of variable against regex.

    The documentation says it's a regex, but it really isn't.

    My final working rule is:

            :0
            * ^Subject: \/=\?utf-8\?B\?.+
            {
                    SUBJECT=`echo $MATCH | perl -MMIME::Base64 -ne 's/^=\?utf-8\?B\?(.*?)\?=$/print decode_base64($1)/e'` 
            }
    
            :0E
            * ^Subject: \/.+
            {
                    SUBJECT=$MATCH
            }
    
    
            :0
            * SUBJECT ?? Report domain: novazur\.fr Submitter: .* Report-ID:
            {
                    :0 cw
                    * ^To:\/.+
                    | /etc/procmail/process_dmarc_report.sh "$MATCH"
            }
    

    NB: Never remove curly braces that you might think are unnecessary around variable assignments. They are essential, even in:

    :0
    * ^Subject: \/=\?utf-8\?B\?.+
    {
        SUBJECT=`echo $MATCH | perl -MMIME::Base64 -ne 's/^=\?utf-8\?B\?(.*?)\?=$/print decode_base64($1)/e'`
    }
    :0E
    * ^Subject: \/.+
    {
        SUBJECT=$MATCH
    }