]> code.delx.au - gnu-emacs/blobdiff - lisp/mail/rmail-spam-filter.el
Update copyright year to 2015
[gnu-emacs] / lisp / mail / rmail-spam-filter.el
index 0b16965d9afabdf63c8c59e37e806b1862cfea1c..ef6b6d0d683f200fe27d40dd690721e950918af6 100644 (file)
@@ -1,9 +1,9 @@
 ;;; rmail-spam-filter.el --- spam filter for Rmail, the Emacs mail reader
 
-;; Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
-;;   Free Software Foundation, Inc.
+;; Copyright (C) 2002-2015 Free Software Foundation, Inc.
 ;; Keywords: email, spam, filter, rmail
 ;; Author: Eli Tziperman <eli AT deas.harvard.edu>
+;; Package: rmail
 
 ;; This file is part of GNU Emacs.
 
@@ -317,7 +317,7 @@ it from rmail file.  Called for each new message retrieved by
           ;; that this email is spam, output the email to the spam
           ;; rmail file, mark the email for deletion, leave the
           ;; while loop and return nil so that an rmail summary line
-          ;; wont be displayed for this message: (FIXME ?)
+          ;; won't be displayed for this message: (FIXME ?)
           (if (and (car maybe-spam) (cdr maybe-spam))
               (setq exit-while-loop t)
             ;; Else, spam was not yet found, proceed to next element
@@ -329,13 +329,20 @@ it from rmail file.  Called for each new message retrieved by
           ;; and delete the spam msg if needed:
           (let ((rmail-current-message msg) ; FIXME does this do anything?
                 (action (cdr (assq 'action
-                                   (nth num-element rsf-definitions-alist)))))
+                                   (nth num-element rsf-definitions-alist))))
+                (newfile (not (file-exists-p rsf-file))))
             ;; Check action item in rsf-definitions-alist and do it.
             (cond
              ((eq action 'output-and-delete)
-              ;; FIXME the prompt to write a new file leaves the raw
+              ;; Else the prompt to write a new file leaves the raw
               ;; mbox buffer visible.
+              (and newfile
+                   (rmail-show-message (rmail-first-unseen-message) t))
               (rmail-output rsf-file)
+              ;; Swap back, else rmail-get-new-mail-1 gets confused.
+              (when newfile
+                (rmail-swap-buffers-maybe)
+                (widen))
               ;; Don't delete if automatic deletion after output is on.
               (or rmail-delete-after-output (rmail-delete-message)))
              ((eq action 'delete-spam)
@@ -344,6 +351,58 @@ it from rmail file.  Called for each new message retrieved by
         (setq return-value t)))
     return-value))
 
+(defun rmail-get-new-mail-filter-spam (nnew)
+  "Check the most NNEW recent messages for spam.
+This is called at the end of `rmail-get-new-mail-1' if there is new mail."
+  (let* ((nold (- rmail-total-messages nnew))
+        (nspam 0)
+        (nscan (1+ nold))
+        ;; Save the original deleted state of all the messages.
+        (rdv-old rmail-deleted-vector)
+        errflag)
+    ;; Set all messages undeleted so that the expunge only affects spam.
+    (setq rmail-deleted-vector (make-string (1+ rmail-total-messages) ?\s))
+    (while (and (not errflag) (<= nscan rmail-total-messages))
+      (condition-case nil
+         (or (rmail-spam-filter nscan)
+             (setq nspam (1+ nspam)))
+       (error (setq errflag nscan)))
+      (setq nscan (1+ nscan)))
+    (unwind-protect
+       (if errflag
+           (progn
+             (setq rmail-use-spam-filter nil)
+             (if rsf-beep (ding t))
+             (message "Spam filter error for new message %d, disabled" errflag)
+             (sleep-for rsf-sleep-after-message))
+         (when (> nspam 0)
+           ;; Otherwise sleep or expunge prompt leaves raw mbox buffer showing.
+           (rmail-show-message (or (rmail-first-unseen-message) 1) t)
+           (unwind-protect
+               (progn
+                 (if rsf-beep (ding t))
+                 (message "Rmail spam-filter detected and deleted %d spam \
+message%s"
+                          nspam (if (= 1 nspam) "" "s"))
+                 (sleep-for rsf-sleep-after-message)
+                 (if (rmail-expunge-confirmed) (rmail-only-expunge t)))
+             ;; Swap back, else get-new-mail-1 gets confused.
+             (rmail-swap-buffers-maybe)
+             (widen))))
+      ;; Restore the original deleted state.  Character N refers to message N.
+      (setq rmail-deleted-vector
+           (concat (substring rdv-old 0 (1+ nold))
+                   ;; This still works if we deleted all the new mail.
+                   (substring rmail-deleted-vector (1+ nold)))))
+    ;; Return a message based on the number of spam messages found.
+    (cond
+     (errflag ", error in spam filter")
+     ((zerop nspam) "")
+     ((= 1 nnew) ", and it appears to be spam")
+     ((= nspam nnew) ", and all appear to be spam")
+     (t (format ", and %d appear%s to be spam" nspam
+               (if (= 1 nspam) "s" ""))))))
+
 ;; define functions for interactively adding sender/subject of a
 ;; specific message to the spam definitions while reading it, using
 ;; the menubar:
@@ -355,7 +414,7 @@ it from rmail file.  Called for each new message retrieved by
     ;; to make sure message-subject is actually evaluated and its value
     ;; substituted.
     (add-to-list 'rsf-definitions-alist
-                ;; Note that an empty elment is treated the same as
+                ;; Note that an empty element is treated the same as
                 ;; an absent one, so why does it bother to add them?
                 (list '(from . "")
                       '(to . "")
@@ -495,5 +554,4 @@ checks to see if the old format is used, and updates it if necessary."
 
 (provide 'rmail-spam-filter)
 
-;; arch-tag: 03e1d45d-b72f-4dd7-8f04-e7fd78249746
-;;; rmail-spam-fitler ends here
+;;; rmail-spam-filter ends here