# pm-jaube-prg-spamassassin -- Interface to spamassassin program
#
#   File id
#
#       Copyright (C) 1997-2010 Jari Aalto
#
#       This program is free software; you can redistribute it and/or
#       modify it under the terms of the GNU General Public License as
#       published by the Free Software Foundation; either version 2 of the
#       License, or (at your option) any later version
#
#       This program is distributed in the hope that it will be useful, but
#       WITHOUT ANY WARRANTY; without even the implied warranty of
#       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
#       General Public License for more details at
#       <http://www.gnu.org/copyleft/gpl.html>.
#
#   Warning
#
#       Put all your Unsolicited Bulk Emacil (aka spam) filters towards the
#       end of your `~/.procmailrc'. The idea is that valid messages are filed
#       first (mailing lists, your work and private mail, bounces) and only
#       the uncategorized messages are checked last.
#
#       YOU CANNOT USE THIS PROCMAIL SUBROUTINE UNLESS YOU HAVE TRAINED THE
#       BAYESIAN PROGRAM FIRST!
#
#       To train:
#
#           $ rm -f ~/.spamassassin/bayes*
#           $ sa-learn $opt --local --no-rebuild --ham  good.msg ...
#           $ sa-learn $opt --local --no-rebuild --spam spam.msg ...
#           $ sa-learn --rebuild
#
#   Overview of features
#
#       o   Implements interface to http://www.spamassassin.org/
#           project.
#       o   variable `ERROR' is set if message was spam.
#       o   Results are available in default headers (X-Spam-*)
#
#   Description
#
#       There are several Bayesian based statistical analysis programs that
#       study the message's tokens and then classify it into two categories:
#       good or bad, or if you like, ham and spam. All the Bayesian programs
#       are not the same, so if you want to achive magic 99.99% probability
#       the only methodology to do that is to chain several programs in
#       serially. There is no single program that can solve the UBE detection.
#       This procmail subroutine implements call interface to program
#       `spamassassin', which must already have been installed.
#
#   About bouncing message back
#
#       The general consensus is, that you should not send bounces. The UBE
#       sender is not there, because the address forged. Do not increase
#       the network traffic; you will not do any good to anybody by
#       bouncing messgas -- you just increase mail traffic even more.
#       Instead save the messages to folders and periodically periodically
#       check their contents.
#
#   Required settings
#
#       If `spamassassin' program is available, define this variable in your
#       `~/.procmailrc'. Use absolute path to make the external shell
#       quick; it'll save server load considerably.
#
#           JA_UBE_SPAMASSASSIN_PRG = /usr/bin/spamassassin
#
#       If you _do_ _not_ have program installed, do not leave the
#       variable lying aroung, because it will keep this subroutine active.
#       Calling a non existing program is not a good idea, so it better to
#       empty the variable if the program is not available.
#
#   Required settings
#
#       None. No dependencies to other procmail modules.
#
#   Call arguments (variables to set before calling)
#
#       o   JA_UBE_SPAMASSASSIN_PRG, path to the program
#       o   JA_UBE_SPAMASSASSIN_MIN_SIZE, minumum message size. Default is
#           100 bytes.
#       o   JA_UBE_SPAMASSASSIN_MAX_SIZE, maximum message size. Default is
#           256 000 bytes (about 256k).
#       o   JA_UBE_SPAMASSASSIN_FORCE, if set to _yes_ then call program no
#           matter what. Normally if there already is `X-Spam-*' header,
#           it is assumed that the message has already been checked
#           and no new checking is needed.
#
#   Return values
#
#       o   ERROR, is set to the return value of program if message was spam.
#       o   ERROR_INFO, is set if case is "unsure".
#
#   Usage example
#
#           PMSRC                   = $HOME/procmail # procmail recipe dir
#
#           <other checks, mailing lists, work mail etc.>
#
#           JA_UBE_SPAMASSASSIN_PRG = "/usr/bin/nice -n 5 /usr/bin/bogofilter"
#           INCLUDERC               = $PMSRC/pm-jaube-prg-spamassassin.rc
#
#           #   The ERROR will contains reason if program classified
#           #   the message into "bad" category.
#
#           :0 :
#           * ! ERROR ?? ^^^^
#           junk.mbox
#
#   File layout
#
#       The layout of this file is managed by Emacs packages tinyprocmail.el
#       and tinytab.el for the 4 tab text placement.
#       See project http://freshmeat.net/projects/emacs-tiny-tools/
#
#   Change Log
#
#       None

dummy = "
========================================================================
pm-jaube-prg-spamassassin.rc: init:"

