Synch with Oort Gnus (gnus-ja.texi hasn't been translated yet).
[elisp/gnus.git-] / lisp / spam.el
index 1e6bc45..bb399c4 100644 (file)
 (require 'dns)
 (require 'message)
 
+;; Attempt to load BBDB macros
+(eval-when-compile
+  (condition-case nil
+      (require 'bbdb-com)
+    (file-error (defalias 'bbdb-search 'ignore))))
+
+;; autoload executable-find
+(eval-and-compile
+  ;; executable-find is not autoloaded in Emacs 20
+  (autoload 'executable-find "executable"))
+
+;; autoload ifile-spam-filter
+(eval-and-compile
+  (autoload 'ifile-spam-filter "ifile-gnus"))
+
 ;;; Main parameters.
 
 (defvar spam-use-blacklist t
   "True if the blacklist should be used.")
 
-(defvar spam-use-whitelist t
+(defvar spam-use-whitelist nil
   "True if the whitelist should be used.")
 
 (defvar spam-use-blackholes nil
   ;; FIXME!  Turned off for now.  The DNS routines are said to be flaky.
   "True if blackholes should be used.")
 
-(defvar spam-use-bogofilter t
+(defvar spam-use-bogofilter nil
   "True if bogofilter should be used.")
 
+(defvar spam-use-bbdb nil
+  "True if BBDB should be used.")
+
+(defvar spam-use-ifile nil
+  "True if ifile should be used.")
+
 (defvar spam-split-group "spam"
   "Usual group name where spam should be split.")
 
@@ -110,6 +131,8 @@ Such articles will be transmitted to `bogofilter -s' on group exit.")
 (gnus-define-keys gnus-summary-mode-map
   "St" spam-bogofilter-score
   "Sx" gnus-summary-mark-as-spam
+  "Mst" spam-bogofilter-score
+  "Msx" gnus-summary-mark-as-spam
   "\M-d" gnus-summary-mark-as-spam)
 
 ;;; How to highlight a spam summary line.
@@ -142,23 +165,25 @@ Such articles will be transmitted to `bogofilter -s' on group exit.")
 \f
 ;;;; Spam determination.
 
-;; The following list contains pairs associating a parameter variable with a
-;; spam checking function.  If the parameter variable is true, then the
-;; checking function is called, and its value decides what happens.  Each
-;; individual check may return `nil', `t', or a mailgroup name.  The value
-;; `nil' means that the check does not yield a decision, and so, that further
-;; checks are needed.  The value `t' means that the message is definitely not
-;; spam, and that further spam checks should be inhibited.  Otherwise, a
-;; mailgroup name is returned where the mail should go, and further checks are
-;; also inhibited.  The usual mailgroup name is the value of
-;; `spam-split-group', meaning that the message is definitely a spam.
 
 (defvar spam-list-of-checks
   '((spam-use-blacklist  . spam-check-blacklist)
     (spam-use-whitelist  . spam-check-whitelist)
     (spam-use-bbdb      . spam-check-bbdb)
+    (spam-use-ifile     . spam-check-ifile)
     (spam-use-blackholes . spam-check-blackholes)
-    (spam-use-bogofilter . spam-check-bogofilter)))
+    (spam-use-bogofilter . spam-check-bogofilter))
+"The spam-list-of-checks list contains pairs associating a parameter
+variable with a spam checking function.  If the parameter variable is
+true, then the checking function is called, and its value decides what
+happens.  Each individual check may return `nil', `t', or a mailgroup
+name.  The value `nil' means that the check does not yield a decision,
+and so, that further checks are needed.  The value `t' means that the
+message is definitely not spam, and that further spam checks should be
+inhibited.  Otherwise, a mailgroup name is returned where the mail
+should go, and further checks are also inhibited.  The usual mailgroup
+name is the value of `spam-split-group', meaning that the message is
+definitely a spam.")
 
 (defun spam-split ()
   "Split this message into the `spam' group if it is spam.
@@ -172,8 +197,8 @@ See the Info node `(gnus)Fancy Mail Splitting' for more details."
        decision)
     (while (and list-of-checks (not decision))
       (let ((pair (pop list-of-checks)))
-       (when (eval (car pair))
-         (setq decision (apply (cdr pair))))))
+       (when (symbol-value (car pair))
+         (setq decision (funcall (cdr pair))))))
     (if (eq decision t)
        nil
       decision)))
@@ -260,15 +285,31 @@ The regular expression is matched against the address.")
     (setq spam-whitelist-cache (spam-parse-list spam-whitelist)))
   (if (spam-from-listed-p spam-whitelist-cache) nil spam-split-group))
 
-;;; copied from code by Alexander Kotelnikov <sacha@giotto.sj.ru>
-;; FIXME: assumes that bbdb.el is loaded
-;; FIXME: broken right now, if the "from" field can't be retrieved
-(defun spam-check-bbdb ()
-  "We want messages from people who are in the BBDB not to be split to spam"
-  (let ((who (message-fetch-field "from")))
-    (when who
-      (setq who (regexp-quote (cadr (gnus-extract-address-components who))))
-      (if (bbdb-search (bbdb-records) nil nil who) nil spam-split-group))))
+;;; original idea from Alexander Kotelnikov <sacha@giotto.sj.ru>
+(condition-case nil
+    (progn
+      (require 'bbdb-com)
+      (defun spam-check-bbdb ()
+       "We want messages from people who are in the BBDB not to be split to spam"
+       (let ((who (message-fetch-field "from")))
+         (when who
+           (setq who (regexp-quote (cadr (gnus-extract-address-components who))))
+           (if (bbdb-search (bbdb-records) nil nil who) nil spam-split-group)))))
+  (file-error (setq spam-list-of-checks
+                   (delete (assoc 'spam-use-bbdb spam-list-of-checks)
+                           spam-list-of-checks))))
+
+;;; check the ifile backend; return nil if the mail was NOT classified as spam
+(condition-case nil
+    (progn
+      (require 'ifile-gnus)
+        ;;; 
+      (defun spam-check-ifile ()
+       (let ((ifile-primary-spam-group spam-split-group))
+         (ifile-spam-filter nil))))
+  (file-error (setq spam-list-of-checks
+                   (delete (assoc 'spam-use-ifile spam-list-of-checks)
+                           spam-list-of-checks))))
 
 (defun spam-check-blacklist ()
   ;; FIXME!  Should it detect when file timestamps change?
@@ -304,6 +345,7 @@ The regular expression is matched against the address.")
        (setq found t
              cache nil)))
     found))
+
 \f
 ;;;; Training via Bogofilter.   Last updated 2002-09-02.
 
@@ -334,7 +376,7 @@ The regular expression is matched against the address.")
 ;;;     make install
 ;;;
 ;;; Here as well, you need to become super-user for the last step.  Now,
-;;; initialises your word lists by doing, under your own identity:
+;;; initialize your word lists by doing, under your own identity:
 ;;;
 ;;;     mkdir ~/.bogofilter
 ;;;     touch ~/.bogofilter/badlist
@@ -407,16 +449,6 @@ The regular expression is matched against the address.")
 Markup from spam recognisers, as well as `Xref', are to be removed from
 articles before they get registered by Bogofilter.")
 
-;; FIXME!  I do not know if Gnus has a compatibility function for
-;; `executable-find'.  Here is a possible mantra for portability,
-;; until Lars decides how we really should do it.
-(unless (fboundp 'executable-find)
-  (if (fboundp 'locate-file)
-      (defun executable-find (command)
-       (locate-file command exec-path))
-    (autoload 'executable-find "executable")))
-;; End of portability mantra for `executable-find'.
-
 (defvar spam-bogofilter-path (executable-find "bogofilter")
   "File path of the Bogofilter executable program.
 Force this variable to nil if you want to inhibit the functionality.")
@@ -439,11 +471,16 @@ spamicity coefficient of each, and the overall article spamicity."
   (interactive)
   (when (and spam-use-bogofilter spam-bogofilter-path)
     (spam-bogofilter-articles nil "-v" (list (gnus-summary-article-number)))
-    (save-excursion
-      (set-buffer spam-output-buffer-name)
-      (unless (= (point-min) (point-max))
-       (display-message-or-buffer (current-buffer)
-                                  spam-output-buffer-name)))))
+    (with-current-buffer spam-output-buffer-name
+      (unless (zerop (buffer-size))
+       (if (<= (count-lines (point-min) (point-max)) 1)
+           (progn
+             (goto-char (point-max))
+             (when (bolp)
+               (backward-char 1))
+             (message "%s" (buffer-substring (point-min) (point))))
+         (goto-char (point-min))
+         (display-buffer (current-buffer)))))))
 
 (defun spam-bogofilter-register-routine ()
   (when (and spam-use-bogofilter spam-bogofilter-path)