;;; rmail-spam-filter.el --- spam filter for rmail, the emacs mail reader.
-;; Copyright (C) 2002 Free Software Foundation, Inc.
-
+;; Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
;; Keywords: email, spam, filter, rmail
;; Author: Eli Tziperman <eli AT deas.harvard.edu>
;; 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:
;;; -----------
;;; Automatically recognize and delete junk email before it is
;;; displayed in rmail/rmail-summary. Spam emails are defined by
;;; specifying one or more of the sender, subject and contents.
-;;; URL: http://deas.harvard.edu/climate/eli/Downloads/rmail-spam-filter/
+;;; URL: http://www.weizmann.ac.il/~eli/Downloads/rmail-spam-filter/
;;; Usage:
;;; ------
;;; sender's bbdb entry as well _if_ it was created at the same day.
(require 'rmail)
-(require 'rmailsum)
+(if (> emacs-major-version 20)
+ (require 'rmailsum)
+ (if (not (fboundp 'rmail-make-summary-line)) (load-library "rmailsum")))
;; For find-if and other cool common lisp functions we may want to use.
(eval-when-compile
"Spam filter for RMAIL, the mail reader for Emacs."
:group 'rmail)
-;;;###autoload
(defcustom rmail-use-spam-filter nil
"*Non-nil to activate the rmail spam filter.
Specify `rsf-definitions-alist' to define what you consider spam
is spam\\|another spam' (without the single quotes). To specify that
if the contents contain both this and that the message is spam,
specify 'this\\&that' in the appropriate spam definition field."
- :type '(repeat
+ :type '(repeat
(list :format "%v"
(cons :format "%v" :value (from . "")
(const :format "" from)
(string :tag "Contents" ""))
(cons :format "%v" :value (action . output-and-delete)
(const :format "" action)
- (choice :tag "Action selection"
+ (choice :tag "Action selection"
(const :tag "output to spam folder and delete" output-and-delete)
(const :tag "delete spam" delete-spam)
))
;; the advantage over the automatic filter definitions is the AND conjunction
;; of in-one-definition-elements
-(defun rsf-check-field (field-symbol message-data definition result)
+(defun check-field (field-symbol message-data definition result)
"Check if field-symbol is in `rsf-definitions-alist'.
Capture maybe-spam and this-is-a-spam-email in a cons in result,
-where maybe-spam is in first and this-is-a-spam-email is in rest.
+where maybe-spam is in first and this-is-a-spam-email is in rest.
The values are returned by destructively changing result.
If FIELD-SYMBOL field does not exist AND is not specified,
this may still be spam due to another element...
(save-current-msg)
(rsf-saved-bbdb/mail_auto_create_p nil)
)
-
+
;; make sure bbdb does not create entries for messages while spam
;; filter is scanning the rmail file:
(setq rsf-saved-bbdb/mail_auto_create_p 'bbdb/mail_auto_create_p)
;;; do we want to ignore case in spam definitions:
(setq case-fold-search rsf-ignore-case)
-
+
;; Check for blind CC condition. Set vars such that while
;; loop will be bypassed and spam condition will trigger
(if (and rsf-no-blind-cc
;; Check white list, and likewise cause while loop
;; bypass.
- (if (let ((white-list rsf-white-list)
- (found nil))
- (while (and (not found) white-list)
- (if (string-match (car white-list) message-sender)
- (setq found t)
- (setq white-list (cdr white-list))))
- found)
+ (if (and message-sender
+ (let ((white-list rsf-white-list)
+ (found nil))
+ (while (and (not found) white-list)
+ (if (string-match (car white-list) message-sender)
+ (setq found t)
+ (setq white-list (cdr white-list))))
+ found))
(setq exit-while-loop t
maybe-spam nil
this-is-a-spam-email nil))
;; maybe-spam is in first, this-is-a-spam-email in rest, this
- ;; simplifies the call to rsf-check-field
+ ;; simplifies the call to check-field
(setq maybe-spam (cons maybe-spam this-is-a-spam-email))
;; scan all elements of the list rsf-definitions-alist
;; start scanning incoming message:
;;---------------------------------
-
+
;; Maybe the different fields should also be done in a
;; loop to make the whole thing more flexible
;; if sender field is not specified in message being
;; scanned, AND if "from" field does not appear in spam
;; definitions for this element, this may still be spam
;; due to another element...
- (rsf-check-field 'from message-sender definition maybe-spam)
+ (check-field 'from message-sender definition maybe-spam)
;; next, if spam was not ruled out already, check recipients:
- (rsf-check-field 'to message-recipients definition maybe-spam)
+ (check-field 'to message-recipients definition maybe-spam)
;; next, if spam was not ruled out already, check subject:
- (rsf-check-field 'subject message-subject definition maybe-spam)
+ (check-field 'subject message-subject definition maybe-spam)
;; next, if spam was not ruled out already, check content-type:
- (rsf-check-field 'content-type message-content-type
+ (check-field 'content-type message-content-type
definition maybe-spam)
;; next, if spam was not ruled out already, check
;; contents: if contents field is not specified, this may
;; still be spam due to another element...
- (rsf-check-field 'contents
+ (check-field 'contents
(buffer-substring
(rmail-msgbeg msg) (rmail-msgend msg))
definition maybe-spam)
-
+
;; if the search in rsf-definitions-alist found
;; that this email is spam, output the email to the spam
;; rmail file, mark the email for deletion, leave the
(setq num-element (+ num-element 1)))
)
)
-
+
;; (BK) re-set originally used variables
(setq this-is-a-spam-email (rest maybe-spam)
maybe-spam (first maybe-spam))
(while definitions
(setq current (car definitions))
(setq definitions (cdr definitions))
- (setq result
+ (setq result
(append result
- (list
+ (list
(list (assoc 'from current)
(assoc 'to current)
(assoc 'subject current)