X-Git-Url: https://cgit.sxemacs.org/?a=blobdiff_plain;f=lisp%2Fspam.el;h=e95baf570b9cd5ef52c22d4c13d3fe4fc366d465;hb=931e64049c6d898e55d204449f536e170937a03c;hp=c4d34b25509e7e2e173459d381ceeb7d529430b8;hpb=c05533ef75245561e6719c5f2b9bf9d7cf7fb0f3;p=gnus diff --git a/lisp/spam.el b/lisp/spam.el index c4d34b255..e95baf570 100644 --- a/lisp/spam.el +++ b/lisp/spam.el @@ -1,5 +1,5 @@ ;;; spam.el --- Identifying spam -;; Copyright (C) 2002 Free Software Foundation, Inc. +;; Copyright (C) 2002, 2003 Free Software Foundation, Inc. ;; Author: Lars Magne Ingebrigtsen ;; Keywords: network @@ -40,6 +40,9 @@ (require 'gnus) ; for the definitions of group content classification and spam processors (require 'message) ;for the message-fetch-field functions +;; for nnimap-split-download-body-default +(eval-when-compile (require 'nnimap)) + ;; autoload executable-find (eval-and-compile ;; executable-find is not autoloaded in Emacs 20 @@ -69,7 +72,15 @@ When nil, only ham and unclassified groups will have their spam moved to the spam-process-destination. When t, spam will also be moved from spam groups." :type 'boolean - :group 'spam-ifile) + :group 'spam) + +(defcustom spam-mark-ham-unread-before-move-from-spam-group nil + "Whether ham should be marked unread before it's moved out of a spam +group according to ham-process-destination. This variable is an +official entry in the international Longest Variable Name +Competition." + :type 'boolean + :group 'spam) (defcustom spam-whitelist (expand-file-name "whitelist" spam-directory) "The location of the whitelist. @@ -100,11 +111,29 @@ The regular expression is matched against the address." :type 'boolean :group 'spam) +(defcustom spam-use-whitelist-exclusive nil + "Whether whitelist-exclusive should be used by spam-split. +Exclusive whitelisting means that all messages from senders not in the whitelist +are considered spam." + :type 'boolean + :group 'spam) + (defcustom spam-use-blackholes nil "Whether blackholes should be used by spam-split." :type 'boolean :group 'spam) +(defcustom spam-use-hashcash nil + "Whether hashcash payments should be detected by spam-split." + :type 'boolean + :group 'spam) + +(defcustom spam-use-regex-headers nil + "Whether a header regular expression match should be used by spam-split. +Also see the variable `spam-spam-regex-headers' and `spam-ham-regex-headers'." + :type 'boolean + :group 'spam) + (defcustom spam-use-bogofilter-headers nil "Whether bogofilter headers should be used by spam-split. Enable this if you pre-process messages with Bogofilter BEFORE Gnus sees them." @@ -122,6 +151,13 @@ Enable this if you want Gnus to invoke Bogofilter on new messages." :type 'boolean :group 'spam) +(defcustom spam-use-BBDB-exclusive nil + "Whether BBDB-exclusive should be used by spam-split. +Exclusive BBDB means that all messages from senders not in the BBDB are +considered spam." + :type 'boolean + :group 'spam) + (defcustom spam-use-ifile nil "Whether ifile should be used by spam-split." :type 'boolean @@ -149,6 +185,11 @@ All unmarked article in such group receive the spam mark on group entry." :type '(repeat (string :tag "Server")) :group 'spam) +(defcustom spam-blackhole-good-server-regex nil + "String matching IP addresses that should not be checked in the blackholes" + :type 'regexp + :group 'spam) + (defcustom spam-ham-marks (list 'gnus-del-mark 'gnus-read-mark 'gnus-killed-mark 'gnus-kill-file-mark 'gnus-low-score-mark) @@ -177,6 +218,16 @@ Such articles will be transmitted to `bogofilter -s' on group exit." :type 'face :group 'spam) +(defcustom spam-regex-headers-spam '("^X-Spam-Flag: YES") + "Regular expression for positive header spam matches" + :type '(repeat (regexp :tag "Regular expression to match spam header")) + :group 'spam) + +(defcustom spam-regex-headers-ham '("^X-Spam-Flag: NO") + "Regular expression for positive header ham matches" + :type '(repeat (regexp :tag "Regular expression to match ham header")) + :group 'spam) + (defgroup spam-ifile nil "Spam ifile configuration." :group 'spam) @@ -198,6 +249,13 @@ Such articles will be transmitted to `bogofilter -s' on group exit." :type 'string :group 'spam-ifile) +(defcustom spam-ifile-ham-category nil + "Name of the ham ifile category. If nil, the current group name will +be used." + :type '(choice (string :tag "Use a fixed category") + (const :tag "Use the current group name")) + :group 'spam-ifile) + (defcustom spam-ifile-all-categories nil "Whether the ifile check will return all categories, or just spam. Set this to t if you want to use the spam-split invocation of ifile as @@ -220,6 +278,21 @@ your main source of newsgroup names." :type 'string :group 'spam-bogofilter) +(defcustom spam-bogofilter-spam-switch "-s" + "The switch that Bogofilter uses to register spam messages." + :type 'string + :group 'spam-bogofilter) + +(defcustom spam-bogofilter-ham-switch "-n" + "The switch that Bogofilter uses to register ham messages." + :type 'string + :group 'spam-bogofilter) + +(defcustom spam-bogofilter-bogosity-positive-spam-header "^\\(Yes\\|Spam\\)" + "The regex on `spam-bogofilter-header' for positive spam identification." + :type 'regexp + :group 'spam-bogofilter) + (defcustom spam-bogofilter-database-directory nil "Directory path of the Bogofilter databases." :type '(choice (directory :tag "Location of the Bogofilter database directory") @@ -275,7 +348,7 @@ your main source of newsgroup names." (spam-group-processor-p group 'gnus-group-ham-exit-processor-ifile)) (defun spam-group-ham-processor-bogofilter-p (group) - (spam-group-processor-p group 'gnus-group-ham-exit-processor-ifile)) + (spam-group-processor-p group 'gnus-group-ham-exit-processor-bogofilter)) (defun spam-group-spam-processor-stat-p (group) (spam-group-processor-p group 'gnus-group-spam-exit-processor-stat)) @@ -289,6 +362,9 @@ your main source of newsgroup names." (defun spam-group-ham-processor-BBDB-p (group) (spam-group-processor-p group 'gnus-group-ham-exit-processor-BBDB)) +(defun spam-group-ham-processor-copy-p (group) + (spam-group-processor-p group 'gnus-group-ham-exit-processor-copy)) + ;;; Summary entry and exit processing. (defun spam-summary-prepare () @@ -296,49 +372,68 @@ your main source of newsgroup names." (add-hook 'gnus-summary-prepare-hook 'spam-summary-prepare) +;; The spam processors are invoked for any group, spam or ham or neither (defun spam-summary-prepare-exit () - ;; The spam processors are invoked for any group, spam or ham or neither - (when (and spam-bogofilter-path - (spam-group-spam-processor-bogofilter-p gnus-newsgroup-name)) - (spam-bogofilter-register-spam-routine)) + (unless gnus-group-is-exiting-without-update-p + (gnus-message 6 "Exiting summary buffer and applying spam rules") + (when (and spam-bogofilter-path + (spam-group-spam-processor-bogofilter-p gnus-newsgroup-name)) + (gnus-message 5 "Registering spam with bogofilter") + (spam-bogofilter-register-spam-routine)) - (when (and spam-ifile-path - (spam-group-spam-processor-ifile-p gnus-newsgroup-name)) - (spam-ifile-register-spam-routine)) + (when (and spam-ifile-path + (spam-group-spam-processor-ifile-p gnus-newsgroup-name)) + (gnus-message 5 "Registering spam with ifile") + (spam-ifile-register-spam-routine)) - (when (spam-group-spam-processor-stat-p gnus-newsgroup-name) - (spam-stat-register-spam-routine)) - - (when (spam-group-spam-processor-bogofilter-p gnus-newsgroup-name) - (spam-blacklist-register-routine)) - - (if spam-move-spam-nonspam-groups-only - (when (not (spam-group-spam-contents-p gnus-newsgroup-name)) - (spam-mark-spam-as-expired-and-move-routine - (gnus-parameter-spam-process-destination gnus-newsgroup-name))) - (spam-mark-spam-as-expired-and-move-routine - (gnus-parameter-spam-process-destination gnus-newsgroup-name))) - - ;; now we redo spam-mark-spam-as-expired-and-move-routine to only - ;; expire spam, in case the above did not expire them - (spam-mark-spam-as-expired-and-move-routine nil) - - (when (spam-group-ham-contents-p gnus-newsgroup-name) - (when (spam-group-ham-processor-whitelist-p gnus-newsgroup-name) - (spam-whitelist-register-routine)) - (when (spam-group-ham-processor-ifile-p gnus-newsgroup-name) - (spam-ifile-register-ham-routine)) - (when (spam-group-ham-processor-bogofilter-p gnus-newsgroup-name) - (spam-bogofilter-register-ham-routine)) - (when (spam-group-ham-processor-stat-p gnus-newsgroup-name) - (spam-stat-register-ham-routine)) - (when (spam-group-ham-processor-BBDB-p gnus-newsgroup-name) - (spam-BBDB-register-routine))) - - ;; now move all ham articles out of spam groups - (when (spam-group-spam-contents-p gnus-newsgroup-name) - (spam-ham-move-routine - (gnus-parameter-ham-process-destination gnus-newsgroup-name)))) + (when (spam-group-spam-processor-stat-p gnus-newsgroup-name) + (gnus-message 5 "Registering spam with spam-stat") + (spam-stat-register-spam-routine)) + + (when (spam-group-spam-processor-blacklist-p gnus-newsgroup-name) + (gnus-message 5 "Registering spam with the blacklist") + (spam-blacklist-register-routine)) + + (if spam-move-spam-nonspam-groups-only + (when (not (spam-group-spam-contents-p gnus-newsgroup-name)) + (spam-mark-spam-as-expired-and-move-routine + (gnus-parameter-spam-process-destination gnus-newsgroup-name))) + (gnus-message 5 "Marking spam as expired and moving it to %s" gnus-newsgroup-name) + (spam-mark-spam-as-expired-and-move-routine + (gnus-parameter-spam-process-destination gnus-newsgroup-name))) + + ;; now we redo spam-mark-spam-as-expired-and-move-routine to only + ;; expire spam, in case the above did not expire them + (gnus-message 5 "Marking spam as expired without moving it") + (spam-mark-spam-as-expired-and-move-routine nil) + + (when (spam-group-ham-contents-p gnus-newsgroup-name) + (when (spam-group-ham-processor-whitelist-p gnus-newsgroup-name) + (gnus-message 5 "Registering ham with the whitelist") + (spam-whitelist-register-routine)) + (when (spam-group-ham-processor-ifile-p gnus-newsgroup-name) + (gnus-message 5 "Registering ham with ifile") + (spam-ifile-register-ham-routine)) + (when (spam-group-ham-processor-bogofilter-p gnus-newsgroup-name) + (gnus-message 5 "Registering ham with Bogofilter") + (spam-bogofilter-register-ham-routine)) + (when (spam-group-ham-processor-stat-p gnus-newsgroup-name) + (gnus-message 5 "Registering ham with spam-stat") + (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))) + + (when (spam-group-ham-processor-copy-p gnus-newsgroup-name) + (gnus-message 5 "Copying ham") + (spam-ham-move-routine + (gnus-parameter-ham-process-destination gnus-newsgroup-name) t)) + + ;; now move all ham articles out of spam groups + (when (spam-group-spam-contents-p gnus-newsgroup-name) + (gnus-message 5 "Moving ham messages from spam group") + (spam-ham-move-routine + (gnus-parameter-ham-process-destination gnus-newsgroup-name))))) (add-hook 'gnus-summary-prepare-exit-hook 'spam-summary-prepare-exit) @@ -346,6 +441,7 @@ your main source of newsgroup names." ;; check the global list of group names spam-junk-mailgroups and the ;; group parameters (when (spam-group-spam-contents-p gnus-newsgroup-name) + (gnus-message 5 "Marking unread articles as spam") (let ((articles gnus-newsgroup-articles) article) (while articles @@ -354,28 +450,44 @@ your main source of newsgroup names." (gnus-summary-mark-article article gnus-spam-mark)))))) (defun spam-mark-spam-as-expired-and-move-routine (&optional group) + (gnus-summary-kill-process-mark) (let ((articles gnus-newsgroup-articles) - article) - (while articles - (setq article (pop articles)) + article tomove) + (dolist (article articles) (when (eq (gnus-summary-article-mark article) gnus-spam-mark) (gnus-summary-mark-article article gnus-expirable-mark) - (when (stringp group) - (let ((gnus-current-article article)) - (gnus-summary-move-article nil group))))))) + (push article tomove))) + + ;; now do the actual move + (when (and tomove + (stringp group)) + (dolist (article tomove) + (gnus-summary-set-process-mark article)) + (when tomove (gnus-summary-move-article nil group)))) + (gnus-summary-yank-process-mark)) -(defun spam-ham-move-routine (&optional group) +(defun spam-ham-move-routine (&optional group copy) + (gnus-summary-kill-process-mark) (let ((articles gnus-newsgroup-articles) - article ham-mark-values mark) - (dolist (mark spam-ham-marks) - (push (symbol-value mark) ham-mark-values)) - - (while articles - (setq article (pop articles)) - (when (and (memq mark ham-mark-values) - (stringp group)) - (let ((gnus-current-article article)) - (gnus-summary-move-article nil group)))))) + article ham-mark-values mark tomove) + (when (stringp group) ; this routine will do nothing + ; without a valid group + (dolist (mark spam-ham-marks) + (push (symbol-value mark) ham-mark-values)) + (dolist (article articles) + (when (memq (gnus-summary-article-mark article) ham-mark-values) + (push article tomove))) + + ;; now do the actual move + (when tomove + (dolist (article tomove) + (when spam-mark-ham-unread-before-move-from-spam-group + (gnus-summary-mark-article article gnus-unread-mark)) + (gnus-summary-set-process-mark article)) + (if copy + (gnus-summary-copy-article nil group) + (gnus-summary-move-article nil group))))) + (gnus-summary-yank-process-mark)) (defun spam-generic-register-routine (spam-func ham-func) (let ((articles gnus-newsgroup-articles) @@ -412,14 +524,32 @@ your main source of newsgroup names." 'line-end-position))) (defun spam-get-article-as-string (article) - (let ((article-string)) + (let ((article-buffer (spam-get-article-as-buffer article)) + article-string) + (when article-buffer + (save-window-excursion + (set-buffer article-buffer) + (setq article-string (buffer-string)))) + article-string)) + +(defun spam-get-article-as-buffer (article) + (let ((article-buffer)) (when (numberp article) (save-window-excursion (gnus-summary-goto-subject article) (gnus-summary-show-article t) - (set-buffer gnus-article-buffer) - (setq article-string (buffer-string)))) - article-string)) + (setq article-buffer (get-buffer gnus-article-buffer)))) + article-buffer)) + +;; disabled for now +;; (defun spam-get-article-as-filename (article) +;; (let ((article-filename)) +;; (when (numberp article) +;; (nnml-possibly-change-directory (gnus-group-real-name gnus-newsgroup-name)) +;; (setq article-filename (expand-file-name (int-to-string article) nnml-current-directory))) +;; (if (file-exists-p article-filename) +;; article-filename +;; nil))) (defun spam-fetch-field-from-fast (article) "Fetch the `from' field quickly, using the internal gnus-data-list function" @@ -440,25 +570,32 @@ your main source of newsgroup names." (defvar spam-list-of-checks '((spam-use-blacklist . spam-check-blacklist) + (spam-use-regex-headers . spam-check-regex-headers) (spam-use-whitelist . spam-check-whitelist) (spam-use-BBDB . spam-check-BBDB) (spam-use-ifile . spam-check-ifile) (spam-use-stat . spam-check-stat) (spam-use-blackholes . spam-check-blackholes) + (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 +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-statistical-checks + '(spam-use-ifile spam-use-stat spam-use-bogofilter) +"The spam-list-of-statistical-checks list contains all the mail +splitters that need to have the full message body available.") + (defun spam-split () "Split this message into the `spam' group if it is spam. This function can be used as an entry in `nnmail-split-fancy', for @@ -466,19 +603,52 @@ example like this: (: spam-split) See the Info node `(gnus)Fancy Mail Splitting' for more details." (interactive) - - ;; load the spam-stat tables if needed - (when spam-use-stat (spam-stat-load)) + (dolist (check spam-list-of-statistical-checks) + (when (symbol-value check) + (widen) + (gnus-message 8 "spam-split: widening the buffer (%s requires it)" + (symbol-name check)) + (return))) +;; (progn (widen) (debug (buffer-string))) (let ((list-of-checks spam-list-of-checks) decision) (while (and list-of-checks (not decision)) (let ((pair (pop list-of-checks))) (when (symbol-value (car pair)) + (gnus-message 5 "spam-split: calling the %s function" (symbol-name (cdr pair))) (setq decision (funcall (cdr pair)))))) (if (eq decision t) nil decision))) + +(defun spam-setup-widening () + (dolist (check spam-list-of-statistical-checks) + (when (symbol-value check) + (setq nnimap-split-download-body-default t)))) + +(add-hook 'gnus-get-new-news-hook 'spam-setup-widening) + + +;;;; Regex headers + +(defun spam-check-regex-headers () + (let (ret found) + (dolist (h-regex spam-regex-headers-ham) + (unless found + (goto-char (point-min)) + (when (re-search-forward h-regex nil t) + (message "Ham regex header search positive.") + (setq found t)))) + (dolist (s-regex spam-regex-headers-spam) + (unless found + (goto-char (point-min)) + (when (re-search-forward s-regex nil t) + (message "Spam regex header search positive." (match-string 1)) + (setq found t) + (setq ret spam-split-group)))) + ret)) + ;;;; Blackholes. @@ -490,29 +660,48 @@ See the Info node `(gnus)Fancy Mail Splitting' for more details." (with-temp-buffer (insert headers) (goto-char (point-min)) + (gnus-message 5 "Checking headers for relay addresses") (while (re-search-forward "\\[\\([0-9]+.[0-9]+.[0-9]+.[0-9]+\\)\\]" nil t) - (message "Blackhole search found host IP %s." (match-string 1)) + (gnus-message 9 "Blackhole search found host IP %s." (match-string 1)) (push (mapconcat 'identity (nreverse (split-string (match-string 1) "\\.")) ".") ips))) (dolist (server spam-blackhole-servers) (dolist (ip ips) - (let ((query-string (concat ip "." server))) - (if spam-use-dig - (let ((query-result (query-dig query-string))) - (when query-result - (message "spam: positive blackhole check '%s'" 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))))))) + (unless (and spam-blackhole-good-server-regex + (string-match spam-blackhole-good-server-regex ip)) + (let ((query-string (concat ip "." server))) + (if spam-use-dig + (let ((query-result (query-dig query-string))) + (when query-result + (gnus-message 5 "(DIG): positive blackhole check '%s'" + query-result) + (push (list ip server query-result) + matches))) + ;; else, if not using dig.el + (when (query-dns query-string) + (gnus-message 5 "positive blackhole check") + (push (list ip server (query-dns query-string 'TXT)) + matches)))))))) (when matches spam-split-group))) +;;;; 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 + + (file-error (progn + (defalias 'mail-check-payment 'ignore) + (defalias 'spam-check-hashcash 'ignore)))) + ;;;; BBDB ;;; original idea for spam-check-BBDB from Alexander Kotelnikov @@ -531,7 +720,7 @@ See the Info node `(gnus)Fancy Mail Splitting' for more details." (let* ((parsed-address (gnus-extract-address-components from)) (name (or (car parsed-address) "Ham Sender")) (net-address (car (cdr parsed-address)))) - (message "Adding address %s to BBDB" from) + (gnus-message 5 "Adding address %s to BBDB" from) (when (and net-address (not (bbdb-search-simple nil net-address))) (bbdb-create-internal name nil net-address nil nil @@ -546,13 +735,15 @@ See the Info node `(gnus)Fancy Mail Splitting' for more details." (spam-enter-ham-BBDB (spam-fetch-field-from-fast article))))) (defun spam-check-BBDB () - "Mail from people in the BBDB is never considered spam" + "Mail from people in the BBDB is classified as ham or non-spam" (let ((who (message-fetch-field "from"))) (when who - (setq who (regexp-quote (cadr - (gnus-extract-address-components who)))) + (setq who (cadr (gnus-extract-address-components who))) (if (bbdb-search-simple nil who) - nil spam-split-group))))) + t + (if spam-use-BBDB-exclusive + spam-split-group + nil)))))) (file-error (progn (defalias 'bbdb-search-simple 'ignore) @@ -606,7 +797,7 @@ Uses `gnus-newsgroup-name' if category is nil (for ham registration)." (let ((category (or category gnus-newsgroup-name)) (db-param (spam-get-ifile-database-parameter))) (with-temp-buffer - (insert-string article-string) + (insert article-string) (if db-param (call-process-region (point-min) (point-max) spam-ifile-path nil nil nil @@ -627,7 +818,7 @@ Uses `gnus-newsgroup-name' if category is nil (for ham registration)." nil (lambda (article) (spam-ifile-register-with-ifile - (spam-get-article-as-string article) nil)))) + (spam-get-article-as-string article) spam-ifile-ham-category)))) ;;;; spam-stat @@ -649,10 +840,9 @@ Uses `gnus-newsgroup-name' if category is nil (for ham registration)." (lambda (article) (let ((article-string (spam-get-article-as-string article))) (with-temp-buffer - (insert-string article-string) + (insert article-string) (spam-stat-buffer-is-spam)))) - nil) - (spam-stat-save)) + nil)) (defun spam-stat-register-ham-routine () (spam-generic-register-routine @@ -660,9 +850,19 @@ Uses `gnus-newsgroup-name' if category is nil (for ham registration)." (lambda (article) (let ((article-string (spam-get-article-as-string article))) (with-temp-buffer - (insert-string article-string) - (spam-stat-buffer-is-non-spam))))) - (spam-stat-save))) + (insert article-string) + (spam-stat-buffer-is-non-spam)))))) + + (defun spam-maybe-spam-stat-load () + (when spam-use-stat (spam-stat-load))) + + (defun spam-maybe-spam-stat-save () + (when spam-use-stat (spam-stat-save))) + + ;; Add hooks for loading and saving the spam stats + (add-hook 'gnus-save-newsrc-hook 'spam-maybe-spam-stat-save) + (add-hook 'gnus-get-top-new-news-hook 'spam-maybe-spam-stat-load) + (add-hook 'gnus-startup-hook 'spam-maybe-spam-stat-load)) (file-error (progn (defalias 'spam-stat-register-ham-routine 'ignore) @@ -706,12 +906,16 @@ Uses `gnus-newsgroup-name' if category is nil (for ham registration)." (insert address "\n") (save-buffer))) -;;; returns nil if the sender is in the whitelist, spam-split-group otherwise +;;; returns t if the sender is in the whitelist, nil or 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) nil spam-split-group)) + (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? @@ -769,19 +973,23 @@ Uses `gnus-newsgroup-name' if category is nil (for ham registration)." (defun spam-check-bogofilter-headers (&optional score) (let ((header (message-fetch-field spam-bogofilter-header))) (when (and header - (string-match "^Yes" header)) + (string-match spam-bogofilter-bogosity-positive-spam-header + header)) (if score (when (string-match "spamicity=\\([0-9.]+\\)" header) (match-string 1 header)) spam-split-group)))) - ;; return something sensible if the score can't be determined (defun spam-bogofilter-score () "Get the Bogofilter spamicity score" (interactive) - (or (spam-check-bogofilter t) - 0)) + (save-window-excursion + (gnus-summary-show-article t) + (set-buffer gnus-article-buffer) + (let ((score (spam-check-bogofilter t))) + (message "Spamicity score %s" score) + (or score "0")))) (defun spam-check-bogofilter (&optional score) "Check the Bogofilter backend for the classification of this message" @@ -804,9 +1012,10 @@ Uses `gnus-newsgroup-name' if category is nil (for ham registration)." (defun spam-bogofilter-register-with-bogofilter (article-string spam) "Register an article, given as a string, as spam or non-spam." (when (stringp article-string) - (let ((switch (if spam "-s" "-n"))) + (let ((switch (if spam spam-bogofilter-spam-switch + spam-bogofilter-ham-switch))) (with-temp-buffer - (insert-string article-string) + (insert article-string) (if spam-bogofilter-database-directory (call-process-region (point-min) (point-max) spam-bogofilter-path