*** empty log message ***
[emacs.git] / lisp / mail / rmail-spam-filter.el
blob0ae87fe5179ab91b95fdff2f1c182c9638f6c071
1 ;;; rmail-spam-filter.el --- spam filter for rmail, the emacs mail reader.
3 ;; Copyright (C) 2002
4 ;; Free Software Foundation, Inc.
5 ;; Keywords: email, spam, filter, rmail
6 ;; Author: Eli Tziperman <eli@beach.weizmann.ac.il>
8 ;; This file is part of GNU Emacs.
10 ;; GNU Emacs is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 2, or (at your option)
13 ;; any later version.
15 ;; GNU Emacs is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs; see the file COPYING. If not, write to the
22 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
25 ;;; Commentary:
26 ;;; -----------
28 ;;; Automatically recognize and delete junk email before it is
29 ;;; displayed in rmail/rmail-summary. Spam emails are defined by
30 ;;; specifying one or more of the sender, subject and contents.
31 ;;; URL: http://www.weizmann.ac.il/~eli/Downloads/rmail-spam-filter/
33 ;;; Usage:
34 ;;; ------
36 ;;; put in your .emacs:
38 ;;; (load "rmail-spam-filter.el")
40 ;;; and use customize (in rmail-spam-filter group) to:
42 ;;; (*) turn on the variable rmail-use-spam-filter,
44 ;;; (*) specify in variable rmail-spam-definitions-alist what sender,
45 ;;; subject and contents make an email be considered spam.
47 ;;; in addition, you may:
49 ;;; (*) Block future mail with the subject or sender of a message
50 ;;; while reading it in RMAIL: just click on the "Spam" item on the
51 ;;; menubar, and add the subject or sender to the list of spam
52 ;;; definitions using the mouse and the appropriate menu item. Â  You
53 ;;; need to later also save the list of spam definitions using the
54 ;;; same menu item, or alternatively, see variable
55 ;;; `rmail-spam-filter-autosave-newly-added-spam-definitions'.
57 ;;; (*) specify if blind-cc'ed mail (no "To:" header field) is to be
58 ;;; treated as spam (variable rmail-spam-no-blind-cc; Thanks to Ethan
59 ;;; Brown <ethan@gso.saic.com> for this).
61 ;;; (*) specify if rmail-spam-filter should ignore case of spam
62 ;;; definitions (variable rmail-spam-filter-ignore-case; Thanks to
63 ;;; Ethan Brown <ethan@gso.saic.com> for the suggestion).
65 ;;; (*) Specify a "white-list" of trusted senders. If any
66 ;;; rmail-spam-white-list string matches a substring of the "From"
67 ;;; header, the message is flagged as a valid, non-spam message (Ethan
68 ;;; Brown <ethan@gso.saic.com>).
70 ;;; (*) rmail spam filter also works with bbdb to prevent spam senders
71 ;;; from entering into the .bbdb file. See variable
72 ;;; "rmail-spam-filter-auto-delete-spam-bbdb-entries". This is done
73 ;;; in two ways: (a) bbdb is made not to auto-create entries for
74 ;;; messages that are deleted by the rmail-spam-filter, (b) when a
75 ;;; message is deleted in rmail, the user is offered to delete the
76 ;;; sender's bbdb entry as well _if_ it was created at the same day.
78 (require 'rmail)
80 ;; For find-if and other cool common lisp functions we may want to use. (EDB)
81 (require 'cl)
83 (defgroup rmail-spam-filter nil
84 "Spam filter for RMAIL, the mail reader for Emacs."
85 :group 'rmail)
87 (defcustom rmail-use-spam-filter nil
88 "*Non-nil to activate the rmail spam filter.
89 Specify `rmail-spam-definitions-alist' to define what you consider spam
90 emails."
91 :type 'boolean
92 :group 'rmail-spam-filter )
94 (defcustom rmail-spam-file "~/XRMAIL-SPAM"
95 "*Name of rmail file for optionally saving some of the spam.
96 Spam may be either just deleted, or saved in a separate spam file to
97 be looked at at a later time. Whether the spam is just deleted or
98 also saved in a separete spam file is specified for each definition of
99 spam, as one of the fields of `rmail-spam-definitions-alist'"
100 :type 'string
101 :group 'rmail-spam-filter )
103 (defcustom rmail-spam-no-blind-cc nil
104 "*Non-nil to treat blind CC (no To: header) as spam."
105 :type 'boolean
106 :group 'rmail-spam-filter )
108 (defcustom rmail-spam-filter-ignore-case nil
109 "*Non-nil to ignore case in `rmail-spam-definitions-alist'."
110 :type 'boolean
111 :group 'rmail-spam-filter )
113 (defcustom rmail-spam-filter-beep nil
114 "*Non-nil to beep if spam is found."
115 :type 'boolean
116 :group 'rmail-spam-filter )
118 (defcustom rmail-spam-sleep-after-message 2.0
119 "*Seconds to wait after display of message that spam was found."
120 :type 'number
121 :group 'rmail-spam-filter )
123 (defcustom rmail-spam-filter-auto-delete-spam-bbdb-entries nil
124 "*Non-nil to make sure no entries are made in bbdb for spam emails.
125 This is done in two ways: (1) bbdb is made not to auto-create entries
126 for messages that are deleted by the `rmail-spam-filter', (2) when a
127 message is deleted in rmail, the user is offered to delete the
128 sender's bbdb entry as well if it was created at the same day. Note
129 that Emacs needs to be restarted after setting this option for it to
130 take an effect."
131 :type 'boolean
132 :group 'rmail-spam-filter )
134 (defcustom rmail-spam-filter-autosave-newly-added-spam-definitions nil
135 "*Non-nil to auto save new spam entries.
136 New entries entered via the spam menu bar item are then saved to
137 customization file immediately after being added via the menu bar, and
138 do not require explicitly saving the file after adding the new
139 entries."
140 :type 'boolean
141 :group 'rmail-spam-filter )
143 (defcustom rmail-spam-white-list nil
144 "*List of strings to identify valid senders.
145 If any rmail-spam-white-list string matches a substring of the 'From'
146 header, the message is flagged as a valid, non-spam message. Example:
147 If your domain is emacs.com then including 'emacs.com' in your
148 rmail-spam-white-list would flag all mail from your colleagues as
149 valid."
150 :type '(repeat string)
151 :group 'rmail-spam-filter )
153 (defcustom rmail-spam-definitions-alist nil
154 "*Alist matching strings defining what messages are considered spam.
155 Each definition may contain specifications of one or more of the
156 elements {subject, sender, recipients or contents}, as well as a
157 definition of what to do with the spam (action item). A spam e-mail
158 is defined as one that fits all of the specified elements of any one
159 of the spam definitions. The strings that specify spam subject,
160 sender, etc, may be regexp. For example, to specify that the subject
161 may be either 'this is spam' or 'another spam', use the regexp: 'this
162 is spam\|another spam' (without the single quotes)."
163 :type '(repeat
164 (list :format "%v"
165 (cons :format "%v" :value (from . "")
166 (const :format "" from)
167 (string :tag "From" ""))
168 (cons :format "%v" :value (to . "")
169 (const :format "" to)
170 (string :tag "To" ""))
171 (cons :format "%v" :value (subject . "")
172 (const :format "" subject)
173 (string :tag "Subject" ""))
174 (cons :format "%v" :value (contents . "")
175 (const :format "" contents)
176 (string :tag "Contents" ""))
177 (cons :format "%v" :value (action . output-and-delete)
178 (const :format "" action)
179 (choice :tag "Action selection"
180 (const :tag "output to spam folder and delete" output-and-delete)
181 (const :tag "delete spam" delete-spam)
184 :group 'rmail-spam-filter)
186 (defvar rmail-spam-filter-scanning-messages-now nil
187 "Non nil when rmail-spam-filter scans messages,
188 for interaction with `rmail-bbdb-auto-delete-spam-entries'")
190 (defun rmail-spam-filter (msg)
191 "Return nil if msg is spam based on rmail-spam-definitions-alist.
192 If spam, optionally output msg to a file `rmail-spam-file' and delete
193 it from rmail file. Called for each new message retrieved by
194 `rmail-get-new-mail'."
196 (let ((old-message)
197 (return-value)
198 (this-is-a-spam-email)
199 (maybe-spam)
200 (message-sender)
201 (message-recipients)
202 (message-subject)
203 (num-spam-definition-elements)
204 (num-element 0)
205 (exit-while-loop nil)
206 (saved-case-fold-search case-fold-search)
207 (save-current-msg)
208 (rmail-spam-filter-saved-bbdb/mail_auto_create_p nil)
211 ;; make sure bbdb does not create entries for messages while spam
212 ;; filter is scanning the rmail file:
213 (setq rmail-spam-filter-saved-bbdb/mail_auto_create_p 'bbdb/mail_auto_create_p)
214 (setq bbdb/mail_auto_create_p nil)
215 ;; let `rmail-bbdb-auto-delete-spam-entries' know that rmail spam
216 ;; filter is running, so that deletion of rmail messages should be
217 ;; ignored for now:
218 (setq rmail-spam-filter-scanning-messages-now t)
219 (save-excursion
220 (save-restriction
221 (setq this-is-a-spam-email nil)
222 ;; Narrow buffer to header of message and get Sender and
223 ;; Subject fields to be used below:
224 (save-restriction
225 (goto-char (rmail-msgbeg msg))
226 (narrow-to-region (point) (progn (search-forward "\n\n") (point)))
227 (setq message-sender (mail-fetch-field "From"))
228 (setq message-recipients (mail-fetch-field "To"))
229 (setq message-subject (mail-fetch-field "Subject"))
231 ;; Find number of spam-definition elements in the list
232 ;; rmail-spam-definitions-alist specified by user:
233 (setq num-spam-definition-elements (safe-length
234 rmail-spam-definitions-alist))
236 ;;; do we want to ignore case in spam definitions:
237 (setq case-fold-search rmail-spam-filter-ignore-case)
239 ;; Check for blind CC condition. Set vars such that while
240 ;; loop will be bypassed and spam condition will trigger (EDB)
241 (if (and rmail-spam-no-blind-cc
242 (null message-recipients))
243 (progn
244 (setq exit-while-loop t)
245 (setq maybe-spam t)
246 (setq this-is-a-spam-email t)))
248 ;; Check white list, and likewise cause while loop
249 ;; bypass. (EDB)
250 (if (find-if '(lambda (white-str)
251 (string-match white-str message-sender))
252 rmail-spam-white-list)
253 (progn
254 (setq exit-while-loop t)
255 (setq maybe-spam nil)
256 (setq this-is-a-spam-email nil)))
258 ;; scan all elements of the list rmail-spam-definitions-alist
259 (while (and
260 (< num-element num-spam-definition-elements)
261 (not exit-while-loop))
262 (progn
263 ;; Initialize maybe-spam which is set to t in one of two
264 ;; cases: (1) unspecified definition-elements are found in
265 ;; rmail-spam-definitions-alist, (2) empty field is found
266 ;; in the message being scanned (e.g. empty subject,
267 ;; sender, recipients, etc). The variable is set to nil
268 ;; if a non empty field of the scanned message does not
269 ;; match a specified field in
270 ;; rmail-spam-definitions-alist.
271 (setq maybe-spam t)
272 ;; initialize this-is-a-spam-email to nil. This variable
273 ;; is set to t if one of the spam definitions matches a
274 ;; field in the scanned message.
275 (setq this-is-a-spam-email nil)
277 ;; start scanning incoming message:
278 ;;---------------------------------
280 ;; if sender field is not specified in message being
281 ;; scanned, AND if "from" field does not appear in spam
282 ;; definitions for this element, this may still be spam
283 ;; due to another element...
284 (if (and (not message-sender)
285 (string-match
286 (cdr (assoc 'from (nth num-element
287 rmail-spam-definitions-alist))) ""))
288 (setq maybe-spam t)
289 ;; ... else, if message-sender does appear in the
290 ;; message, and it also appears in the spam definition
291 ;; list, it is potentially spam:
292 (if (and message-sender
293 (string-match
294 (cdr (assoc 'from (nth num-element
295 rmail-spam-definitions-alist)))
296 message-sender)
298 (setq this-is-a-spam-email t)
299 (setq maybe-spam nil)
302 ;; next, if spam was not ruled out already, check recipients:
303 (if maybe-spam
304 ;; if To field does not exist AND is not specified,
305 ;; this may still be spam due to another element...
306 (if (and (not message-recipients)
307 (string-match
308 (cdr (assoc 'to
309 (nth num-element
310 rmail-spam-definitions-alist))) ""))
311 (setq maybe-spam t)
312 ;; ... else, if To field does appear in the message,
313 ;; and it also appears in spam definition list, this
314 ;; is potentially a spam:
315 (if (and message-recipients
316 (string-match
317 (cdr (assoc 'to (nth num-element
318 rmail-spam-definitions-alist)))
319 message-recipients)
321 (setq this-is-a-spam-email t)
322 (setq maybe-spam nil)
326 ;; next, if spam was not ruled out already, check subject:
327 (if maybe-spam
328 ;; if subject field does not exist AND is not
329 ;; specified, this may still be spam due to another
330 ;; element...
331 (if (and (not message-subject)
332 (string-match
333 (cdr (assoc 'subject
334 (nth num-element
335 rmail-spam-definitions-alist)))
336 ""))
337 (setq maybe-spam t)
338 ;; ... else, if subject field does appear in the
339 ;; message, and it also appears in the spam
340 ;; definition list, this is potentially a spam:
341 (if (and message-subject
342 (string-match
343 (cdr (assoc 'subject (nth num-element
344 rmail-spam-definitions-alist)))
345 message-subject)
347 (setq this-is-a-spam-email t)
348 (setq maybe-spam nil)
352 ;; next, if spam was not ruled out already, check
353 ;; contents: if contents field is not specified, this may
354 ;; still be spam due to another element...
355 (if maybe-spam
356 (if (string-match
357 (cdr (assoc 'contents
358 (nth num-element
359 rmail-spam-definitions-alist))) "")
360 (setq maybe-spam t)
361 ;; ... else, check to see if it appears in spam
362 ;; definition:
363 (if (string-match
364 (cdr (assoc 'contents
365 (nth num-element
366 rmail-spam-definitions-alist)))
367 (buffer-substring
368 (rmail-msgbeg msg) (rmail-msgend msg)))
369 (setq this-is-a-spam-email t)
370 (setq maybe-spam nil)))
372 ;; if the search in rmail-spam-definitions-alist found
373 ;; that this email is spam, output the email to the spam
374 ;; rmail file, mark the email for deletion, leave the
375 ;; while loop and return nil so that an rmail summary line
376 ;; wont be displayed for this message:
377 (if (and this-is-a-spam-email maybe-spam)
378 ;; found that this is spam, no need to look at the
379 ;; rest of the rmail-spam-definitions-alist, exit
380 ;; loop:
381 (setq exit-while-loop t)
382 ;; else, spam was not yet found, increment number of
383 ;; element in rmail-spam-definitions-alist and proceed
384 ;; to next element:
385 (setq num-element (+ num-element 1)))
388 (if (and this-is-a-spam-email maybe-spam)
389 (progn
390 ;;(message "Found spam!")
391 ;;(ding 1) (sleep-for 2)
393 ;; temprarily set rmail-current-message in order to
394 ;; output and delete the spam msg if needed:
395 (setq save-current-msg rmail-current-message)
396 (setq rmail-current-message msg)
397 ;; check action item and rmail-spam-definitions-alist
398 ;; and do it:
399 (cond
400 ((equal (cdr (assoc 'action
401 (nth num-element rmail-spam-definitions-alist)))
402 'output-and-delete)
403 (progn
404 (rmail-output-to-rmail-file rmail-spam-file)
405 (rmail-delete-message)
407 ((equal (cdr (assoc 'action
408 (nth num-element rmail-spam-definitions-alist)))
409 'delete-spam)
410 (progn
411 (rmail-delete-message)
414 (setq rmail-current-message save-current-msg)
415 (setq bbdb/mail_auto_create_p 'rmail-spam-filter-saved-bbdb/mail_auto_create_p)
416 ;; set return value. These lines must be last in the
417 ;; function, so that they will determine the value
418 ;; returned by rmail-spam-filter:
419 (setq return-value nil))
420 (setq return-value t))))
421 (setq case-fold-search saved-case-fold-search)
422 (setq rmail-spam-filter-scanning-messages-now nil)
423 return-value))
426 ;; define functions for interactively adding sender/subject of a
427 ;; specific message to the spam definitions while reading it, using
428 ;; the menubar:
429 (defun rmail-spam-filter-add-subject-to-spam-list ()
430 (interactive)
431 (set-buffer rmail-buffer)
432 (let ((message-subject))
433 (setq message-subject (mail-fetch-field "Subject"))
434 ;; note the use of a backquote and comma on the subject line here,
435 ;; to make sure message-subject is actually evaluated and its value
436 ;; substituted:
437 (add-to-list 'rmail-spam-definitions-alist
438 (list '(from . "")
439 '(to . "")
440 `(subject . ,message-subject)
441 '(contents . "")
442 '(action . output-and-delete))
444 (customize-mark-to-save 'rmail-spam-definitions-alist)
445 (if rmail-spam-filter-autosave-newly-added-spam-definitions
446 (progn
447 (custom-save-all)
448 (message (concat "added subject \n <<< \n" message-subject
449 " \n >>> \n to list of spam definitions. \n"
450 "and saved the spam definitions to file.")))
451 (message (concat "added subject \n <<< \n" message-subject
452 " \n >>> \n to list of spam definitions. \n"
453 "Don't forget to save the spam definitions to file using the spam menu"))
456 (defun rmail-spam-filter-add-sender-to-spam-list ()
457 (interactive)
458 (set-buffer rmail-buffer)
459 (let ((message-sender))
460 (setq message-sender (mail-fetch-field "From"))
461 ;; note the use of a backquote and comma on the "from" line here,
462 ;; to make sure message-sender is actually evaluated and its value
463 ;; substituted:
464 (add-to-list 'rmail-spam-definitions-alist
465 (list `(from . ,message-sender)
466 '(to . "")
467 '(subject . "")
468 '(contents . "")
469 '(action . output-and-delete))
471 (customize-mark-to-save 'rmail-spam-definitions-alist)
472 (if rmail-spam-filter-autosave-newly-added-spam-definitions
473 (progn
474 (custom-save-all)
475 (message (concat "added sender \n <<< \n" message-sender
476 " \n >>> \n to list of spam definitions. \n"
477 "and saved the spam definitions to file.")))
478 (message (concat "added sender \n <<< \n " message-sender
479 " \n >>> \n to list of spam definitions."
480 "Don't forget to save the spam definitions to file using the spam menu"))
484 (defun rmail-spam-filter-add-region-to-spam-list ()
485 "Add the region makred by user in the rmail buffer to the list of
486 spam definitions as a contents field."
487 (interactive)
488 (set-buffer rmail-buffer)
489 (let ((region-to-spam-list))
490 ;; check if region is inactive or has zero size:
491 (if (not (and mark-active (not (= (region-beginning) (region-end)))))
492 ;; if inactive, print error message:
493 (message "you need to first highlight some text in the rmail buffer")
494 ;; if active, add to list of spam definisions:
495 (progn
496 (setq region-to-spam-list (buffer-substring (region-beginning) (region-end)))
497 ;; note the use of a backquote and comma on the "from" line here,
498 ;; to make sure message-sender is actually evaluated and its value
499 ;; substituted:
500 (add-to-list 'rmail-spam-definitions-alist
501 (list '(from . "")
502 '(to . "")
503 '(subject . "")
504 `(contents . ,region-to-spam-list)
505 '(action . output-and-delete))
507 (customize-mark-to-save 'rmail-spam-definitions-alist)
508 (if rmail-spam-filter-autosave-newly-added-spam-definitions
509 (progn
510 (custom-save-all)
511 (message (concat "added highlighted text \n <<< \n" region-to-spam-list
512 " \n >>> \n to list of spam definitions. \n"
513 "and saved the spam definitions to file.")))
514 (message (concat "added highlighted text \n <<< \n " region-to-spam-list
515 " \n >>> \n to list of spam definitions."
516 "Don't forget to save the spam definitions to file using the spam menu"))
517 )))))
520 (defun rmail-spam-filter-customize-spam-definitions ()
521 (interactive)
522 (customize-variable (quote rmail-spam-definitions-alist)))
524 (defun rmail-spam-filter-customize-group ()
525 (interactive)
526 (customize-group (quote rmail-spam-filter)))
528 (defun rmail-spam-custom-save-all ()
529 (interactive)
530 (custom-save-all))
532 ;; add the actual menu items and keyboard shortcuts to both rmail and
533 ;; rmail-summary menu-bars::
534 (define-key rmail-summary-mode-map [menu-bar spam]
535 (cons "Spam" (make-sparse-keymap "Spam")))
536 (define-key rmail-mode-map [menu-bar spam]
537 (cons "Spam" (make-sparse-keymap "Spam")))
539 (define-key rmail-summary-mode-map [menu-bar spam customize-group]
540 '("Browse customizations of rmail spam filter" . rmail-spam-filter-customize-group))
541 (define-key rmail-mode-map [menu-bar spam customize-group]
542 '("Browse customizations of rmail spam filter" . rmail-spam-filter-customize-group))
543 (define-key rmail-summary-mode-map "\C-cSg" 'rmail-spam-filter-customize-group)
544 (define-key rmail-mode-map "\C-cSg" 'rmail-spam-filter-customize-group)
546 (define-key rmail-summary-mode-map [menu-bar spam customize-spam-list]
547 '("Customize list of spam definitions" . rmail-spam-filter-customize-spam-definitions))
548 (define-key rmail-mode-map [menu-bar spam customize-spam-list]
549 '("Customize list of spam definitions" . rmail-spam-filter-customize-spam-definitions))
550 (define-key rmail-summary-mode-map "\C-cSd" 'rmail-spam-filter-customize-spam-definitions)
551 (define-key rmail-mode-map "\C-cSd" 'rmail-spam-filter-customize-spam-definitions)
553 (define-key rmail-summary-mode-map [menu-bar spam lambda] '("----"))
554 (define-key rmail-mode-map [menu-bar spam lambda] '("----"))
556 (define-key rmail-summary-mode-map [menu-bar spam my-custom-save-all]
557 '("save newly added spam definitions to customization file" . rmail-spam-custom-save-all))
558 (define-key rmail-mode-map [menu-bar spam my-custom-save-all]
559 '("save newly added spam definitions to customization file" . rmail-spam-custom-save-all))
560 (define-key rmail-summary-mode-map "\C-cSa" 'rmail-spam-custom-save-all)
561 (define-key rmail-mode-map "\C-cSa" 'rmail-spam-custom-save-all)
563 (define-key rmail-summary-mode-map [menu-bar spam add-region-to-spam-list]
564 '("add region to spam list" . rmail-spam-filter-add-region-to-spam-list))
565 (define-key rmail-mode-map [menu-bar spam add-region-to-spam-list]
566 '("add region to spam list" . rmail-spam-filter-add-region-to-spam-list))
567 (define-key rmail-summary-mode-map "\C-cSn" 'rmail-spam-filter-add-region-to-spam-list)
568 (define-key rmail-mode-map "\C-cSn" 'rmail-spam-filter-add-region-to-spam-list)
570 (define-key rmail-summary-mode-map [menu-bar spam add-sender-to-spam-list]
571 '("add sender to spam list" . rmail-spam-filter-add-sender-to-spam-list))
572 (define-key rmail-mode-map [menu-bar spam add-sender-to-spam-list]
573 '("add sender to spam list" . rmail-spam-filter-add-sender-to-spam-list))
574 (define-key rmail-summary-mode-map "\C-cSr" 'rmail-spam-filter-add-sender-to-spam-list)
575 (define-key rmail-mode-map "\C-cSr" 'rmail-spam-filter-add-sender-to-spam-list)
577 (define-key rmail-summary-mode-map [menu-bar spam add-subject-to-spam-list]
578 '("add subject to spam list" . rmail-spam-filter-add-subject-to-spam-list))
579 (define-key rmail-mode-map [menu-bar spam add-subject-to-spam-list]
580 '("add subject to spam list" . rmail-spam-filter-add-subject-to-spam-list))
581 (define-key rmail-summary-mode-map "\C-cSt" 'rmail-spam-filter-add-subject-to-spam-list)
582 (define-key rmail-mode-map "\C-cSt" 'rmail-spam-filter-add-subject-to-spam-list)
585 (defun rmail-bbdb-auto-delete-spam-entries ()
586 "When deleting a message in RMAIL, check to see if the bbdb entry
587 was created today, and if it was, prompt to delete it too. This function
588 needs to be called via the `rmail-delete-message-hook' like this:
589 \(add-hook 'rmail-delete-message-hook 'rmail-bbdb-auto-delete-spam-entries)"
590 (interactive)
591 (require 'bbdb-hooks)
592 (if (not rmail-spam-filter-scanning-messages-now)
593 (if (get-buffer "*BBDB*")
594 (save-excursion
595 (set-buffer (get-buffer "*BBDB*"))
596 (if (bbdb-current-record)
597 (if (equal
598 (format-time-string bbdb-time-internal-format (current-time))
599 (bbdb-record-getprop (bbdb-current-record) 'creation-date))
600 (bbdb-delete-current-record (bbdb-current-record))))))))
602 (defun rmail-spam-filter-bbdb-dont-create-entries-for-spam ()
603 "Make sure senderes of rmail messages marked as deleted are not added to bbdb.
604 Need to add this as a hook like this:
605 \(setq bbdb/mail-auto-create-p 'rmail-spam-filter-bbdb-dont-create-entries-for-spam)
606 and this is also used in conjunction with rmail-bbdb-auto-delete-spam-entries.
607 More doc: rmail-bbdb-auto-delete-spam-entries will delete newly created bbdb
608 entries of mail that is deleted. However, if one scrolls back to the deleted
609 messages, then the sender is again added to the bbdb. This function
610 prevents this. Also, don't create entries for messages in the `rmail-spam-file'."
611 (interactive)
612 (not
613 ;; don't create a bbdb entry if one of the following conditions is satisfied:
615 ;; 1) looking at a deleted message:
616 (rmail-message-deleted-p rmail-current-message)
617 ;; 2) looking at messages in rmail-spam-file:
618 (string-match
619 (expand-file-name rmail-spam-file)
620 (expand-file-name (buffer-file-name rmail-buffer)))
623 ;; activate bbdb-anti-spam measures:
624 (if rmail-spam-filter-auto-delete-spam-bbdb-entries
625 (progn
626 (add-hook 'rmail-delete-message-hook 'rmail-bbdb-auto-delete-spam-entries)
627 (setq bbdb/mail-auto-create-p 'rmail-spam-filter-bbdb-dont-create-entries-for-spam)
630 (provide 'rmail-spam-filter)
632 ;;; rmail-spam-filter ends here