Configure procmail to match an external email addr

2019-08-30 08:36发布

问题:

My fetchmail scripts retrieves emails from an email box and puts them into a file, called mario, and dumps it into my /var/mail/ folder. I am trying to set up a procmail script to process mario; by processing, this is what I mean: the procmail script should filter against an external text file (fromlist) containing a list of known email addresses. Once there is a match mario/fromlist, the message is pulled out from mario and stored into my local nbox/ folder.

Online, I found a piece of code, including a recipe, that I have entered into my procmail control file (.procmailrc) but it doesn't seem to be working. This is the code:

FROMFL=$MAIL/fromlist

FROMLS=formail -xFrom: | sed -e 's/*(.*)//;s/>.*//;s/.*[:]*//'`

:0

* ? fgrep -xi $FROMLS $FROMFL

$MAIL/inbox

I think I have addressed the sed (see my question Sed command and unknown patterns found online), but I still haven't been able to address the formail and fgrep parts. So when I run the procmail script, the logs I obtain are:

$ mailstat var/log/procmail.log
/bin/sh: 0: Can't open fgrep
/bin/sh: 1: grep: not found
/bin/sh: 1: sed: not found
/home/user/var/mail/reginbox/
procmail: [6880] Sat Jun 16 16:57:32 2018
procmail: Acquiring kernel-lock
procmail: Assigning "FROMFL=/home/user/var/mail/fromlist"
procmail: Assigning "FROMLS="
procmail: Assigning "LASTFOLDER=/home/user/var/mail/reginbox/msg.XXX"
procmail: Assigning "SHELL=/bin/sh"
procmail: Executing "fgrep,-xi,/home/user/var/mail/fromlist"
procmail: Executing "formail -xFrom: | sed -e `'s/.*<//; s/>.*//'`"
procmail: No match on "fgrep -xi /home/user/var/mail/fromlist"
procmail: Non-zero exitcode (127) from "fgrep"
procmail: Notified comsat: "user@0:/home/user/var/mail/reginbox/msg.XXX"
procmail: Opening "/home/user/var/mail/reginbox/msg.XXX"

It looks as if formail cannot quite extract the lines where "From:" is located, which means that the email addresses in those lines are not carved out of the rest by the SED command and are not compared against the text file with the list of emails (fromlist), that's why the log show a "No match" message.

How can I find out where these things break down?

回答1:

The syntax for running an external command is

VARIABLE=`command to run`

You are missing the opening backtick, so you are running effectively

FROMLS="formail"
-xFrom: | sed etc is a syntax error

Anyway, the recipe to extract the sender is a bit inexact, because it doesn't cope correctly with various variations in email address formats. A more robust but slightly harder to understand solution is

FROMLS=`formail -rtzxTo:`

which makes formail generate a reply -rt, then from the generated reply extract the To: address, which of course now points back to the original sender. By design, formail only puts the actual email address of the sender of the input message in the To: header when it generates the reply, so that's what you will be extracting.

With that out of the way, your script should technically work to the point where it can extract the matching messages and copy them to the destination folder you want. Here's a quick demo:

tripleee$ cd /tmp

tripleee$ echo moo@example.com >fromlist

tripleee$ cat one.rc
# temporary hack
SHELL=/bin/sh
MAILDIR=/tmp
MAIL=.
VERBOSE=yes

FROMFL=$MAIL/fromlist

FROMLS=`formail -rtzxTo:`

:0
* ? fgrep -xi "$FROMLS" "$FROMFL"
$MAIL/inbox


tripleee$ procmail -m one.rc <<\:
From: ick@example.com
To: poo@example.org
Subject: no match

hello
:
procmail: [16406] Wed Jun 27 13:41:35 2018
procmail: Assigning "FROMFL=./fromlist"
procmail: Executing "formail,-rtzxTo:"
procmail: Assigning "FROMLS=ick@example.com"
procmail: Executing "fgrep,-xi,ick@example.com,./fromlist"
procmail: Non-zero exitcode (1) from "fgrep"
procmail: No match on "fgrep -xi ick@example.com ./fromlist"
 Subject: no match
  Folder: **Bounced**                                                        61

tripleee$ procmail -m one.rc <<\:
From: moo@example.com
To: poo@example.org
Subject: match

hello
:
procmail: [16410] Wed Jun 27 13:41:37 2018
procmail: Assigning "FROMFL=./fromlist"
procmail: Executing "formail,-rtzxTo:"
procmail: Assigning "FROMLS=moo@example.com"
procmail: Executing "fgrep,-xi,moo@example.com,./fromlist"
procmail: Match on "fgrep -xi moo@example.com ./fromlist"
procmail: Assigning "LASTFOLDER=./inbox"
procmail: Opening "./inbox"
procmail: Acquiring kernel-lock
 Subject: match
  Folder: ./inbox                                                            68    

There is no way really for procmail to remove anything from the input folder. If you want to do that, a common solution is to have Procmail write the non-matching messages to another output folder, then copy that back over the input file. The net effect is that the messages from the original input folder are now partitioned into two files, one with matching, and one with non-matching messages.