1# pm-jaube-prg-bogofilter -- Interface to bogofilter program
2#
3#   File id
4#
5#       Copyright (C) 1997-2010 Jari Aalto
6#
7#       This program is free software; you can redistribute it and/or
8#       modify it under the terms of the GNU General Public License as
9#       published by the Free Software Foundation; either version 2 of the
10#       License, or (at your option) any later version
11#
12#       This program is distributed in the hope that it will be useful, but
13#       WITHOUT ANY WARRANTY; without even the implied warranty of
14#       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15#       General Public License for more details at
16#       <http://www.gnu.org/copyleft/gpl.html>.
17#
18#   Warning
19#
20#       Put all your Unsolicited Bulk Emacil (aka spam) filters towards the
21#       end of your `~/.procmailrc'. The idea is that valid messages are filed
22#       first (mailing lists, your work and private mail, bounces) and only
23#       the uncategorized messages are checked last.
24#
25#       YOU CANNOT USE THIS PROCMAIL SUBROUTINE UNLESS YOU HAVE TRAINED THE
26#       BAYESIAN PROGRAM FIRST!
27#
28#       To train:
29#
30#           $  rm -f ~/.bogofilter/*.db         # delete database
31#           $  bogofilter -B -n good.msg ...
32#           $  bogofilter -B -s spam.msg ...
33#
34#   Overview of features
35#
36#       o   Implements interface to http://www.sf.net/projects/bogofilter
37#           project.
38#       o   variable `ERROR' is set if message was likely spam.
39#       o   Results are available by default in header
40#           `X-Spam-Bogofilter-Status'.
41#
42#   Description
43#
44#       There are several Bayesian based statistical analysis programs that
45#       study the message's tokens and then classify it into two categories:
46#       good or bad, or if you like, ham and spam. All the Bayesian programs
47#       are not the same, so if you want to achive magic 99.99% probability
48#       the only methodology to do that is to chain several programs in
49#       serially. There is no single program that can solve the UBE detection.
50#       This procmail subroutine implements call interface to program
51#       `bogofilter', which must already have been installed.
52#
53#   About bouncing message back
54#
55#       The general consensus is, that you should not send bounces. The UBE
56#       sender is not there, because the address forged. Do not increase
57#       the network traffic; you will not do any good to anybody by
58#       bouncing messgas -- you just increase mail traffic even more.
59#       Instead save the messages to folders and periodically periodically
60#       check their contents.
61#
62#   Required settings
63#
64#       If `bogofilter' program is available, define this variable in your
65#       `~/.procmailrc'. Use absolute path to make the external shell
66#       quick; it'll save server load considerably.
67#
68#           JA_UBE_BOGOFILTER_PRG = /usr/bin/bogofilter
69#
70#       If you _do_ _not_ have program installed, do not leave the
71#       variable lying aroung, because it will keep this subroutine active.
72#       Calling a non existing program is not a good idea, so it better to
73#       empty the variable if the program is not available.
74#
75#   Required settings
76#
77#       None. No dependencies to other procmail modules.
78#
79#   Call arguments (variables to set before calling)
80#
81#       o   JA_UBE_BOGOFILTER_PRG, path to the program
82#       o   JA_UBE_BOGOFILTER_HEADER_NEW, the header name where the results
83#           are put. If not defined, no header is added.
84#           Defaults to `X-Spam-Bogofilter-Status'
85#       o   JA_UBE_BOGOFILTER_FORCE, if set to _yes_ then call program no matter
86#           what. Normally if there already is `X-Spam-*' header,
87#           it is assumed that the message has already been checked
88#           and no new checking is needed.
89#
90#   Return values
91#
92#       o   ERROR, is set to the return value of program if message was spam.
93#       o   ERROR_INFO, is set if case is "unsure".
94#
95#   Usage example
96#
97#           PMSRC                  = $HOME/procmail # procmail recipe dir
98#
99#           <other checks, mailing lists, work mail etc.>
100#
101#           JA_UBE_BOGOFILTER_PRG  = "/usr/bin/nice -n 5 /usr/bin/bogogilter"
102#           INCLUDERC              = $PMSRC/pm-jaube-prg-bogofilter.rc
103#
104#           #   The ERROR will contains reason if program classified
105#           #   the message into "bad" category.
106#
107#           :0 :
108#           * ! ERROR ?? ^^^^
109#           junk.mbox
110#
111#   File layout
112#
113#       The layout of this file is managed by Emacs packages tinyprocmail.el
114#       and tinytab.el for the 4 tab text placement.
115#       See project http://freshmeat.net/projects/emacs-tiny-tools/
116#
117#   Change Log
118#
119#       None
120
121dummy = "
122========================================================================
123pm-jaube-prg-bogofilter.rc: init:"
124
125# ................................................... User variables ...
126
127#   You must define program path, because we don't know
128#   if it has been installed in this system or not
129
130JA_UBE_BOGOFILTER_PRG             = ${JA_UBE_BOGOFILTER_PRG:-""}
131JA_UBE_BOGOFILTER_OPT		  = ${$JA_UBE_BOGOFILTER_OPT:-""}
132
133#  No user options cannot be passed, because the output would
134#  change. This variable is not used.
135# JA_UBE_BOGOFILTER_PRG_OPT       = ${JA_UBE_BOGOFILTER_PRG_OPT:-""}
136
137#  The original header name.
138
139JA_UBE_BOGOFILTER_HEADER_ORIGINAL = ${JA_UBE_BOGOFILTER_HEADER_ORIGINAL:-"\
140X-Bogosity"}
141
142#   The header name with no colon at the end. If this variable
143#   is empty, then external formail call is saved - results can still
144#   be checked from variable ERROR.
145
146JA_UBE_BOGOFILTER_HEADER_NEW = ${JA_UBE_BOGOFILTER_HEADER:-\
147"X-Spam-bogofilter-Status"}
148
149# Should we check even if there already was already header
150# 'JA_UBE_BOGOFILTER_HEADER' ?
151
152JA_UBE_BOGOFILTER_FORCE = ${JA_UBE_BOGOFILTER_FORCE:-"no"}
153
154# ............................................................ do it ...
155
156ERROR               # Kill variables
157ERROR_INFO
158
159:0
160*                   JA_UBE_BOGOFILTER_PRG          ?? [a-z]
161*$ ! 9876543210^0  ^$JA_UBE_BOGOFILTER_HEADER_NEW
162*    9876543210^0   JA_UBE_BOGOFILTER_FORCE        ?? yes
163{
164    #   This call will add header. Notice that newer version output
165    #   "Ham" instead of "No"
166    #
167    # X-Bogosity: No, tests=bogofilter, spamicity=0.000111, version=0.92.5
168    # X-Bogosity: Ham, tests=bogofilter, spamicity=0.004063, version=0.93.2
169    # X-Bogosity: Unsure, tests=bogofilter, spamicity=0.499327, version=0.92.5
170    # X-Bogosity: Yes, tests=bogofilter, spamicity=1.000000, version=0.92.5
171
172    jaubeBogoHdr   # Kill variable
173
174    :0
175    * ! JA_UBE_BOGOFILTER_HEADER_NEW ?? ^^^^
176    {
177        jaubeBogoHdr = $JA_UBE_BOGOFILTER_HEADER_NEW
178
179	#  -e  = Exit with code 0 if message is ham/unsure.
180	#  -p  = Pass through
181
182        :0 fhbw # : bogofilter$LOCKEXT
183        | $JA_UBE_BOGOFILTER_PRG \
184          -e \
185	  -p \
186          --spam-header-name="$JA_UBE_BOGOFILTER_HEADER_NEW" \
187          $JA_UBE_BOGOFILTER_OPT
188    }
189    :0 E
190    {
191        jaubeBogoHdr = $JA_UBE_BOGOFILTER_HEADER_ORIGINAL
192
193        :0 fhbw : bogofilter$LOCKEXT
194        | $JA_UBE_BOGOFILTER_PRG -e -p $JA_UBE_BOGOFILTER_OPT
195    }
196
197    #   Bogofilter returns three status messages: Yes, Unsure, No|Ham
198    #   Save the value for user to check
199
200    :0
201    *$ ^$jaubeBogoHdr: \/yes.*
202    {
203        ERROR = "bogofilter; $MATCH"
204    }
205    :0 E
206    *$ ^$jaubeBogoHdr: \/unsure.*
207    {
208        ERROR_INFO = "bogofilter; $MATCH"
209    }
210    :0 E
211    *$  ^$jaubeBogoHdr: \/.+
212    {
213        # Do nothing. Just record bogofilter response to log file
214    }
215}
216
217dummy = "pm-jaube-prg-bogofilter.rc: end: $ERROR"
218
219# End of file
220