+2003-06-09 Teodor Zlatanov <tzz@lifelogs.com>
+ From Eric Knauel <knauel@informatik.uni-tuebingen.de>
+
+ * spam.el (spam-use-spamoracle): new variable
+ (spam-install-hooks): add spamoracle to the list of conditions
+ for activation of spam-install-hooks
+ (spam-spamoracle): new variable customization group
+ (spam-spamoracle, spam-spamoracle): new variables
+ (spam-group-spam-processor-spamoracle-p)
+ (spam-group-ham-processor-spamoracle-p): new functions
+ (spam-summary-prepare-exit): added spamoracle ham/spam exit processing
+ (spam-list-of-checks, spam-list-of-statistical-checks): add
+ spam-use-spamoracle
+ (spam-check-spamoracle, spam-spamoracle-learn)
+ (spam-spamoracle-learn-ham, spam-spamoracle-learn-spam): new functions
+
+ * gnus.el (gnus-group-spam-exit-processor-spamoracle)
+ (gnus-group-ham-exit-processor-spamoracle): new variables for SpamOracle
+ (spam-process, ham-process): added spamoracle spam/ham processors
+
2003-06-08 Jesper Harder <harder@ifa.au.dk>
* message.el (message-beginning-of-line): Docstring improvement.
"The Gmane reporting summary exit spam processor.
Only applicable to NNTP groups with articles from Gmane. See spam-report.el")
+ (defvar gnus-group-spam-exit-processor-spamoracle "spamoracle-spam"
+ "The spamoracle summary exit spam processor.")
+
(defvar gnus-group-ham-exit-processor-ifile "ifile-ham"
"The ifile summary exit ham processor.
Only applicable to non-spam (unclassified and ham) groups.")
"The ham copy exit ham processor.
Only applicable to non-spam (unclassified and ham) groups.")
+ (defvar gnus-group-ham-exit-processor-spamoracle "spamoracle-ham"
+ "The spamoracle summary exit ham processor.
+Only applicable to non-spam (unclassified and ham) groups.")
+
(gnus-define-group-parameter
spam-process
:type list
(variable-item gnus-group-spam-exit-processor-bogofilter)
(variable-item gnus-group-spam-exit-processor-blacklist)
(variable-item gnus-group-spam-exit-processor-report-gmane)
+ (variable-item gnus-group-spam-exit-processor-spamoracle)
(variable-item gnus-group-ham-exit-processor-bogofilter)
(variable-item gnus-group-ham-exit-processor-ifile)
(variable-item gnus-group-ham-exit-processor-stat)
(variable-item gnus-group-ham-exit-processor-whitelist)
(variable-item gnus-group-ham-exit-processor-BBDB)
- (variable-item gnus-group-ham-exit-processor-copy))))
+ (variable-item gnus-group-ham-exit-processor-copy)
+ (variable-item gnus-group-ham-exit-processor-spamoracle))))
:function-document
"Which spam or ham processors will be applied to the GROUP articles at summary exit."
:variable gnus-spam-process-newsgroups
:type 'boolean
:group 'spam)
+(defcustom spam-use-spamoracle nil
+ "Whether spamoracle should be used by spam-split."
+ :type 'boolean
+ :group 'spam)
+
(defcustom spam-install-hooks (or
spam-use-dig
spam-use-blacklist
spam-use-BBDB
spam-use-BBDB-exclusive
spam-use-ifile
- spam-use-stat)
+ spam-use-stat
+ spam-use-spamoracle)
"Whether the spam hooks should be installed, default to t if one of
the spam-use-* variables is set."
:group 'gnus-registry
(const :tag "Use the default"))
:group 'spam-ifile)
+(defgroup spam-spamoracle nil
+ "Spam ifile configuration."
+ :group 'spam)
+
+(defcustom spam-spamoracle-database nil
+ "Location of spamoracle database file. When nil, use the default
+spamoracle database."
+ :type '(choice (directory :tag "Location of spamoracle database file.")
+ (const :tag "Use the default"))
+ :group 'spam-spamoracle)
+
+(defcustom spam-spamoracle-binary (executable-find "spamoracle")
+ "Location of the spamoracle binary."
+ :type '(choice (directory :tag "Location of the spamoracle binary")
+ (const :tag "Use the default"))
+ :group 'spam-spamoracle)
+
;;; Key bindings for spam control.
(gnus-define-keys gnus-summary-mode-map
(defun spam-group-ham-processor-ifile-p (group)
(spam-group-processor-p group 'gnus-group-ham-exit-processor-ifile))
+(defun spam-group-spam-processor-spamoracle-p (group)
+ (spam-group-processor-p group 'gnus-group-spam-exit-processor-spamoracle))
+
(defun spam-group-ham-processor-bogofilter-p (group)
(spam-group-processor-p group 'gnus-group-ham-exit-processor-bogofilter))
(defun spam-group-ham-processor-copy-p (group)
(spam-group-processor-p group 'gnus-group-ham-exit-processor-copy))
+(defun spam-group-ham-processor-spamoracle-p (group)
+ (spam-group-processor-p group 'gnus-group-ham-exit-processor-spamoracle))
+
;;; Summary entry and exit processing.
(defun spam-summary-prepare ()
(gnus-message 5 "Registering spam with ifile")
(spam-ifile-register-spam-routine))
+ (when (spam-group-spam-processor-spamoracle-p gnus-newsgroup-name)
+ (gnus-message 5 "Registering spam with spamoracle")
+ (spam-spamoracle-learn-spam))
+
(when (spam-group-spam-processor-stat-p gnus-newsgroup-name)
(gnus-message 5 "Registering spam with spam-stat")
(spam-stat-register-spam-routine))
(spam-stat-register-ham-routine))
(when (spam-group-ham-processor-BBDB-p gnus-newsgroup-name)
(gnus-message 5 "Registering ham with the BBDB")
- (spam-BBDB-register-routine)))
+ (spam-BBDB-register-routine))
+ (when (spam-group-ham-processor-spamoracle-p gnus-newsgroup-name)
+ (gnus-message 5 "Registering ham with spamoracle")
+ (spam-spamoracle-learn-ham)))
(when (spam-group-ham-processor-copy-p gnus-newsgroup-name)
(gnus-message 5 "Copying ham")
(spam-use-whitelist . spam-check-whitelist)
(spam-use-BBDB . spam-check-BBDB)
(spam-use-ifile . spam-check-ifile)
+ (spam-use-spamoracle . spam-check-spamoracle)
(spam-use-stat . spam-check-stat)
(spam-use-blackholes . spam-check-blackholes)
(spam-use-hashcash . spam-check-hashcash)
definitely a spam.")
(defvar spam-list-of-statistical-checks
- '(spam-use-ifile spam-use-stat spam-use-bogofilter)
+ '(spam-use-ifile spam-use-stat spam-use-bogofilter spam-use-spamoracle)
"The spam-list-of-statistical-checks list contains all the mail
splitters that need to have the full message body available.")
(spam-get-article-as-string article) nil))))
\f
+;;;; spamoracle
+(defun spam-check-spamoracle ()
+ "Run spamoracle on an article to determine whether it's spam."
+ (let ((article-buffer-name (buffer-name)))
+ (with-temp-buffer
+ (let ((temp-buffer-name (buffer-name)))
+ (save-excursion
+ (set-buffer article-buffer-name)
+ (let ((status
+ (apply 'call-process-region
+ (point-min) (point-max)
+ spam-spamoracle-binary
+ nil temp-buffer-name nil
+ (if spam-spamoracle-database
+ `("-f" ,spam-spamoracle-database "mark")
+ '("mark")))))
+ (if (zerop status)
+ (progn
+ (set-buffer temp-buffer-name)
+ (goto-char (point-min))
+ (when (re-search-forward "^X-Spam: yes;" nil t)
+ spam-split-group))
+ (error "Error running spamoracle" status))))))))
+
+(defun spam-spamoracle-learn (article article-is-spam-p)
+ "Run spamoracle in training mode."
+ (with-temp-buffer
+ (let ((temp-buffer-name (buffer-name)))
+ (save-excursion
+ (goto-char (point-min))
+ (insert-string (spam-get-article-as-string article))
+ (let* ((arg (if article-is-spam-p "-spam" "-good"))
+ (status
+ (apply 'call-process-region
+ (point-min) (point-max)
+ spam-spamoracle-binary
+ nil temp-buffer-name nil
+ (if spam-spamoracle-database
+ `("-f" ,spam-spamoracle-database
+ "add" ,arg)
+ `("add" ,arg)))))
+ (when (not (zerop status))
+ (error "Error running spamoracle" status)))))))
+
+(defun spam-spamoracle-learn-ham ()
+ (spam-generic-register-routine
+ nil
+ (lambda (article)
+ (spam-spamoracle-learn article nil))))
+
+(defun spam-spamoracle-learn-spam ()
+ (spam-generic-register-routine
+ (lambda (article)
+ (spam-spamoracle-learn article t))
+ nil))
+\f
;;;; Hooks
(defun spam-install-hooks-function ()
+2003-06-09 Teodor Zlatanov <tzz@lifelogs.com>
+
+ * gnus.texi (Filtering Spam Using The Spam ELisp Package): new
+ SpamOracle node
+ (SpamOracle): document new SpamOracle code
+
2003-06-07 Jesper Harder <harder@ifa.au.dk>
* gnus.texi (Article Buttons, Splitting in IMAP)
* Bogofilter::
* ifile spam filtering::
* spam-stat spam filtering::
+* SpamOracle::
* Extending the spam elisp package::
@end menu
Spam \e$B$H\e(B ham \e$B$N%W%m%;%C%5!<$H\e(B @code{spam-split} \e$B$N$?$a\e(B
\e$B$N\e(B @code{spam-use-stat} \e$BJQ?t$,Ds6!$5$l$^$9!#\e(B
+@c TRANSLATEME
+@node SpamOracle
+@subsubsection Using SpamOracle with Gnus
+@cindex spam filtering
+@cindex SpamOracle
+@cindex spam
+
+An easy way to filter out spam is to use SpamOracle. SpamOracle is an
+statistical mail filtering tool written by Xavier Leroy and needs to be
+installed separately.
+
+There are several ways to use SpamOracle with Gnus. In all cases, your
+mail is piped through SpamOracle in its @emph{mark} mode. SpamOracle will
+then enter an @samp{X-Spam} header indicating whether it regards the
+mail as a spam mail or not.
+
+One possibility is to run SpamOracle as a @code{:prescript} from the
+@xref{Mail Source Specifiers}, (@pxref{SpamAssassin}). This method has
+the advantage that the user can see the @emph{X-Spam} headers.
+
+The easiest method is to make @code{spam.el} (@pxref{Filtering Spam
+Using The Spam ELisp Package}) call SpamOracle.
+
+@vindex spam-use-spamoracle
+To enable SpamOracle usage by @code{spam.el}, set the variable
+@code{spam-use-spamoracle} to @code{t} and configure the
+@code{nnmail-split-fancy} or @code{nnimap-split-fancy} as described in
+the section @xref{Filtering Spam Using The Spam ELisp Package}. In
+this example the @samp{INBOX} of an nnimap server is filtered using
+SpamOracle. Mails recognized as spam mails will be moved to
+@code{spam-split-group}, @samp{Junk} in this case. Ham messages stay
+in @samp{INBOX}:
+
+@example
+(setq spam-use-spamoracle t
+ spam-split-group "Junk"
+ nnimap-split-inbox '("INBOX")
+ nnimap-split-rule 'nnimap-split-fancy
+ nnimap-split-fancy '(| (: spam-split) "INBOX"))
+@end example
+
+@defvar spam-use-spamoracle
+Set to @code{t} if you want Gnus to enable spam filtering using
+SpamOracle.
+@end defvar
+
+@defvar spam-spamoracle-binary
+Gnus uses the SpamOracle binary called @file{spamoracle} found in the
+user's PATH. Using the variable @code{spam-spamoracle-binary}, this
+can be customized.
+@end defvar
+
+@defvar spam-spamoracle-database
+By default, SpamOracle uses the file @file{~/.spamoracle.db} as a database to
+store its analyses. This is controlled by the variable
+@code{spam-spamoracle-database} which defaults to @code{nil}. That means
+the default SpamOracle database will be used. In case you want your
+database to live somewhere special, set
+@code{spam-spamoracle-database} to this path.
+@end defvar
+
+SpamOracle employs a statistical algorithm to determine whether a
+message is spam or ham. In order to get good results, meaning few
+false hits or misses, SpamOracle needs training. SpamOracle learns the
+characteristics of your spam mails. Using the @emph{add} mode
+(training mode) one has to feed good (ham) and spam mails to
+SpamOracle. This can be done by pressing @kbd{|} in the Summary buffer
+and pipe the mail to a SpamOracle process or using @code{spam.el}'s
+spam- and ham-processors, which is much more convenient. For a
+detailed description of spam- and ham-processors, see @xref{Filtering Spam Using The Spam ELisp Package}.
+
+@defvar gnus-group-spam-exit-processor-spamoracle
+Add this symbol to a group's @code{spam-process} parameter by
+customizing the group parameter or the
+@code{gnus-spam-process-newsgroups} variable. When this symbol is added
+to a group's @code{spam-process} parameter, spam-marked articles will be
+sent to SpamOracle as spam samples.
+@end defvar
+
+@defvar gnus-group-ham-exit-processor-spamoracle
+Add this symbol to a group's @code{spam-process} parameter by
+customizing the group parameter or the
+@code{gnus-spam-process-newsgroups} variable. When this symbol is added
+to a grup's @code{spam-process} parameter, the ham-marked articles in
+@emph{ham} groups will be sent to the SpamOracle as samples of ham
+messages. Note that this ham processor has no effect in @emph{spam} or
+@emph{unclassified} groups.
+@end defvar
+
+@emph{Example:} These are the Group Parameters of an group that has been
+classified as a ham group, meaning that it should only contain ham
+messages.
+@example
+ ((spam-contents gnus-group-spam-classification-ham)
+ (spam-process
+ (gnus-group-spam-exit-processor-spamoracle)))
+@end example
+For this group the `gnus-group-spam-exit-processor-spamoracle' is
+installed. If the group contains spam message (e.g. because SpamOracle
+has not had enough sample messages yet) and the user marks some
+messages as spam messages, these messages will be processed by
+@code{gnus-group-spam-exit-processor-spamoracle}. This processor sends
+the messages to SpamOracle as new samples for spam.
+
@node Extending the spam elisp package
@subsubsection Spam elisp \e$B%Q%C%1!<%8$N3HD%\e(B
@cindex spam filtering
* Bogofilter::
* ifile spam filtering::
* spam-stat spam filtering::
+* SpamOracle::
* Extending the spam elisp package::
@end menu
processor, and the @code{spam-use-stat} variable for @code{spam-split}
are provided.
+@node SpamOracle
+@subsubsection Using SpamOracle with Gnus
+@cindex spam filtering
+@cindex SpamOracle
+@cindex spam
+
+An easy way to filter out spam is to use SpamOracle. SpamOracle is an
+statistical mail filtering tool written by Xavier Leroy and needs to be
+installed separately.
+
+There are several ways to use SpamOracle with Gnus. In all cases, your
+mail is piped through SpamOracle in its @emph{mark} mode. SpamOracle will
+then enter an @samp{X-Spam} header indicating whether it regards the
+mail as a spam mail or not.
+
+One possibility is to run SpamOracle as a @code{:prescript} from the
+@xref{Mail Source Specifiers}, (@pxref{SpamAssassin}). This method has
+the advantage that the user can see the @emph{X-Spam} headers.
+
+The easiest method is to make @code{spam.el} (@pxref{Filtering Spam
+Using The Spam ELisp Package}) call SpamOracle.
+
+@vindex spam-use-spamoracle
+To enable SpamOracle usage by @code{spam.el}, set the variable
+@code{spam-use-spamoracle} to @code{t} and configure the
+@code{nnmail-split-fancy} or @code{nnimap-split-fancy} as described in
+the section @xref{Filtering Spam Using The Spam ELisp Package}. In
+this example the @samp{INBOX} of an nnimap server is filtered using
+SpamOracle. Mails recognized as spam mails will be moved to
+@code{spam-split-group}, @samp{Junk} in this case. Ham messages stay
+in @samp{INBOX}:
+
+@example
+(setq spam-use-spamoracle t
+ spam-split-group "Junk"
+ nnimap-split-inbox '("INBOX")
+ nnimap-split-rule 'nnimap-split-fancy
+ nnimap-split-fancy '(| (: spam-split) "INBOX"))
+@end example
+
+@defvar spam-use-spamoracle
+Set to @code{t} if you want Gnus to enable spam filtering using
+SpamOracle.
+@end defvar
+
+@defvar spam-spamoracle-binary
+Gnus uses the SpamOracle binary called @file{spamoracle} found in the
+user's PATH. Using the variable @code{spam-spamoracle-binary}, this
+can be customized.
+@end defvar
+
+@defvar spam-spamoracle-database
+By default, SpamOracle uses the file @file{~/.spamoracle.db} as a database to
+store its analyses. This is controlled by the variable
+@code{spam-spamoracle-database} which defaults to @code{nil}. That means
+the default SpamOracle database will be used. In case you want your
+database to live somewhere special, set
+@code{spam-spamoracle-database} to this path.
+@end defvar
+
+SpamOracle employs a statistical algorithm to determine whether a
+message is spam or ham. In order to get good results, meaning few
+false hits or misses, SpamOracle needs training. SpamOracle learns the
+characteristics of your spam mails. Using the @emph{add} mode
+(training mode) one has to feed good (ham) and spam mails to
+SpamOracle. This can be done by pressing @kbd{|} in the Summary buffer
+and pipe the mail to a SpamOracle process or using @code{spam.el}'s
+spam- and ham-processors, which is much more convenient. For a
+detailed description of spam- and ham-processors, see @xref{Filtering Spam Using The Spam ELisp Package}.
+
+@defvar gnus-group-spam-exit-processor-spamoracle
+Add this symbol to a group's @code{spam-process} parameter by
+customizing the group parameter or the
+@code{gnus-spam-process-newsgroups} variable. When this symbol is added
+to a group's @code{spam-process} parameter, spam-marked articles will be
+sent to SpamOracle as spam samples.
+@end defvar
+
+@defvar gnus-group-ham-exit-processor-spamoracle
+Add this symbol to a group's @code{spam-process} parameter by
+customizing the group parameter or the
+@code{gnus-spam-process-newsgroups} variable. When this symbol is added
+to a grup's @code{spam-process} parameter, the ham-marked articles in
+@emph{ham} groups will be sent to the SpamOracle as samples of ham
+messages. Note that this ham processor has no effect in @emph{spam} or
+@emph{unclassified} groups.
+@end defvar
+
+@emph{Example:} These are the Group Parameters of an group that has been
+classified as a ham group, meaning that it should only contain ham
+messages.
+@example
+ ((spam-contents gnus-group-spam-classification-ham)
+ (spam-process
+ (gnus-group-spam-exit-processor-spamoracle)))
+@end example
+For this group the `gnus-group-spam-exit-processor-spamoracle' is
+installed. If the group contains spam message (e.g. because SpamOracle
+has not had enough sample messages yet) and the user marks some
+messages as spam messages, these messages will be processed by
+@code{gnus-group-spam-exit-processor-spamoracle}. This processor sends
+the messages to SpamOracle as new samples for spam.
+
@node Extending the spam elisp package
@subsubsection Extending the spam elisp package
@cindex spam filtering