+2003-01-09 Teodor Zlatanov <tzz@lifelogs.com>
+
+ * spam.el (spam-check-ifile): fixed call-process-region to use the
+ db parameter only if it's set
+ (spam-ifile-register-with-ifile): ditto
+
2002-01-09 Kevin Greiner <kgreiner@xpediantsolutions.com>
* gnus-agent.el (gnus-agent-catchup): Do not mark cached nor
"Get the command-line parameter for ifile's database from spam-ifile-database-path."
(if spam-ifile-database-path
(format "--db-file=%s" spam-ifile-database-path)
- ""))
+ nil))
(defun spam-check-ifile ()
"Check the ifile backend for the classification of this message"
(let ((article-buffer-name (buffer-name))
category return)
(with-temp-buffer
- (let ((temp-buffer-name (buffer-name)))
+ (let ((temp-buffer-name (buffer-name))
+ (db-param (spam-get-ifile-database-parameter)))
(save-excursion
(set-buffer article-buffer-name)
- (call-process-region (point-min) (point-max) spam-ifile-path
- nil temp-buffer-name nil
- "-q" "-c" (spam-get-ifile-database-parameter)))
+ (if db-param
+ (call-process-region (point-min) (point-max) spam-ifile-path
+ nil temp-buffer-name nil "-q" "-c" db-param)
+ (call-process-region (point-min) (point-max) spam-ifile-path
+ nil temp-buffer-name nil "-q" "-c")))
(goto-char (point-min))
(if (not (eobp))
(setq category (buffer-substring (point) (spam-point-at-eol))))
;; else, if spam-ifile-all-categories is not set...
(when (string-equal spam-ifile-spam-category category)
;; always accept the ifile category
- (setq return spam-split-group))))))
+ (setq return spam-split-group))))))
return))
(defun spam-ifile-register-with-ifile (article-string category)
"Register an article, given as a string, with a category.
Uses `gnus-newsgroup-name' if category is nil (for ham registration)."
(when (stringp article-string)
- (let ((category (or category gnus-newsgroup-name)))
+ (let ((category (or category gnus-newsgroup-name))
+ (db-param (spam-get-ifile-database-parameter)))
(with-temp-buffer
(insert-string article-string)
- (call-process-region (point-min) (point-max) spam-ifile-path
- nil nil nil
- "-h" "-i" category
- (spam-get-ifile-database-parameter))))))
+ (if db-param
+ (call-process-region (point-min) (point-max) spam-ifile-path
+ nil nil nil
+ "-h" "-i" category db-param)
+ (call-process-region (point-min) (point-max) spam-ifile-path
+ nil nil nil
+ "-h" "-i" category))))))
(defun spam-ifile-register-spam-routine ()
(spam-generic-register-routine
+2003-01-09 Teodor Zlatanov <tzz@lifelogs.com>
+
+ * gnus.texi (Filtering Spam Using spam.el, ifile spam filtering)
+ (spam-stat spam filtering): added new functionality and explained
+ old functionality better, especially where it has changed in
+ ham/spam/unclassified group exit processing.
+
+2003-01-09 Alex Schroeder <alex@emacswiki.org>
+
+ * gnus.texi (Splitting mail using spam-stat): Fix typo.
+ (Creating a spam-stat dictionary, Splitting mail using spam-stat):
+ Fix markup in a few places.
+
2003-01-08 Lars Magne Ingebrigtsen <larsi@gnus.org>
* gnus.texi (Positioning Point): %~ => ~*.
@emph{Spam} \e$B%0%k!<%W$rH4$1$k$H$-$K!"\e(Bspam \e$B0u$,IU$$$F$$$k$9$Y$F$N5-;v\e(B
\e$B$K$O\e(B spam \e$B%W%m%;%C%5!<$G=hM}$7$?8e$G4|8B@Z$l>C5n$N0u$,IU$1$i$l$^$9!#$3$l\e(B
-\e$B$O\e(B @emph{\e$BL$J,N`\e(B} \e$B$^$?$O\e(B @emph{ham} \e$B%0%k!<%W$KBP$7$F$O9T$J$o$l$^$;$s!#\e(B
+\e$B$O\e(B @emph{\e$BL$J,N`\e(B} \e$B$^$?$O\e(B @emph{ham} \e$B%0%k!<%W$KBP$7$F$O9T$J$o$l$^$;$s!#$5\e(B
+\e$B$i$K\e(B spam \e$B%0%k!<%W$K$"$k$I$N\e(B @strong{ham} \e$B5-;v$b!"\e(B
+@code{ham-process-destination} \e$B%0%k!<%W%Q%i%a!<%?\e(B
+\e$B$+\e(B @code{gnus-ham-process-destinations} \e$BJQ?t$N$I$A$i$+$G7h$a$i$l$F$$$k>l\e(B
+\e$B=j$K0\$5$l$^$9!#>l=j$H$$$&$N$O%0%k!<%WL>$N$3$H$G$9!#\e(B
+@code{ham-process-destination} \e$B%Q%i%a!<%?$,@_Dj$5$l$F$$$J$$$H!"\e(Bspam \e$B5-;v\e(B
+\e$B$OC1$K4|8B@Z$l>C5n$5$l$^$9!#\e(B
@emph{Ham} \e$B%0%k!<%W$rH4$1$k$H$-$K!"\e(Bham \e$B0u$,IU$$$F$$$k$9$Y$F$N5-;v\e(B
\e$B$O\e(B ham \e$B%W%m%;%C%5!<$KAw$i$l!"$=$l$i$r\e(B spam \e$B$G$O$J$$I8K\$H$7$F3X=,$7$^$9!#\e(B
-@strong{TODO: @code{spam-use-ifile} \e$B$O8=>u$G$OF0:n$7$^$;$s!#;d\e(B (\e$BLuCm\e(B:
-Teodor Zlatanov) \e$B$O$=$N5!G=$,\e(B @code{spam.el} \e$B$G$O$J$/\e(B
-\e$B$F\e(B @code{ifile-gnus.el} \e$B$G9T$J$o$l$k$Y$-$@$H;W$&$N$G!"\e(B
-@code{ifile-gnus.el} \e$B$N:n<T$+$i$N\e(B info \e$B$rBT$C$F$$$^$9!#F~$C$F$/$k%a!<%k\e(B
-\e$B$rJ,3d$9$k$?$a$K\e(B ifile \e$B$r;H$$$?$$$H\e(B @code{spam-split} \e$B$KEA$($k$?$a$K!":#\e(B
-\e$B$^$G$I$*$j\e(B @code{spam-use-ifile} \e$B$r;H$&$3$H$O$G$-$^$9!#\e(B}
+@emph{Ham} \e$B$^$?$O\e(B @emph{\e$BL$J,N`\e(B} \e$B%0%k!<%W$rH4$1$k$H$-$K!"$9$Y$F\e(B
+\e$B$N\e(B @strong{spam} \e$B5-;v$O!"\e(B@code{spam-process-destination} \e$B%0%k!<%W%Q%i%a!<\e(B
+\e$B%?$+\e(B @code{gnus-spam-process-destinations} \e$BJQ?t$N$I$A$i$+$G7h$a$i$l$F$$\e(B
+\e$B$k>l=j$K0\$5$l$^$9!#>l=j$H$$$&$N$O%0%k!<%WL>$N$3$H$G$9!#\e(B
+@code{spam-process-destination} \e$B%Q%i%a!<%?$,@_Dj$5$l$F$$$J$$$H!"\e(Bspam \e$B5-\e(B
+\e$B;v$OC1$K4|8B@Z$l>C5n$5$l$^$9!#\e(B
\e$BF~$C$F$/$k%a!<%k$r_I2a$9$kL\E*$G\e(B @code{spam.el} \e$B$r;H$&$K$O!"FC5iJ,3d%j%9\e(B
\e$B%H\e(B @code{nnmail-split-fancy} \e$B$^$?$O\e(B @code{nnimap-split-fancy} \e$B$K0J2<$rDI\e(B
\e$B%U%)%k%H$G$O$=$N%0%k!<%WL>$O\e(B @samp{spam} \e$B$G$9$,!"%+%9%?%^%$%:$9$k$3$H$O\e(B
\e$B2DG=$G$9!#\e(B
+@emph{TODO: \e$B8=>u\e(B spam.el \e$B$O5-;v$r%P%C%/%(%s%I$KEjF~$9$k$3$H$@$1$r%5%]!<\e(B
+\e$B%H$7$^$9!#5-;v$,$b$O$d\e(B spam \e$B$^$?$O\e(B ham \e$B$G$O$J$$$H\e(B spam.el \e$B$KEA$($kJ}K!$O\e(B
+\e$B$"$j$^$;$s!#\e(B}
+
+@emph{TODO: spam.el \e$B$O$9$Y$F$NE}7W%G!<%?%Y!<%9$r71N}$9$k$?$a$N0lDjITJQ$N\e(B
+\e$BJ}K!$rDs6!$9$kI,MW$,$"$j$^$9!#$$$/$D$+$O$=$N5!G=$r<+A0$G;}$C$F$$$^$9$,!"\e(B
+\e$B$=$&$G$J$$$b$N$b$"$j$^$9!#\e(B}
+
\e$B0J2<$O\e(B @code{spam-split} \e$B$NF0:n$r@)8f$9$k$?$a$K;H$&$3$H$,$G$-$k3F<o$NJ}\e(B
\e$BK!$H!"$=$l$i$KBP1~$9$k\e(B spam \e$B$H\e(B ham \e$B$N%W%m%;%C%5!<$G$9\e(B:
* BBDB Whitelists::
* Blackholes::
* Bogofilter::
-* Ifile spam filtering::
+* ifile spam filtering::
+* spam-stat filtering::
* Extending spam.el::
@end menu
\e$B$D$N\e(B spam \e$B%W%m%;%C%5!<$G$"$k$3$H$KCm0U$7$F2<$5$$!#\e(B}
@end defvar
-@node Ifile spam filtering
-@subsubsection Ifile \e$B$K$h$k\e(B spam \e$B$N_I2a\e(B
+@node ifile spam filtering
+@subsubsection ifile \e$B$K$h$k\e(B spam \e$B$N_I2a\e(B
@cindex spam filtering
@cindex ifile, spam filtering
@cindex spam.el
@defvar spam-use-ifile
-Bogofilter \e$B$K;w$?E}7WJ,@O4o$G$"$k\e(B Ifile \e$B$r\e(B @code{spam-split} \e$B$K;H$$$?$$\e(B
-\e$B>l9g$O!"$3$NJQ?t$rM-8z$K$7$F2<$5$$!#:#$N$H$3\e(B
-\e$B$m\e(B @code{ifile-gnus.el} \e$B$r\e(B load \e$B$7$J$1$l$P$J$j$^$;$s!#\e(B
-Ifile \e$B$N\e(B @code{spam.el} \e$B$X$NE}9g$O$^$@:Q$s$G$$$^$;$s$,!"$=$l$r9%$`$J$i\e(B
-\e$B$P\e(B @code{ifile-gnus.el} \e$B$rC1FH$K;H$&$3$H$,$G$-$^$9!#\e(B
+Bogofilter \e$B$K;w$?E}7WJ,@O4o$G$"$k\e(B ifile \e$B$r\e(B @code{spam-split} \e$B$K;H$$$?$$\e(B
+\e$B>l9g$O!"$3$NJQ?t$rM-8z$K$7$F2<$5$$!#\e(B
+
+@end defvar
+
+@defvar spam-ifile-all-categories
+
+@c TRANSLATEME!
+Enable this variable if you want @code{spam-use-ifile} to give you all
+the ifile categories, not just spam/non-spam. If you use this, make
+sure you train ifile as described in its documentation.
+
+@end defvar
+
+@defvar spam-ifile-spam-category
+
+This is the category of spam messages as far as ifile is concerned.
+The actual string used is irrelevant, but you probably want to leave
+the default value of @samp{spam}.
+@end defvar
+
+@defvar spam-ifile-database-path
+
+This is the filename for the ifile database. It is not specified by
+default, so ifile will use its own default database name.
@end defvar
-Ifile \e$B$O!"\e(B@code{spam-split} \e$B$rDL$7$FF~$C$FMh$?%a!<%k$r\e(B spam \e$B$H\e(B ham \e$B$K_I\e(B
-\e$B2a$9$k$@$1$N$?$a$K;H$&$3$H$,$G$-$^$9!#$=$l$O\e(B @code{ifile-gnus.el} \e$B$N<!$N\e(B
-\e$B%j%j!<%9$r;}$D\e(B @code{spam.el} \e$B$K0lAX$h$/E}9g$5$l$k$G$7$g$&!#\e(B
+The ifile mail classifier is similar to Bogofilter in intent and
+purpose. A ham and a spam processor are provided, plus the
+@code{spam-use-ifile} variable to indicate to spam-split that ifile
+should be used. The 1.2.1 version of ifile was used to test this
+functionality.
+
+@node spam-stat spam filtering
+@subsubsection spam-stat spam filtering
+@cindex spam filtering
+@cindex spam-stat, spam filtering
+@cindex spam-stat.el
+@cindex spam.el
+
+@xref{Filtering Spam Using Statistics (spam-stat.el)}.
+
+@defvar spam-use-stat
+
+Enable this variable if you want @code{spam-split} to use
+spam-stat.el, an Emacs Lisp statistical analyzer.
+
+@end defvar
+
+@defvar gnus-group-spam-exit-processor-stat
+Add this symbol to a group's @code{spam-process} parameter by
+customizing the group parameters or the
+@code{gnus-spam-process-newsgroups} variable. When this symbol is
+added to a group's @code{spam-process} parameter, the spam-marked
+articles will be added to the spam-stat database of spam messages.
+@end defvar
+
+@defvar gnus-group-ham-exit-processor-stat
+Add this symbol to a group's @code{spam-process} parameter by
+customizing the group parameters or the
+@code{gnus-spam-process-newsgroups} variable. When this symbol is
+added to a group's @code{spam-process} parameter, the ham-marked
+articles in @emph{ham} groups will be added to the spam-stat database
+of non-spam messages. Note that this ham processor has no effect in
+@emph{spam} or @emph{unclassified} groups.
+@end defvar
+
+This enables spam.el to cooperate with spam-stat.el. spam-stat.el
+provides an internal (Lisp-only) spam database, which unlike ifile or
+Bogofilter does not require external programs. A spam and a ham
+processor, and the @code{spam-use-stat} variable for @code{spam-split}
+are provided.
@node Extending spam.el
@subsubsection spam.el \e$B$N3HD%\e(B
\e$B$N\e(B -- \e$B$r;}$A$^$9!#$3$N%O%C%7%e%F!<%V%k$O!"APJ}$N%3%l%/%7%g%s$N$9$Y$F$NC1\e(B
\e$B8l$K$D$$$F\e(B spam \e$B$*$h$SHs\e(B-spam \e$B%a!<%k$K$*$1$k=P8=IQEY$rI=$9%Y%/%H%k$r3JG<\e(B
\e$B$7$^$9!#\e(B
+@end defvar
\e$BE}7W$r:G=i$+$i:n$jD>$7$?$$$H$-$O!"<-=q$r%j%;%C%H$9$kI,MW$,$"$j$^$9!#\e(B
-@end defvar
-
@defun spam-stat-reset
@code{spam-stat} \e$B%O%C%7%e%F!<%V%k$r%j%;%C%H$7!"$9$Y$F$NE}7W$r:o=|$7$^$9!#\e(B
+@end defun
\e$B9T$J$C$?$i<-=q$r%;!<%V$7$J$1$l$P$J$j$^$;$s!#<-=q$O$+$J$jBg$-$/$J$k$+$b$7\e(B
\e$B$l$^$;$s!#<-=q$rDI2C99?7$7$J$$>l9g\e(B (\e$B8@$$49$($k$H!"Nc$($PKh7n0l2s:n$jD>$9\e(B
\e$B>l9g\e(B)\e$B!"IQHK$K8=$l$J$$$+!"$^$?$O\e(B spam \e$B$+Hs\e(B-spam \e$B$N$I$A$i$KB0$9$k$+$,$O$C\e(B
\e$B$-$j$7$J$$$9$Y$F$NC18l$r:o=|$9$k$3$H$K$h$C$F!"<-=q$N%5%$%:$r>.$5$/$9$k$3\e(B
\e$B$H$,$G$-$^$9!#\e(B
-@end defun
@defun spam-stat-reduce-size
\e$B<-=q$N%5%$%:$r>.$5$/$7$^$9!#$3$l$O<-=q$rDI2C99?7$7$?$/$J$$>l9g$@$1;H$C$F\e(B
@code{spam-stat} \e$B$r;H$&$?$a$N<g%$%s%?!<%U%'!<%9$O0J2<$N4X?t$G$9\e(B:
@defun spam-stat-buffer-is-spam
-Spam \e$B$G$"$k$H9M$($i$l$k?7Ce%a!<%k$,$"$k%P%C%U%!$G8F$P$l$^$9\e(B; \e$B=hM}A0$N?7\e(B
+Spam \e$B$G$"$k$H9M$($i$l$k?7Ce%a!<%k$,$"$k%P%C%U%!$G8F$P$l$^$9!#=hM}A0$N?7\e(B
\e$BCe%a!<%k$KBP$7$F;H$C$F2<$5$$!#\e(B
-
@end defun
@defun spam-stat-buffer-is-no-spam
-\e$BHs\e(B-spam \e$B$G$"$k$H9M$($i$l$k?7Ce%a!<%k$,$"$k%P%C%U%!$G8F$P$l$^$9\e(B; \e$B=hM}A0$N\e(B
+\e$BHs\e(B-spam \e$B$G$"$k$H9M$($i$l$k?7Ce%a!<%k$,$"$k%P%C%U%!$G8F$P$l$^$9!#=hM}A0$N\e(B
\e$B?7Ce%a!<%k$KBP$7$F;H$C$F2<$5$$!#\e(B
-
@end defun
@defun spam-stat-buffer-change-to-spam
Spam \e$B$G$O$J$$DL>o$N%a!<%k$@$H$O$b$O$d9M$($i$l$J$$%a!<%k$,$"$k%P%C%U%!$G\e(B
-\e$B8F$P$l$^$9\e(B; \e$B$9$G$KHs\e(B-spam \e$B$G$"$k$b$N$H$7$F=hM}$5$l$F$7$^$C$?%a!<%k$NCO0L\e(B
+\e$B8F$P$l$^$9!#$9$G$KHs\e(B-spam \e$B$G$"$k$b$N$H$7$F=hM}$5$l$F$7$^$C$?%a!<%k$NCO0L\e(B
\e$B$NJQ99$K;H$C$F2<$5$$!#\e(B
-
@end defun
@defun spam-stat-buffer-change-to-non-spam
\e$BDL>o$N%a!<%k$G$O$J$$\e(B spam \e$B$@$H$O$b$O$d9M$($i$l$J$$%a!<%k$,$"$k%P%C%U%!$G\e(B
-\e$B8F$P$l$^$9\e(B; \e$B$9$G$K\e(B spam \e$B$G$"$k$b$N$H$7$F=hM}$5$l$F$7$^$C$?%a!<%k$NCO0L$N\e(B
+\e$B8F$P$l$^$9!#$9$G$K\e(B spam \e$B$G$"$k$b$N$H$7$F=hM}$5$l$F$7$^$C$?%a!<%k$NCO0L$N\e(B
\e$BJQ99$K;H$C$F2<$5$$!#\e(B
-
@end defun
@defun spam-stat-save
-\e$B%O%C%7%e%F!<%V%k$r%U%!%$%k$K%;!<%V$7$^$9\e(B; \e$BJQ?t\e(B @code{spam-stat-file} \e$B$G\e(B
+\e$B%O%C%7%e%F!<%V%k$r%U%!%$%k$K%;!<%V$7$^$9!#JQ?t\e(B @code{spam-stat-file} \e$B$G\e(B
\e$B@_Dj$5$l$?%U%!%$%kL>$,;H$o$l$^$9!#\e(B
-
@end defun
@defun spam-stat-load
-\e$B%O%C%7%e%F!<%V%k$r%U%!%$%k$+$i\e(B load \e$B$7$^$9\e(B; \e$BJQ\e(B
+\e$B%O%C%7%e%F!<%V%k$r%U%!%$%k$+$i\e(B load \e$B$7$^$9!#JQ\e(B
\e$B?t\e(B @code{spam-stat-file} \e$B$G@_Dj$5$l$?%U%!%$%kL>$,;H$o$l$^$9!#\e(B
-
@end defun
@defun spam-stat-score-word
\e$BC18l$N\e(B spam \e$B%9%3%"$rJV$7$^$9!#\e(B
-
@end defun
@defun spam-stat-score-buffer
\e$B%P%C%U%!$N\e(B spam \e$B%9%3%"$rJV$7$^$9!#\e(B
-
@end defun
@defun spam-stat-split-fancy
-\e$BFC5i%a!<%kJ,3d$N$?$a$K!"\e(B@code{nnmail-split-fancy} \e$B$K5,\e(B
-\e$BB'\e(B @samp{(: spam-stat-split-fancy)} \e$B$rDI2C$7$^$9!#\e(B
+\e$BFC5i%a!<%kJ,3d$N$?$a$K$3$N4X?t$r;H$C$F2<$5$$!#\e(B
+@code{nnmail-split-fancy} \e$B$K5,B'\e(B @samp{(: spam-stat-split-fancy)} \e$B$rDI2C\e(B
+\e$B$7$^$9!#\e(B
+@end defun
-\e$B$3$l$K$O\e(B @file{~/.gnus} \e$B$K0J2<$,I,MW$G$9\e(B:
+\e$B$=$l$r;H$&A0$K!"I,$:<-=q$,\e(B load \e$B$5$l$F$$$k$h$&$K$7$F2<$5$$!#$3$l$K\e(B
+\e$B$O\e(B @file{~/.gnus} \e$B%U%!%$%k$K0J2<$,I,MW$G$9\e(B:
@example
(require 'spam-stat)
(spam-stat-load)
@end example
-@end defun
-
\e$BBeI=E*$J%F%9%H$O0J2<$N4X?t8F=P$7$rI,MW$H$7$^$9\e(B:
@example
When you leave a @emph{spam} group, all spam-marked articles are
marked as expired after processing with the spam processor. This is
-not done for @emph{unclassified} or @emph{ham} groups.
+not done for @emph{unclassified} or @emph{ham} groups. Also, any
+@strong{ham} articles in a spam group will be moved to a location
+determined by either the @code{ham-process-destination} group
+parameter or the @code{gnus-ham-process-destinations} variable. The
+location is a group name. If the @code{ham-process-destination}
+parameter is not set, spam articles are only expired.
When you leave a @emph{ham} group, all ham-marked articles are sent to
a ham processor, which will study these as non-spam samples.
-@strong{TODO: The @code{ifile} spam processor does not work at this
-time. I'm waiting for info from the author of @code{ifile-gnus.el},
-because I think that functionality should go in @code{ifile-gnus.el}
-rather than @code{spam.el}. You can still use @code{spam-use-ifile}
-to tell @code{spam-split} you want to use ifile for splitting incoming
-mail.}
+When you leave a @emph{ham} or @emph{unclassified} group, all
+@strong{spam} articles are moved to a location determined by either
+the @code{spam-process-destination} group parameter or the
+@code{gnus-spam-process-destinations} variable. The location is a
+group name. If the @code{spam-process-destination} parameter is not
+set, the spam articles are only expired.
To use the @code{spam.el} facilities for incoming mail filtering, you
must add the following to your fancy split list
@code{spam-split-group}. By default that group name is @samp{spam},
but you can customize it.
+@emph{TODO: Currently, spam.el only supports insertion of articles
+into a backend. There is no way to tell spam.el that an article is no
+longer spam or ham.}
+
+@emph{TODO: spam.el needs to provide a uniform way of training all the
+statistical databases. Some have that functionality built-in, others
+don't.}
+
The following are the methods you can use to control the behavior of
@code{spam-split} and their corresponding spam and ham processors:
* BBDB Whitelists::
* Blackholes::
* Bogofilter::
-* Ifile spam filtering::
+* ifile spam filtering::
+* spam-stat filtering::
* Extending spam.el::
@end menu
processing.}
@end defvar
-@node Ifile spam filtering
-@subsubsection Ifile spam filtering
+@node ifile spam filtering
+@subsubsection ifile spam filtering
@cindex spam filtering
@cindex ifile, spam filtering
@cindex spam.el
@defvar spam-use-ifile
-Enable this variable if you want @code{spam-split} to use Ifile, a
-statistical analyzer similar to Bogofilter. Currently you must have
-@code{ifile-gnus.el} loaded. The integration of Ifile with
-@code{spam.el} is not finished yet, but you can use
-@code{ifile-gnus.el} on its own if you like.
+Enable this variable if you want @code{spam-split} to use ifile, a
+statistical analyzer similar to Bogofilter.
+
+@end defvar
+
+@defvar spam-ifile-all-categories
+
+Enable this variable if you want @code{spam-use-ifile} to give you all
+the ifile categories, not just spam/non-spam. If you use this, make
+sure you train ifile as described in its documentation.
+
+@end defvar
+
+@defvar spam-ifile-spam-category
+
+This is the category of spam messages as far as ifile is concerned.
+The actual string used is irrelevant, but you probably want to leave
+the default value of @samp{spam}.
+@end defvar
+
+@defvar spam-ifile-database-path
+
+This is the filename for the ifile database. It is not specified by
+default, so ifile will use its own default database name.
+
+@end defvar
+
+The ifile mail classifier is similar to Bogofilter in intent and
+purpose. A ham and a spam processor are provided, plus the
+@code{spam-use-ifile} variable to indicate to spam-split that ifile
+should be used. The 1.2.1 version of ifile was used to test this
+functionality.
+
+@node spam-stat spam filtering
+@subsubsection spam-stat spam filtering
+@cindex spam filtering
+@cindex spam-stat, spam filtering
+@cindex spam-stat.el
+@cindex spam.el
+
+@xref{Filtering Spam Using Statistics (spam-stat.el)}.
+
+@defvar spam-use-stat
+
+Enable this variable if you want @code{spam-split} to use
+spam-stat.el, an Emacs Lisp statistical analyzer.
+
+@end defvar
+
+@defvar gnus-group-spam-exit-processor-stat
+Add this symbol to a group's @code{spam-process} parameter by
+customizing the group parameters or the
+@code{gnus-spam-process-newsgroups} variable. When this symbol is
+added to a group's @code{spam-process} parameter, the spam-marked
+articles will be added to the spam-stat database of spam messages.
+@end defvar
+@defvar gnus-group-ham-exit-processor-stat
+Add this symbol to a group's @code{spam-process} parameter by
+customizing the group parameters or the
+@code{gnus-spam-process-newsgroups} variable. When this symbol is
+added to a group's @code{spam-process} parameter, the ham-marked
+articles in @emph{ham} groups will be added to the spam-stat database
+of non-spam messages. Note that this ham processor has no effect in
+@emph{spam} or @emph{unclassified} groups.
@end defvar
-Ifile can only be used to filter incoming mail into spam and ham
-through the @code{spam-split} function. It will be better integrated
-with @code{spam.el} with the next release of @code{ifile-gnus.el}.
+This enables spam.el to cooperate with spam-stat.el. spam-stat.el
+provides an internal (Lisp-only) spam database, which unlike ifile or
+Bogofilter does not require external programs. A spam and a ham
+processor, and the @code{spam-use-stat} variable for @code{spam-split}
+are provided.
@node Extending spam.el
@subsubsection Extending spam.el
dictionary we have been talking about. For every word in either
collection, this hash-table stores a vector describing how often the
word appeared in spam and often it appeared in non-spam mails.
+@end defvar
If you want to regenerate the statistics from scratch, you need to
reset the dictionary.
-@end defvar
-
@defun spam-stat-reset
Reset the @code{spam-stat} hash-table, deleting all the statistics.
+@end defun
When you are done, you must save the dictionary. The dictionary may
be rather large. If you will not update the dictionary incrementally
can reduce the size of the dictionary by deleting all words that did
not appear often enough or that do not clearly belong to only spam or
only non-spam mails.
-@end defun
@defun spam-stat-reduce-size
Reduce the size of the dictionary. Use this only if you do not want
@end defvar
If you also filter mail with specific subjects into other groups, use
-the following expression. It only the mails not matching the regular
+the following expression. Only mails not matching the regular
expression are considered potential spam.
@example
The main interface to using @code{spam-stat}, are the following functions:
@defun spam-stat-buffer-is-spam
-called in a buffer, that buffer is considered to be a new spam mail;
-use this for new mail that has not been processed before
-
+Called in a buffer, that buffer is considered to be a new spam mail.
+Use this for new mail that has not been processed before.
@end defun
@defun spam-stat-buffer-is-no-spam
-called in a buffer, that buffer is considered to be a new non-spam
-mail; use this for new mail that has not been processed before
-
+Called in a buffer, that buffer is considered to be a new non-spam
+mail. Use this for new mail that has not been processed before.
@end defun
@defun spam-stat-buffer-change-to-spam
-called in a buffer, that buffer is no longer considered to be normal
-mail but spam; use this to change the status of a mail that has
-already been processed as non-spam
-
+Called in a buffer, that buffer is no longer considered to be normal
+mail but spam. Use this to change the status of a mail that has
+already been processed as non-spam.
@end defun
@defun spam-stat-buffer-change-to-non-spam
-called in a buffer, that buffer is no longer considered to be spam but
-normal mail; use this to change the status of a mail that has already
-been processed as spam
-
+Called in a buffer, that buffer is no longer considered to be spam but
+normal mail. Use this to change the status of a mail that has already
+been processed as spam.
@end defun
@defun spam-stat-save
-save the hash table to the file; the filename used is stored in the
-variable @code{spam-stat-file}
-
+Save the hash table to the file. The filename used is stored in the
+variable @code{spam-stat-file}.
@end defun
@defun spam-stat-load
-load the hash table from a file; the filename used is stored in the
-variable @code{spam-stat-file}
-
+Load the hash table from a file. The filename used is stored in the
+variable @code{spam-stat-file}.
@end defun
@defun spam-stat-score-word
-return the spam score for a word
-
+Return the spam score for a word.
@end defun
@defun spam-stat-score-buffer
-return the spam score for a buffer
-
+Return the spam score for a buffer.
@end defun
@defun spam-stat-split-fancy
-for fancy mail splitting; add the rule @samp{(: spam-stat-split-fancy)} to
-@code{nnmail-split-fancy}
+Use this function for fancy mail splitting. Add the rule @samp{(:
+spam-stat-split-fancy)} to @code{nnmail-split-fancy}
+@end defun
-This requires the following in your @file{~/.gnus} file:
+Make sure you load the dictionary before using it. This requires the
+following in your @file{~/.gnus} file:
@example
(require 'spam-stat)
(spam-stat-load)
@end example
-@end defun
-
Typical test will involve calls to the following functions:
@example