From f4ae16376c70bed94cb39ccdbd0a2e2a80d14431 Mon Sep 17 00:00:00 2001 From: yamaoka Date: Sun, 14 Dec 2003 12:37:57 +0000 Subject: [PATCH] Synch to Gnus 200312140318. --- lisp/ChangeLog | 30 +++++++++ lisp/gnus.el | 82 +++++++++++++++++++++++++ lisp/spam.el | 186 ++++++++++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 267 insertions(+), 31 deletions(-) diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 183a915..a8b0baf 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,33 @@ +2003-12-13 Teodor Zlatanov + + * spam.el: added some gnus-registry autoloads + (spam-split-symbolic-return): makes spam-split return 'spam + instead of the value of spam-split-group when spam is detected + (spam-split-symbolic-return-positive): makes spam-split return + 'ham instead of nil when ham is detected + (spam-autodetect-recheck-messages): tells spam.el whether it + should recheck all messages in a group, or only the unseen ones + (spam-split-last-successful-check): spam-split will set this to + the last successful check; this was seen as a cleaner approach + than returning a cell like '(spam spam-use-bogofilter) + (spam-list-of-checks): documentation appended + (spam-split): accomodate the spam-split-symbolic-return and + spam-split-symbolic-return-positive variables + (spam-find-spam): new function called when the summary is built + (spam-log-registered-p): checks if a ham or spam registration has + already been done for an article + (spam-check-regex-headers, spam-check-blackholes, spam-check-BBDB) + (spam-check-ifile, spam-check-stat, spam-check-whitelist) + (spam-check-blacklist, spam-check-bogofilter-headers) + (spam-check-spamoracle): respect the spam-split-symbolic-return + and spam-split-symbolic-return-positive variables + (spam-initialize): add spam-find-spam to gnus-summary-prepare-hook + (spam-unload-hook): remove spam-find-spam from + gnus-summary-prepare-hook + + * gnus.el (spam-autodetect, spam-autodetect-methods): new + configuration items for spam autodetection + 2003-12-12 Reiner Steib * gnus-draft.el (gnus-draft-mode-map): Bind `e' to diff --git a/lisp/gnus.el b/lisp/gnus.el index 8673c75..8aaddbd 100644 --- a/lisp/gnus.el +++ b/lisp/gnus.el @@ -1998,6 +1998,88 @@ spam processing, associated with the appropriate processor." "Which spam or ham processors will be applied when the summary is exited.") (gnus-define-group-parameter + spam-autodetect + :type list + :parameter-type + '(boolean :tag "Spam autodetection") + :function-document + "Should spam be autodetected (with spam-split) in this group?" + :variable gnus-spam-autodetect + :variable-default nil + :variable-document + "*Groups in which spam should be autodetected when they are entered. + Only unseen articles will be examined, unless + spam-autodetect-recheck-messages is set." + :variable-group spam + :variable-type + '(repeat + :tag "Autodetection setting" + (list + (regexp :tag "Group Regexp") + boolean)) + :parameter-document + "Spam autodetection. +Only unseen articles will be examined, unless +spam-autodetect-recheck-messages is set.") + + (gnus-define-group-parameter + spam-autodetect-methods + :type list + :parameter-type + '(choice :tag "Spam autodetection-specific methods" + (const none) + (const default) + (set :tag "Use specific methods" + (variable-item spam-use-blacklist) + (variable-item spam-use-regex-headers) + (variable-item spam-use-regex-body) + (variable-item spam-use-whitelist) + (variable-item spam-use-BBDB) + (variable-item spam-use-ifile) + (variable-item spam-use-spamoracle) + (variable-item spam-use-stat) + (variable-item spam-use-blackholes) + (variable-item spam-use-hashcash) + (variable-item spam-use-bogofilter-headers) + (variable-item spam-use-bogofilter))) + :function-document + "Methods to be used for autodetection in each group" + :variable gnus-spam-autodetect-methods + :variable-default nil + :variable-document + "*Methods for autodetecting spam per group. +Requires the spam-autodetect parameter. Only unseen articles +will be examined, unless spam-autodetect-recheck-messages is +set." + :variable-group spam + :variable-type + '(repeat + :tag "Autodetection methods" + (list + (regexp :tag "Group Regexp") + (choice + (const none) + (const default) + (set :tag "Use specific methods" + (variable-item spam-use-blacklist) + (variable-item spam-use-regex-headers) + (variable-item spam-use-regex-body) + (variable-item spam-use-whitelist) + (variable-item spam-use-BBDB) + (variable-item spam-use-ifile) + (variable-item spam-use-spamoracle) + (variable-item spam-use-stat) + (variable-item spam-use-blackholes) + (variable-item spam-use-hashcash) + (variable-item spam-use-bogofilter-headers) + (variable-item spam-use-bogofilter))))) + :parameter-document + "Spam autodetection methods. +Requires the spam-autodetect parameter. Only unseen articles +will be examined, unless spam-autodetect-recheck-messages is +set.") + + (gnus-define-group-parameter spam-process-destination :type list :parameter-type diff --git a/lisp/spam.el b/lisp/spam.el index a8c1bc6..751d7ed 100644 --- a/lisp/spam.el +++ b/lisp/spam.el @@ -60,6 +60,8 @@ ;; autoload gnus-registry (eval-and-compile + (autoload 'gnus-registry-group-count "gnus-registry") + (autoload 'gnus-registry-add-group "gnus-registry") (autoload 'gnus-registry-store-extra-entry "gnus-registry") (autoload 'gnus-registry-fetch-extra "gnus-registry")) @@ -95,6 +97,18 @@ spam groups." :type 'boolean :group 'spam) +(defcustom spam-split-symbolic-return nil + "Whether spam-split should work with symbols or group names." + :type 'boolean + :group 'spam) + +(defcustom spam-split-symbolic-return-positive nil + "Whether spam-split should ALWAYS work with symbols or group + names. Do not set this if you use spam-split in a fancy split + method." + :type 'boolean + :group 'spam) + (defcustom spam-process-ham-in-spam-groups nil "Whether ham should be processed in spam groups." :type 'boolean @@ -125,6 +139,12 @@ configuration." :type 'boolean :group 'spam) +(defcustom spam-autodetect-recheck-messages nil + "Should spam.el recheck all meessages when autodetecting? +Normally this is nil, so only unseen messages will be checked." + :type 'boolean + :group 'spam) + (defcustom spam-whitelist (expand-file-name "whitelist" spam-directory) "The location of the whitelist. The file format is one regular expression per line. @@ -414,6 +434,12 @@ spamoracle database." (defvar spam-old-spam-articles nil "List of old spam articles, generated when a group is entered.") +(defvar spam-split-disabled nil + "If non-nil, spam-split is disabled, and always returns nil.") + +(defvar spam-split-last-successful-check nil + "spam-split will set this to nil or a spam-use-XYZ check if it + finds ham or spam.") ;; convenience functions (defun spam-xor (a b) ; logical exclusive or @@ -814,16 +840,18 @@ spam-use-* variable.") (spam-use-hashcash . spam-check-hashcash) (spam-use-bogofilter-headers . spam-check-bogofilter-headers) (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 + "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 or the symbol 'spam (depending on +spam-split-symbolic-return) 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-statistical-checks @@ -835,9 +863,6 @@ definitely a spam.") "The spam-list-of-statistical-checks list contains all the mail splitters that need to have the full message body available.") -(defvar spam-split-disabled nil - "If non-nil, spam-split is disabled, and always returns nil.") - ;;;TODO: modify to invoke self with each check if invoked without specifics (defun spam-split (&rest specific-checks) "Split this message into the `spam' group if it is spam. @@ -848,6 +873,7 @@ spam-split-group to that string. See the Info node `(gnus)Fancy Mail Splitting' for more details." (interactive) + (setq spam-split-last-successful-check nil) (unless spam-split-disabled (let ((spam-split-group-choice spam-split-group)) (dolist (check specific-checks) @@ -874,11 +900,69 @@ See the Info node `(gnus)Fancy Mail Splitting' for more details." (memq (car pair) specific-checks))) (gnus-message 5 "spam-split: calling the %s function" (symbol-name (cdr pair))) - (setq decision (funcall (cdr pair)))))) + (setq decision (funcall (cdr pair))) + ;; if we got a decision at all, save the current check + (when decision + (setq spam-split-last-successful-check (car pair))) + + (when (eq decision 'spam) + (if spam-split-symbolic-return + (setq decision spam-split-group) + (gnus-error + 5 + (format "spam-split got %s but %s is nil" + (symbol-name decision) + (symbol-name spam-split-symbolic-return)))))))) (if (eq decision t) - nil + (if spam-split-symbolic-return-positive 'ham nil) decision)))))))) +(defun spam-find-spam () + "This function will detect spam in the current newsgroup using spam-split" + (interactive) + + (let* ((group gnus-newsgroup-name) + (autodetect (gnus-parameter-spam-autodetect group)) + (methods (gnus-parameter-spam-autodetect-methods group)) + (first-method (nth 0 methods))) + (when (and autodetect + (not (equal first-method 'none))) + (mapcar + (lambda (article) + (let ((id (spam-fetch-field-message-id-fast article)) + (subject (spam-fetch-field-subject-fast article)) + (sender (spam-fetch-field-from-fast article))) + (unless (and spam-log-to-registry + (spam-log-registered-p id 'incoming)) + (let* ((spam-split-symbolic-return t) + (spam-split-symbolic-return-positive t) + (split-return + (with-temp-buffer + (gnus-request-article-this-buffer + article + group) + (if (or (null first-method) + (equal first-method 'default)) + (spam-split) + (apply 'spam-split methods))))) + (if (equal split-return 'spam) + (gnus-summary-mark-article article gnus-spam-mark)) + + (when (and split-return spam-log-to-registry) + (when (zerop (gnus-registry-group-count id)) + (gnus-registry-add-group + id group subject sender)) + + (spam-log-processing-to-registry + id + 'incoming + split-return + spam-split-last-successful-check + group)))))) + (if spam-autodetect-recheck-messages + gnus-newsgroup-articles + gnus-newsgroup-unseen))))) + (defvar spam-registration-functions ;; first the ham register, second the spam register function ;; third the ham unregister, fourth the spam unregister function @@ -1019,6 +1103,17 @@ functions") (gnus-message 5 (format "%s called with bad ID, type, classification, check, or group" "spam-log-processing-to-registry"))))) +;;; check if a ham- or spam-processor registration has been done +(defun spam-log-registered-p (id type) + (when spam-log-to-registry + (if (and (stringp id) + (spam-process-type-valid-p type)) + (cdr-safe (gnus-registry-fetch-extra id type)) + (progn + (gnus-message 5 (format "%s called with bad ID, type, classification, or check" + "spam-log-registered-p")) + nil)))) + ;;; check if a ham- or spam-processor registration needs to be undone (defun spam-log-unregistration-needed-p (id type classification check) (when spam-log-to-registry @@ -1082,6 +1177,9 @@ functions") (defun spam-check-regex-headers (&optional body) (let ((type (if body "body" "header")) + (spam-split-group (if spam-split-symbolic-return + 'spam + spam-split-group)) ret found) (dolist (h-regex spam-regex-headers-ham) (unless found @@ -1110,6 +1208,9 @@ functions") (defun spam-check-blackholes () "Check the Received headers for blackholed relays." (let ((headers (nnmail-fetch-field "received")) + (spam-split-group (if spam-split-symbolic-return + 'spam + spam-split-group)) ips matches) (when headers (with-temp-buffer @@ -1206,7 +1307,10 @@ functions") (defun spam-check-BBDB () "Mail from people in the BBDB is classified as ham or non-spam" - (let ((who (nnmail-fetch-field "from"))) + (let ((who (nnmail-fetch-field "from")) + (spam-split-group (if spam-split-symbolic-return + 'spam + spam-split-group))) (when who (setq who (nth 1 (gnus-extract-address-components who))) (if (bbdb-search-simple nil who) @@ -1240,6 +1344,9 @@ functions") (defun spam-check-ifile () "Check the ifile backend for the classification of this message" (let ((article-buffer-name (buffer-name)) + (spam-split-group (if spam-split-symbolic-return + 'spam + spam-split-group)) category return) (with-temp-buffer (let ((temp-buffer-name (buffer-name)) @@ -1302,7 +1409,10 @@ Uses `gnus-newsgroup-name' if category is nil (for ham registration)." (defun spam-check-stat () "Check the spam-stat backend for the classification of this message" - (let ((spam-stat-split-fancy-spam-group spam-split-group) ; override + (let ((spam-split-group (if spam-split-symbolic-return + 'spam + spam-split-group)) + (spam-stat-split-fancy-spam-group spam-split-group) ; override (spam-stat-buffer (buffer-name)) ; stat the current buffer category return) (spam-stat-split-fancy))) @@ -1412,19 +1522,25 @@ REMOVE not nil, remove the ADDRESSES." ;;; spam-split-group otherwise (defun spam-check-whitelist () ;; FIXME! Should it detect when file timestamps change? - (unless spam-whitelist-cache - (setq spam-whitelist-cache (spam-parse-list spam-whitelist))) - (if (spam-from-listed-p spam-whitelist-cache) - t - (if spam-use-whitelist-exclusive - spam-split-group - nil))) + (let ((spam-split-group (if spam-split-symbolic-return + 'spam + spam-split-group))) + (unless spam-whitelist-cache + (setq spam-whitelist-cache (spam-parse-list spam-whitelist))) + (if (spam-from-listed-p spam-whitelist-cache) + t + (if spam-use-whitelist-exclusive + spam-split-group + nil)))) (defun spam-check-blacklist () ;; FIXME! Should it detect when file timestamps change? - (unless spam-blacklist-cache - (setq spam-blacklist-cache (spam-parse-list spam-blacklist))) - (and (spam-from-listed-p spam-blacklist-cache) spam-split-group)) + (let ((spam-split-group (if spam-split-symbolic-return + 'spam + spam-split-group))) + (unless spam-blacklist-cache + (setq spam-blacklist-cache (spam-parse-list spam-blacklist))) + (and (spam-from-listed-p spam-blacklist-cache) spam-split-group))) (defun spam-parse-list (file) (when (file-readable-p file) @@ -1515,7 +1631,10 @@ REMOVE not nil, remove the ADDRESSES." ;;;; Bogofilter (defun spam-check-bogofilter-headers (&optional score) - (let ((header (nnmail-fetch-field spam-bogofilter-header))) + (let ((header (nnmail-fetch-field spam-bogofilter-header)) + (spam-split-group (if spam-split-symbolic-return + 'spam + spam-split-group))) (when header ; return nil when no header (if score ; scoring mode (if (string-match "spamicity=\\([0-9.]+\\)" header) @@ -1597,7 +1716,10 @@ REMOVE not nil, remove the ADDRESSES." ;;;; spamoracle (defun spam-check-spamoracle () "Run spamoracle on an article to determine whether it's spam." - (let ((article-buffer-name (buffer-name))) + (let ((article-buffer-name (buffer-name)) + (spam-split-group (if spam-split-symbolic-return + 'spam + spam-split-group))) (with-temp-buffer (let ((temp-buffer-name (buffer-name))) (save-excursion @@ -1670,7 +1792,8 @@ REMOVE not nil, remove the ADDRESSES." (add-hook 'gnus-startup-hook 'spam-maybe-spam-stat-load) (add-hook 'gnus-summary-prepare-exit-hook 'spam-summary-prepare-exit) (add-hook 'gnus-summary-prepare-hook 'spam-summary-prepare) - (add-hook 'gnus-get-new-news-hook 'spam-setup-widening)) + (add-hook 'gnus-get-new-news-hook 'spam-setup-widening) + (add-hook 'gnus-summary-prepare-hook 'spam-find-spam)) (defun spam-unload-hook () "Uninstall the spam.el hooks" @@ -1680,7 +1803,8 @@ REMOVE not nil, remove the ADDRESSES." (remove-hook 'gnus-startup-hook 'spam-maybe-spam-stat-load) (remove-hook 'gnus-summary-prepare-exit-hook 'spam-summary-prepare-exit) (remove-hook 'gnus-summary-prepare-hook 'spam-summary-prepare) - (remove-hook 'gnus-get-new-news-hook 'spam-setup-widening)) + (remove-hook 'gnus-get-new-news-hook 'spam-setup-widening) + (remove-hook 'gnus-summary-prepare-hook 'spam-find-spam)) (when spam-install-hooks (spam-initialize)) -- 1.7.10.4