procmail
[Top] [All Lists]

Re: formail error on large emails

1998-10-15 15:29:49
Paul Ashton <paul(_at_)argo(_dot_)demon(_dot_)co(_dot_)uk> writes:
:0 c
* !^X-Loop: $MYADDR
{
       FROM=`formail -rt -zxTo:`
       SUBJECT=`formail -zxSubject:`

       :0
       | (formail -rI"From: $FROM" \
               -I"Subject: $SUBJECT" \
               -I"To: $SMSEMAIL" \
               -I"X-Loop: $MYADDR" ;\
               echo "$FROM $SUBJECT") \
               | $SENDMAIL -oi -t
}

I've finally decided to try and track down a sporadic problem that 
causes me to receive two copies of each email. It turns out that this 
recipe is returning an error if the incoming mail is larger than 32K.
In this case, I get the following procmail.log error message:

procmail: Error while writing to " (formail -rI"From: $FROM" \
               -I"Subject: $SUBJECT" \
               -I"To: $SMSEMAIL" \
               -I"X-Loop: $MYADDR" ;\
               echo "$FROM $SUBJECT") \
               | $SENDMAIL -oi -t"

Which causes me to receive an extra copy of the mail.

Any idea what I'm doing wrong?

The problem is as follows: you've told procmail to write the entire
message down the pipe to the action (to be precise, you haven't told
procmail to do otherwise), however, the action only reads the header of
the message.  As a result, on messages where the body is more than
PIPE_BUF bytes long or so, procmail will get a write error which it
interprets as failure of the action.  Since the recipe didn't deliver,
the procmail clone spawned by the 'c' flag on the nested block will
fall out of the block and continue on resulting in a duplicate message
being delivered further on in the procmailrc.

Okay, how to solve this.  This first step is to tell procmail to only
feed the head of the message down the pipe to the action.  This is done
by putting the 'h' flag on the inner recipe.  Also, it would be more
efficient for you to place the 'c' flag on the inner recipe instead of
the outer one.  That saves a fork() call and a bunch of memory.

Finally, X-Loop: headers should be added with the -A flag, not the -I
flag so that other X-Loop: headers are preserved.  Without that, it
would be possibile to start a loop with some other site.  Those
changes, plus some reformatting, would give you the following:

        :0
        * ! ^X-Loop: $MYADDR
        {
                FROM=`formail -rt -zxTo:`
                SUBJECT=`formail -zxSubject:`

                :0 hc
                | (formail -rI"From: $FROM" \
                            -I"Subject: $SUBJECT" \
                            -I"To: $SMSEMAIL" \
                            -A"X-Loop: $MYADDR" \
                  ;echo "$FROM $SUBJECT" \
                  ) | $SENDMAIL -oi -t
        }


Does that all make sense?


Philip Guenther

<Prev in Thread] Current Thread [Next in Thread>