(spam-check-BBDB, spam-enter-ham-BBDB, spam-parse-list): use
[gnus] / lisp / spam.el
index ee57514..26c0f5b 100644 (file)
@@ -1,8 +1,10 @@
 ;;; spam.el --- Identifying spam
-;; Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+
+;; Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
-;; Keywords: network
+;; Maintainer: Ted Zlatanov <tzz@lifelogs.com>
+;; Keywords: network, spam, mail, bogofilter, BBDB, dspam, dig, whitelist, blacklist, gmane, hashcash, spamassassin, bsfilter, ifile, stat, crm114, spamoracle
 
 ;; This file is part of GNU Emacs.
 
@@ -18,8 +20,8 @@
 
 ;; You should have received a copy of the GNU General Public License
 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
 ;;; Commentary:
 
@@ -40,6 +42,8 @@
 
 (eval-when-compile (require 'cl))
 (eval-when-compile (require 'spam-report))
+(eval-when-compile (require 'hashcash))
+(eval-when-compile (require 'ietf-drums))
 
 (require 'gnus-sum)
 
@@ -58,6 +62,8 @@
 ;; autoload spam-report
 (eval-and-compile
   (autoload 'spam-report-gmane "spam-report")
+  (autoload 'spam-report-gmane-spam "spam-report")
+  (autoload 'spam-report-gmane-ham "spam-report")
   (autoload 'spam-report-resend "spam-report"))
 
 ;; autoload gnus-registry
@@ -80,7 +86,9 @@ Populated by spam-install-backend-super.")
 
 (defgroup spam nil
   "Spam configuration."
-  :version "22.1")
+  :version "22.1"
+  :group 'mail
+  :group 'news)
 
 (defcustom spam-summary-exit-behavior 'default
   "Exit behavior at the time of summary exit.
@@ -102,6 +110,7 @@ a group through group/topic parameters overrides this mechanism."
 (defcustom spam-mark-new-messages-in-spam-group-as-spam t
   "Whether new messages in a spam group should get the spam-mark."
   :type 'boolean
+  ;; :version "22.1" ;; Gnus 5.10.8 / No Gnus 0.3
   :group 'spam)
 
 (defcustom spam-log-to-registry nil
@@ -350,7 +359,7 @@ Only meaningful if you enable `spam-use-blackholes'."
   :type '(radio (const nil) regexp)
   :group 'spam)
 
-(defface spam-face
+(defface spam
   '((((class color) (type tty) (background dark))
      (:foreground "gray80" :background "gray50"))
     (((class color) (type tty) (background light))
@@ -360,9 +369,12 @@ Only meaningful if you enable `spam-use-blackholes'."
     (((class color) (background light))
      (:foreground "ivory4"))
     (t :inverse-video t))
-  "Face for spam-marked articles.")
+  "Face for spam-marked articles."
+  :group 'spam)
+;; backward-compatibility alias
+(put 'spam-face 'face-alias 'spam)
 
-(defcustom spam-face 'spam-face
+(defcustom spam-face 'spam
   "Face for spam-marked articles."
   :type 'face
   :group 'spam)
@@ -1049,11 +1061,10 @@ backends)."
                              nil)
 
 (spam-install-nocheck-backend 'spam-use-gmane
-                             nil
+                             'spam-report-gmane-unregister-routine
                              'spam-report-gmane-register-routine
-                             ;; does Gmane support unregistration?
-                             nil
-                             nil)
+                             'spam-report-gmane-register-routine
+                             'spam-report-gmane-unregister-routine)
 
 (spam-install-nocheck-backend 'spam-use-resend
                              'spam-report-resend-register-ham-routine
@@ -1146,6 +1157,8 @@ backends)."
       (push 'X-Spam-Status list))
     (when spam-use-bogofilter
       (push 'X-Bogosity list))
+    (when spam-use-crm114
+      (push 'X-CRM114-Status list))
     list))
 
 (defun spam-user-format-function-S (headers)
@@ -1164,26 +1177,37 @@ backends)."
        (return))))
     result))
 
+(defvar spam-spamassassin-score-regexp
+  ".*\\b\\(?:score\\|hits\\)=\\(-?[0-9.]+\\)"
+  "Regexp matching SpamAssassin score header.
+The first group must match the number.")
+;; "score" for Spamassassin 3.0 or later:
+;; X-Spam-Status: Yes, score=13.1 required=5.0 tests=DNS_FROM_RFC_ABUSE,
+;;     [...],UNDISC_RECIPS autolearn=disabled version=3.0.3
+
+
 (defun spam-extra-header-to-number (header headers)
   "Transform an extra HEADER to a number, using list of HEADERS.
 Note this has to be fast."
-  (if (gnus-extra-header header headers)
-      (cond
-       ((eq header 'X-Spam-Status)
-       (string-to-number (gnus-replace-in-string
-                          (gnus-extra-header header headers)
-                          ".*hits=" "")))
-       ;; for CRM checking, it's probably faster to just do the string match
-       ((and spam-use-crm114 (string-match "( pR: \\([0-9.-]+\\)" header))
-       (match-string 1 header))
-       ((eq header 'X-Bogosity)
-       (string-to-number (gnus-replace-in-string
-                          (gnus-replace-in-string
-                           (gnus-extra-header header headers)
-                           ".*spamicity=" "")
-                          ",.*" "")))
-       (t nil))
-    nil))
+  (let ((header-content (gnus-extra-header header headers)))
+    (if header-content
+        (cond
+         ((eq header 'X-Spam-Status)
+          (string-to-number (gnus-replace-in-string
+                             header-content
+                             spam-spamassassin-score-regexp
+                             "\\1")))
+         ;; for CRM checking, it's probably faster to just do the string match
+         ((and spam-use-crm114 (string-match "( pR: \\([0-9.-]+\\)" header-content))
+          (string-to-number (match-string 1 header-content)))
+         ((eq header 'X-Bogosity)
+          (string-to-number (gnus-replace-in-string
+                             (gnus-replace-in-string
+                              header-content
+                              ".*spamicity=" "")
+                             ",.*" "")))
+         (t nil))
+      nil)))
 
 (defun spam-summary-score (headers &optional specific-header)
   "Score an article for the summary buffer, as fast as possible.
@@ -1238,6 +1262,7 @@ Will not return a nil score."
     (gnus-group-spam-exit-processor-stat         spam spam-use-stat)
     (gnus-group-spam-exit-processor-spamoracle   spam spam-use-spamoracle)
     (gnus-group-spam-exit-processor-spamassassin spam spam-use-spamassassin)
+    (gnus-group-spam-exit-processor-report-gmane spam spam-use-gmane) ;; Buggy?
     (gnus-group-ham-exit-processor-ifile         ham spam-use-ifile)
     (gnus-group-ham-exit-processor-bogofilter    ham spam-use-bogofilter)
     (gnus-group-ham-exit-processor-bsfilter      ham spam-use-bsfilter)
@@ -2015,18 +2040,10 @@ See the Info node `(gnus)Fancy Mail Splitting' for more details."
 
 ;;{{{ Hashcash.
 
-(eval-when-compile
-  (autoload 'mail-check-payment "hashcash"))
-
-(condition-case nil
-    (progn
-      (require 'hashcash)
-
-      (defun spam-check-hashcash ()
-       "Check the headers for hashcash payments."
-       (mail-check-payment)))   ;mail-check-payment returns a boolean
+(defun spam-check-hashcash ()
+  "Check the headers for hashcash payments."
+  (ignore-errors (mail-check-payment)))         ;mail-check-payment returns a boolean
 
-  (file-error))
 ;;}}}
 
 ;;{{{ BBDB
@@ -2064,12 +2081,12 @@ See the Info node `(gnus)Fancy Mail Splitting' for more details."
       "Enter an address into the BBDB; implies ham (non-spam) sender"
       (dolist (from addresses)
        (when (stringp from)
-         (let* ((parsed-address (gnus-extract-address-components from))
-                (name (or (nth 0 parsed-address) "Ham Sender"))
+         (let* ((parsed-address (ietf-drums-parse-address from))
+                (name (or (nth 1 parsed-address) "Ham Sender"))
                 (remove-function (if remove
                                      'bbdb-delete-record-internal
                                    'ignore))
-                (net-address (nth 1 parsed-address))
+                (net-address (nth 0 parsed-address))
                 (record (and net-address
                              (bbdb-search-simple nil net-address))))
            (when net-address
@@ -2113,7 +2130,7 @@ See the Info node `(gnus)Fancy Mail Splitting' for more details."
                   bbdb-hashtable))))
            (puthash 'spam-use-BBDB bbdb-cache spam-caches)))
        (when who
-         (setq who (nth 1 (gnus-extract-address-components who)))
+         (setq who (car (ietf-drums-parse-address who)))
          (if
              (if spam-cache-lookups
                  (intern-soft (downcase who) bbdb-cache)
@@ -2363,7 +2380,7 @@ REMOVE not nil, remove the ADDRESSES."
          (forward-line 1)
          ;; insert the e-mail address if detected, otherwise the raw data
          (unless (zerop (length address))
-           (let ((pure-address (nth 1 (gnus-extract-address-components address))))
+           (let ((pure-address (car (ietf-drums-parse-address address))))
              (push (or pure-address address) contents)))))
       (nreverse contents))))
 
@@ -2429,7 +2446,11 @@ REMOVE not nil, remove the ADDRESSES."
 ;;{{{ Spam-report glue (gmane and resend reporting)
 (defun spam-report-gmane-register-routine (articles)
   (when articles
-    (apply 'spam-report-gmane articles)))
+    (apply 'spam-report-gmane-spam articles)))
+
+(defun spam-report-gmane-unregister-routine (articles)
+  (when articles
+    (apply 'spam-report-gmane-ham articles)))
 
 (defun spam-report-resend-register-ham-routine (articles)
   (spam-report-resend-register-routine articles t))
@@ -2498,7 +2519,7 @@ REMOVE not nil, remove the ADDRESSES."
                     (if db `("-d" ,db "-v") `("-v"))))
            (setq return (spam-check-bogofilter-headers score))))
        return)
-    (gnus-error "`spam.el' doesnt support obsolete bogofilter versions")))
+    (gnus-error 5 "`spam.el' doesn't support obsolete bogofilter versions")))
 
 (defun spam-bogofilter-register-with-bogofilter (articles
                                                 spam
@@ -2524,7 +2545,7 @@ REMOVE not nil, remove the ADDRESSES."
                     spam-bogofilter-path
                     nil nil nil switch
                     (if db `("-d" ,db "-v") `("-v")))))))
-    (gnus-error "`spam.el' doesnt support obsolete bogofilter versions")))
+    (gnus-error 5 "`spam.el' doesn't support obsolete bogofilter versions")))
 
 (defun spam-bogofilter-register-spam-routine (articles &optional unregister)
   (spam-bogofilter-register-with-bogofilter articles t unregister))
@@ -2609,7 +2630,7 @@ REMOVE not nil, remove the ADDRESSES."
   (if score                            ; scoring mode
       (let ((header (message-fetch-field spam-spamassassin-spam-status-header)))
        (when header
-         (if (string-match "hits=\\(-?[0-9.]+\\)" header)
+         (if (string-match spam-spamassassin-score-regexp header)
              (match-string 1 header)
            "0")))
     ;; spam detection mode
@@ -2878,8 +2899,8 @@ installed through spam-necessary-extra-headers."
     (add-to-list 'gnus-extra-headers header))
 
   (setq spam-install-hooks t)
-  ;; TODO: How do we redo this every time spam-face is customized?
-  (push '((eq mark gnus-spam-mark) . spam-face)
+  ;; TODO: How do we redo this every time the `spam' face is customized?
+  (push '((eq mark gnus-spam-mark) . spam)
        gnus-summary-highlight)
   ;; Add hooks for loading and saving the spam stats
   (add-hook 'gnus-save-newsrc-hook 'spam-maybe-spam-stat-save)