(spam-bogofilter-articles): Select the article
[gnus] / lisp / spam.el
index 8138b7f..433aba0 100644 (file)
 (require 'dns)
 (require 'message)
 
-(autoload 'bbdb-records "bbdb-com")
-
 ;; Attempt to load BBDB macros
 (eval-when-compile
   (condition-case nil
       (require 'bbdb-com)
-    (file-error (defalias 'bbdb-search 'ignore))
-    (error)))
+    (file-error (defalias 'bbdb-search 'ignore))))
 
 ;; autoload executable-find
-(autoload 'executable-find "executable")
+(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"))
+
+;; autoload query-dig
+(eval-and-compile
+  (autoload 'query-dig "dig"))
 
 ;;; Main parameters.
 
+(defvar spam-use-dig t
+  "True if query-dig should be used instead of query-dns.")
+
 (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.")
 
@@ -122,6 +137,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.
@@ -154,23 +171,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.
@@ -184,8 +203,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)))
@@ -195,12 +214,11 @@ See the Info node `(gnus)Fancy Mail Splitting' for more details."
 (defvar spam-blackhole-servers '("bl.spamcop.net"
                                 "relays.ordb.org"
                                 "dev.null.dk"
-                                "relays.visi.com"
-                                "rbl.maps.vix.com")
+                                "relays.visi.com")
   "List of blackhole servers.")
 
 (defun spam-check-blackholes ()
-  "Check the Receieved headers for blackholed relays."
+  "Check the Received headers for blackholed relays."
   (let ((headers (message-fetch-field "received"))
        ips matches)
     (when headers
@@ -216,9 +234,17 @@ See the Info node `(gnus)Fancy Mail Splitting' for more details."
                ips)))
       (dolist (server spam-blackhole-servers)
        (dolist (ip ips)
-         (when (query-dns (concat ip "." server))
-           (push (list ip server (query-dns (concat ip "." server) 'TXT))
-                 matches)))))
+         (let ((query-string (concat ip "." server)))
+           (if spam-use-dig
+               (let ((query-result (query-dig query-string)))
+                 (when query-result
+                   (message "spam detected with blackhole check of relay %s (dig query result '%s')" query-string query-result)
+                   (push (list ip server query-result)
+                         matches)))
+             ;; else, if not using dig.el
+             (when (query-dns query-string)
+               (push (list ip server (query-dns query-string 'TXT))
+                     matches)))))))
     (when matches
       spam-split-group)))
 \f
@@ -272,18 +298,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>
-(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))))
-
-;; let spam-check-bbdb be nil if the BBDB can't be loaded
+;;; original idea from Alexander Kotelnikov <sacha@giotto.sj.ru>
 (condition-case nil
-    (require 'bbdb)
-  (file-error (defalias 'spam-check-bbdb 'ignore)))
+    (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?
@@ -319,6 +358,7 @@ The regular expression is matched against the address.")
        (setq found t
              cache nil)))
     found))
+
 \f
 ;;;; Training via Bogofilter.   Last updated 2002-09-02.
 
@@ -349,7 +389,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
@@ -444,11 +484,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)
@@ -493,7 +538,7 @@ spamicity coefficient of each, and the overall article spamicity."
              (message "%s %d" prefix counter))
            (setq article (pop articles))
            (gnus-summary-goto-subject article)
-           (gnus-summary-select-article)
+           (gnus-summary-show-article t)
            (gnus-eval-in-buffer-window article-copy
              (insert-buffer-substring gnus-original-article-buffer)
              ;; Remove spam classification redundant headers: they may induce