procmail
[Top] [All Lists]

Re: help with rule request

1998-11-04 20:44:44
dwm(_at_)hotair(_dot_)hobl(_dot_)lucent(_dot_)com writes:
I want to craft a .procmailrc rule like:
get the Subject line and parse it into a FILENAME to be used to
log emails each containing a single line of data
Write that single line of data to $FILENAME

SHELL=/usr/bin/ksh
:0 c
* ^Subject: XXXXXX
* ^From:(_dot_)*something(_at_)domain(_dot_)com(_dot_)*
# other filters here?
 |export FILENAME=`formail -xSubject: |sed -e 's/ //g'`
 :0 A
 # formail -I "" gets just the body, the sed stuff strips blank lines:
 |formail -I "" | sed -e '/^$/ d' >> /path/log/${FILENAME}
...
Problem is that above doesn't work...seems the second filter doesn't
get the value of $FILENAME passed?

Correct.  The action is evaluated by a subshell, so the variable setting
isn't seen by the procmail process.  There's a solution for this.  To
quote the procmailrc(5) manpage:

  Recipe action line
     The action line can start with the following characters:
...
     |    Starts the specified program, possibly in $SHELL if any
          of  the  characters  $SHELLMETAS  are spotted.  You can
          optionally prepend this  pipe  symbol  with  variable=,
          which  will  cause stdout of the program to be captured
          in the environment variable  (procmail  will  not  ter-
          minate  processing  the  rcfile at this point).  If you
          specify just this pipe  symbol,  without  any  program,
          then procmail will pipe the mail to stdout.


So, you can write it instead as:

        :0      # don't need the 'c' flag anymore
        * ^Subject: XXXXXX
        * ^From:(_dot_)*something(_at_)domain(_dot_)com(_dot_)*
        FILENAME=| formail -xSubject: |sed -e 's/ //g'

However, if you're using procmail version 3.10 or later then there's
a better solution: use the \/ token and the MATCH variable.

        # The 'b' flag tells procmail to feed only the body of the
        # message into the action command.  That save a formail.
        # The ^Subject condition, when it matches, saves whatever was
        # matched after the \/ token to the MATCH variable.  In this
        # example I only match if the first non-blank character in the
        # Subject: is either a letter, number, or '-'.  The filename
        # is then the longest string of those characters starting at
        # that first one so that, for instance, the subject line
        #       Subject: blah-blha_boofooooo
        # would result in a filename of "blah-blha", as it stops
        # matching at the '_'.
        :0 b
        * ^From:(_dot_)*something(_at_)domain(_dot_)com(_dot_)*
        * ^Subject: *\/[-a-z0-9]+
        | sed -e '/^$/ d' >> /path/log/$MATCH; \
          echo $MATCH >/path/log/out1
 

If you want to be more liberal in what filenames you accept you should
be careful to exclude things like filenames containing ".." or "/."
(the later to protect 'dotfiles').  You can do so by using conditions
like this:

        *   ^Subject: *\/[-a-z0-9./]+
        * ! ^Subject:.*[./]\.

The later condition fails if the Subject contains ".." or "/.", while
other combos.  Note that MATCH is only set/reset by conditions
containing \/, and only if that condition is processed.  If a previous
(non-weighted) condition has failed then procmail will be skipping the
rest of the conditions and the action so MATCH will not be changed.


Philip Guenther

<Prev in Thread] Current Thread [Next in Thread>
  • Re: help with rule request, Philip Guenther <=