# ................................................... User variables ...

#   You must define program path, because we don't know
#   if it has been installed in this system or not

JA_UBE_SPAMASSASSIN_PRG      = ${JA_UBE_SPAMASSASSIN_PRG:-""}

#   No user options cannot be passed, because the output would
#   change. This variable is not used.
# JA_UBE_SPAMASSASSIN_PRG_OPT = ${JA_UBE_SPAMASSASSIN_PRG_OPT:-""}

#   Theshold values when to run spamassassin for a message.

JA_UBE_SPAMASSASSIN_MIN_SIZE = ${JA_UBE_SPAMASSASSIN_MIN_SIZE:-100}
JA_UBE_SPAMASSASSIN_MAX_SIZE = ${JA_UBE_SPAMASSASSIN_MAX_SIZE:-256000}

#   Headers of earlier run of the program. No trailing colon.

JA_UBE_SPAMASSASSIN_HEADER_FLAG = ${JA_UBE_SPAMASSASSIN_HEADER_FLAG:-\
"X-Spam-Flag"}

JA_UBE_SPAMASSASSIN_HEADER_STATUS = ${JA_UBE_SPAMASSASSIN_HEADER_STATUS:-\
"X-Spam-Status"}

#   Should we check even if there already was header
#   JA_UBE_SPAMASSASSIN_HEADER ?

JA_UBE_SPAMASSASSIN_FORCE = ${JA_UBE_SPAMASSASSIN_FORCE:-"no"}

# ............................................................ do it ...

ERROR       # Kill variables
ERROR_INFO

:0
*                   JA_UBE_SPAMASSASSIN_PRG          ?? [a-z]
*$ ! 9876543210^0  ^$JA_UBE_SPAMASSASSIN_HEADER_FLAG
*    9876543210^0   JA_UBE_SPAMASSASSIN_FORCE        ?? yes
{
    #   Last, run spamassassin if it has not already been run
    #   system wide at MTA level. NOTE: run spamassassin
    #   absolutely _last_ and only _if_ message was still not
    #   detected as Unsolicited Bulk Email by previous recipes.
    #
    #   A lock is used so that only one program is run at a time.
    #   X-Spam-Flag just tests if systemwide SA has already
    #   been run => Headers are there already and we should save CPU
    #   and not call SA again. Skip too long messages (256K)

    :0
    *$ >      $JA_UBE_SPAMASSASSIN_MIN_SIZE
    *$ <      $JA_UBE_SPAMASSASSIN_MAX_SIZE
    {
        jaubeSaved   = $LINEBUF
        LINEBUF      = $JA_UBE_SPAMASSASSIN_MAX_SIZE

	#  This is Procmail's global variable. Kill it for now.

        PROCMAIL_OVERFLOW

        #  The message must be saved, because if there is
        #  a problem with SA call, it will trash the whole message.

        :0
        * HB ?? ^^\/(.*$)+$
        {
            jaubeSavedMsg = $MATCH
        }

        #   Procmail will set PROCMAIL_OVERFLOW if 'jaubeSavedMsg'
        #   cannot hold the content
        #
        #       procmail: Exceeded LINEBUF
        #       procmail: Assigning "PROCMAIL_OVERFLOW=yes"

        :0 fhbw : spamassassin$LOCKEXT
        * PROCMAIL_OVERFLOW ?? ^^^^
        | ${JA_UBE_SPAMASSASSIN_PRG} ${JA_UBE_SPAMASSASSIN_OPT:-""}

        #   Check if SA trashed the message. This is usually due
        #   to errors in environment.
        #
        #   procmail: Executing "/usr/bin/spamassassin,"
        #   Use of uninitialized value in pattern match (m//) at /usr/share/perl5/Mail/SpamAssassin/ArchiveIterator.pm line 571.
        #   ...
        #   Unable to open : No such file or directory

        :0
        * HB ?? 1^1 ^.+
        { }

        #   If no lines were found, then message was trashed. Restore

        :0 E fhbw
        * jaubeSavedMsg ?? [a-z]
        | echo -e "$jaubeSavedMsg"

        LINEBUF = $jaubeSaved
    }

    :0
    *$  ^$JA_UBE_SPAMASSASSIN_HEADER_FLAG: yes
    *$  ^$JA_UBE_SPAMASSASSIN_HEADER_STATUS: \/.*
    {
        ERROR = "spamassassin; $MATCH"
    }
}

dummy = "pm-jaube-prg-spamassassin.rc: end: $ERROR"

# End of file
