diff options
| author | Paul Reilly | 2003-02-19 02:51:22 +0000 |
|---|---|---|
| committer | Paul Reilly | 2003-02-19 02:51:22 +0000 |
| commit | 97d3e8cdeb8942af3b9da2aee174d65635463bc7 (patch) | |
| tree | 07d078c9a57ede7afcf3c3b0633ffdaa187e30b2 | |
| parent | 068f98821bc0b1db32d5b75b7abe9e4799b0ff57 (diff) | |
| download | emacs-97d3e8cdeb8942af3b9da2aee174d65635463bc7.tar.gz emacs-97d3e8cdeb8942af3b9da2aee174d65635463bc7.zip | |
Initial commit to the trunk.
| -rw-r--r-- | lisp/mail/rmail-spam-filter.el | 632 |
1 files changed, 632 insertions, 0 deletions
diff --git a/lisp/mail/rmail-spam-filter.el b/lisp/mail/rmail-spam-filter.el new file mode 100644 index 00000000000..0ae87fe5179 --- /dev/null +++ b/lisp/mail/rmail-spam-filter.el | |||
| @@ -0,0 +1,632 @@ | |||
| 1 | ;;; rmail-spam-filter.el --- spam filter for rmail, the emacs mail reader. | ||
| 2 | |||
| 3 | ;; Copyright (C) 2002 | ||
| 4 | ;; Free Software Foundation, Inc. | ||
| 5 | ;; Keywords: email, spam, filter, rmail | ||
| 6 | ;; Author: Eli Tziperman <eli@beach.weizmann.ac.il> | ||
| 7 | |||
| 8 | ;; This file is part of GNU Emacs. | ||
| 9 | |||
| 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. | ||
| 14 | |||
| 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. | ||
| 19 | |||
| 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. | ||
| 24 | |||
| 25 | ;;; Commentary: | ||
| 26 | ;;; ----------- | ||
| 27 | |||
| 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/ | ||
| 32 | |||
| 33 | ;;; Usage: | ||
| 34 | ;;; ------ | ||
| 35 | |||
| 36 | ;;; put in your .emacs: | ||
| 37 | |||
| 38 | ;;; (load "rmail-spam-filter.el") | ||
| 39 | |||
| 40 | ;;; and use customize (in rmail-spam-filter group) to: | ||
| 41 | |||
| 42 | ;;; (*) turn on the variable rmail-use-spam-filter, | ||
| 43 | |||
| 44 | ;;; (*) specify in variable rmail-spam-definitions-alist what sender, | ||
| 45 | ;;; subject and contents make an email be considered spam. | ||
| 46 | |||
| 47 | ;;; in addition, you may: | ||
| 48 | |||
| 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'. | ||
| 56 | |||
| 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). | ||
| 60 | |||
| 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). | ||
| 64 | |||
| 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>). | ||
| 69 | |||
| 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. | ||
| 77 | |||
| 78 | (require 'rmail) | ||
| 79 | |||
| 80 | ;; For find-if and other cool common lisp functions we may want to use. (EDB) | ||
| 81 | (require 'cl) | ||
| 82 | |||
| 83 | (defgroup rmail-spam-filter nil | ||
| 84 | "Spam filter for RMAIL, the mail reader for Emacs." | ||
| 85 | :group 'rmail) | ||
| 86 | |||
| 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 ) | ||
| 93 | |||
| 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 ) | ||
| 102 | |||
| 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 ) | ||
| 107 | |||
| 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 ) | ||
| 112 | |||
| 113 | (defcustom rmail-spam-filter-beep nil | ||
| 114 | "*Non-nil to beep if spam is found." | ||
| 115 | :type 'boolean | ||
| 116 | :group 'rmail-spam-filter ) | ||
| 117 | |||
| 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 ) | ||
| 122 | |||
| 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 ) | ||
| 133 | |||
| 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 ) | ||
| 142 | |||
| 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 ) | ||
| 152 | |||
| 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) | ||
| 182 | )) | ||
| 183 | )) | ||
| 184 | :group 'rmail-spam-filter) | ||
| 185 | |||
| 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'") | ||
| 189 | |||
| 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'." | ||
| 195 | |||
| 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) | ||
| 209 | ) | ||
| 210 | |||
| 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")) | ||
| 230 | ) | ||
| 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)) | ||
| 235 | |||
| 236 | ;;; do we want to ignore case in spam definitions: | ||
| 237 | (setq case-fold-search rmail-spam-filter-ignore-case) | ||
| 238 | |||
| 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))) | ||
| 247 | |||
| 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))) | ||
| 257 | |||
| 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) | ||
| 276 | |||
| 277 | ;; start scanning incoming message: | ||
| 278 | ;;--------------------------------- | ||
| 279 | |||
| 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) | ||
| 297 | ) | ||
| 298 | (setq this-is-a-spam-email t) | ||
| 299 | (setq maybe-spam nil) | ||
| 300 | ) | ||
| 301 | ) | ||
| 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) | ||
| 320 | ) | ||
| 321 | (setq this-is-a-spam-email t) | ||
| 322 | (setq maybe-spam nil) | ||
| 323 | ) | ||
| 324 | ) | ||
| 325 | ) | ||
| 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) | ||
| 346 | ) | ||
| 347 | (setq this-is-a-spam-email t) | ||
| 348 | (setq maybe-spam nil) | ||
| 349 | ) | ||
| 350 | ) | ||
| 351 | ) | ||
| 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))) | ||
| 371 | ) | ||
| 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))) | ||
| 386 | ) | ||
| 387 | ) | ||
| 388 | (if (and this-is-a-spam-email maybe-spam) | ||
| 389 | (progn | ||
| 390 | ;;(message "Found spam!") | ||
| 391 | ;;(ding 1) (sleep-for 2) | ||
| 392 | |||
| 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) | ||
| 406 | )) | ||
| 407 | ((equal (cdr (assoc 'action | ||
| 408 | (nth num-element rmail-spam-definitions-alist))) | ||
| 409 | 'delete-spam) | ||
| 410 | (progn | ||
| 411 | (rmail-delete-message) | ||
| 412 | )) | ||
| 413 | ) | ||
| 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)) | ||
| 424 | |||
| 425 | |||
| 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)) | ||
| 443 | t) | ||
| 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")) | ||
| 454 | ))) | ||
| 455 | |||
| 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)) | ||
| 470 | t) | ||
| 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")) | ||
| 481 | ))) | ||
| 482 | |||
| 483 | |||
| 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)) | ||
| 506 | t) | ||
| 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 | ))))) | ||
| 518 | |||
| 519 | |||
| 520 | (defun rmail-spam-filter-customize-spam-definitions () | ||
| 521 | (interactive) | ||
| 522 | (customize-variable (quote rmail-spam-definitions-alist))) | ||
| 523 | |||
| 524 | (defun rmail-spam-filter-customize-group () | ||
| 525 | (interactive) | ||
| 526 | (customize-group (quote rmail-spam-filter))) | ||
| 527 | |||
| 528 | (defun rmail-spam-custom-save-all () | ||
| 529 | (interactive) | ||
| 530 | (custom-save-all)) | ||
| 531 | |||
| 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"))) | ||
| 538 | |||
| 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) | ||
| 545 | |||
| 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) | ||
| 552 | |||
| 553 | (define-key rmail-summary-mode-map [menu-bar spam lambda] '("----")) | ||
| 554 | (define-key rmail-mode-map [menu-bar spam lambda] '("----")) | ||
| 555 | |||
| 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) | ||
| 562 | |||
| 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) | ||
| 569 | |||
| 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) | ||
| 576 | |||
| 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) | ||
| 583 | |||
| 584 | |||
| 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)))))))) | ||
| 601 | |||
| 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: | ||
| 614 | (or | ||
| 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))) | ||
| 621 | ))) | ||
| 622 | |||
| 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) | ||
| 628 | )) | ||
| 629 | |||
| 630 | (provide 'rmail-spam-filter) | ||
| 631 | |||
| 632 | ;;; rmail-spam-filter ends here | ||