Search code examples
procmail

How to set variable in procmail as To email address


I have a Procmail rule that uses formail to parse the To: email header to determine the email address the email was sent to:

TO_=`formail -XTo:`

This isn't working, as I'd like ${TO_} to evaluate to "[email protected]", but what I'm getting is "To: firstName lastName".

How can I set an environment variable in a procmail script to the format I'd like?


Solution

  • No, you are extracting the full contents of the To: header, which should normally look something like To: Real Name <[email protected]>. There are many variations, though; it could also be [email protected] (Real Name), for example, though this format is obsolescent.

    Demo:

    bash$ cat <<\: >nst.rc
    SHELL=/bin/sh
    TO_=`formail -XTo:`
    :
    
    bash$ cat <<\: >nst.eml
    From: me <[email protected]>
    To: Real Name <[email protected]>
    Subject: All your base
    
    They are belong to us
    :
    
    bash$ procmail -m VERBOSE=yes DEFAULT=/dev/null nst.rc <nst.eml
    procmail: [271] Fri Sep  2 10:01:29 2022
    procmail: Assigning "DEFAULT=/dev/null"
    procmail: Assigning "MAILDIR=."
    procmail: Rcfile: "nst.rc"
    procmail: Assigning "SHELL=/bin/sh"
    procmail: Executing "formail,-XTo:"
    procmail: Assigning "TO_=To: Real Name <[email protected]>"
    procmail: Assigning "LASTFOLDER=/dev/null"
    procmail: Opening "/dev/null"
     Subject: All your base
      Folder: /dev/null                             114
    

    If you know that the header contains the address between <brokets>, you can extract the text between them without using formail or another external utility.

    :0
    * ^To:.*<\/[^>]+
    { TO_=$MATCH }
    

    This uses Procmail's special \/ extraction token which assigns the matching text after it into the special internal variable MATCH.

    bash$ cat <<\: >nst2.rc
    SHELL=/bin/sh
    
    :0
    * ^To:.*<\/[^>]+
    { TO_=$MATCH }
    :
    
    bash$ procmail -m VERBOSE=yes DEFAULT=/dev/null nst2.rc <nst.eml
    procmail: [275] Fri Sep  2 10:03:26 2022
    procmail: Assigning "DEFAULT=/dev/null"
    procmail: Assigning "MAILDIR=."
    procmail: Rcfile: "nst2.rc"
    procmail: Assigning "SHELL=/bin/sh"
    procmail: Assigning "MATCH="
    procmail: Matched "[email protected]"
    procmail: Match on "^To:.*<\/[^>]+"
    procmail: Assigning "[email protected]"
    procmail: Assigning "LASTFOLDER=/dev/null"
    procmail: Opening "/dev/null"
     Subject: All your base
      Folder: /dev/null                             114
    

    Tangentially, if you wanted to extract a header value without the header keyword itself, that would be

    formail -zxTo:
    

    with a lowercase -x.

    But this still extracts the entire value, i.e. Real Name <[email protected]>. You could of course add a simple sed script to extract just the email terminus; but generally speaking, you want to avoid spawning external processes for efficiency reasons.