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 "address@domain.com", 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?
No, you are extracting the full contents of the To:
header, which should normally look something like To: Real Name <recipient@example.net>
. There are many variations, though; it could also be recipient@example.net (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 <sender@example.org>
To: Real Name <recipient@example.net>
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 <recipient@example.net>"
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 "recipient@example.net"
procmail: Match on "^To:.*<\/[^>]+"
procmail: Assigning "TO_=recipient@example.net"
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 <recipient@example.net>
. 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.