+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 ()