More Newbie Help

Matthias Andree matthias.andree at gmx.de
Thu Jul 10 13:43:30 CEST 2003


"Clark, Aaron" <aclark at Calence.com> writes:

> Okay I'm almost there. I have a filtermail.sh script that Postfix calls when
> it receives a message and pass it through bogofilter. I then have the script
> grep for X-Bogosity:yes and redirect it using Postfix's sendmail to a SPAM
> mailbox. However after it redirects the SPAM the original message is sent to
> the deferred queue with Temporary Failure. I would assume this would hurt
> performance as all SPAM messages get placed in this queue and retry
> delivery. 
>
> Anyone have any thoughts on this? 

Yes, I do. My suggestions below may look strange, "remove the file, then
send it", but it is safe because of the "exec <msg.$$" trick:

1. "exec <msg.$$"   opens the file for reading, assigns file descriptor #0.

2. "rm -f msg.$$"   removes the file name, but the contents remain
                    available because the file is still open.

   (At this time, the next process could safely write to msg.$$ without
   changing the file we have still open, unless we decided to use msg.$$
   by its name, which we do not.)

3. "exec $POSTFIX..."  REPLACES the shell script by $POSTFIX
                       (/usr/sbin/sendmail), and will inherit all open
                       files, including the file descriptor #0. Only
                       after this $POSTFIX program terminates, will the
                       operating system let go of the file contents of
                       msg.$$ and reclaim the disk space.

   It is IMPORTANT that in this step there is NO INPUT REDIRECTION.


> #!/bin/sh
>
> FILTER=/usr/bin/bogofilter
> FILTER_DIR=/var/spool/filter
> POSTFIX=/usr/sbin/sendmail
> # BOGOFITLER_DIR=/var/spool/mail

          ^^ Interchanged letters T and L in the BOGOFILTER word.

> EGREP=/bin/egrep
>
> # Exit codes from <sysexits.h>
> EX_TEMPFAIL=75
> EX_UNAVAILABLE=69
>
> cd $FILTER_DIR || \
>         { echo $FILTER_DIR does not exist; exit $EX_TEMPFAIL; }
>
> # Clean up when done or when aborting.
> trap "rm -f inp.$$ msg.$$; exit $EX_TEMPFAIL" 0 1 2 3 15

This means: "when done, clean up and exit $EX_TEMPFAIL".

> # bogofilter returns: 0 for spam; 1 for non-spam; 2 for I/O or other errors.
> rm -f inp.$$ || exit $EX_TEMPFAIL
> cat > inp.$$ || exit $EX_TEMPFAIL
> $FILTER -p -e < inp.$$ > msg.$$ || exit $EX_TEMPFAIL

You don't use inp.$$ ever again, so make this:

  trap "rm -f msg.$$; exit $EX_TEMPFAIL" 0 1 2 3 15
  rm -f msg.$$ || exit $EX_TEMPFAIL
  $FILTER -p -e >msg.$$ || exit $EX_TEMPFAIL

> if $EGREP -q "^X-Bogosity: Yes" < msg.$$
> then
>         $POSTFIX spam at kalence.org < msg.$$

Try:
        exec <msg.$$
        rm -f msg.$$
        exec $POSTFIX spam at kalence.org

>         rm -f inp.$$

Remove the rm -f line.

> else
>         exec $POSTFIX "$@" < msg.$$

This will leave msg.$$ behind. Use as above,

        exec <msg.$$
        rm -f msg.$$
        exec $POSTFIX "$@"

> fi
>
> exit 0

This should be exit $EX_TEMPFAIL for in-depth robustness against failure
or accidental changes of the script.

-- 
Matthias Andree




More information about the Bogofilter mailing list