53730
|
1 ;;; rmail-spam-filter.el --- spam filter for rmail, the emacs mail reader.
|
49862
|
2
|
79712
|
3 ;; Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
49862
|
4 ;; Keywords: email, spam, filter, rmail
|
53730
|
5 ;; Author: Eli Tziperman <eli AT deas.harvard.edu>
|
49862
|
6
|
|
7 ;; This file is part of GNU Emacs.
|
|
8
|
|
9 ;; GNU Emacs is free software; you can redistribute it and/or modify
|
|
10 ;; it under the terms of the GNU General Public License as published by
|
78232
|
11 ;; the Free Software Foundation; either version 3, or (at your option)
|
49862
|
12 ;; any later version.
|
|
13
|
|
14 ;; GNU Emacs is distributed in the hope that it will be useful,
|
|
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
17 ;; GNU General Public License for more details.
|
|
18
|
|
19 ;; You should have received a copy of the GNU General Public License
|
|
20 ;; along with GNU Emacs; see the file COPYING. If not, write to the
|
64085
|
21 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
22 ;; Boston, MA 02110-1301, USA.
|
49862
|
23
|
|
24 ;;; Commentary:
|
53730
|
25 ;;; -----------
|
49862
|
26
|
53730
|
27 ;;; Automatically recognize and delete junk email before it is
|
|
28 ;;; displayed in rmail/rmail-summary. Spam emails are defined by
|
|
29 ;;; specifying one or more of the sender, subject and contents.
|
54002
|
30 ;;; URL: http://www.weizmann.ac.il/~eli/Downloads/rmail-spam-filter/
|
49862
|
31
|
53730
|
32 ;;; Usage:
|
|
33 ;;; ------
|
49862
|
34
|
53730
|
35 ;;; put in your .emacs:
|
49862
|
36
|
53730
|
37 ;;; (load "rmail-spam-filter.el")
|
|
38
|
|
39 ;;; and use customize (in rmail-spam-filter group) to:
|
49862
|
40
|
53730
|
41 ;;; (*) turn on the variable rmail-use-spam-filter,
|
49862
|
42
|
53730
|
43 ;;; (*) specify in variable rsf-definitions-alist what sender,
|
|
44 ;;; subject and contents make an email be considered spam.
|
49862
|
45
|
53730
|
46 ;;; in addition, you may:
|
49862
|
47
|
53730
|
48 ;;; (*) Block future mail with the subject or sender of a message
|
|
49 ;;; while reading it in RMAIL: just click on the "Spam" item on the
|
|
50 ;;; menubar, and add the subject or sender to the list of spam
|
|
51 ;;; definitions using the mouse and the appropriate menu item. You
|
|
52 ;;; need to later also save the list of spam definitions using the
|
|
53 ;;; same menu item, or alternatively, see variable
|
|
54 ;;; `rsf-autosave-newly-added-definitions'.
|
49862
|
55
|
53730
|
56 ;;; (*) specify if blind-cc'ed mail (no "To:" header field) is to be
|
|
57 ;;; treated as spam (variable rsf-no-blind-cc; Thanks to Ethan
|
|
58 ;;; Brown <ethan@gso.saic.com> for this).
|
|
59
|
|
60 ;;; (*) specify if rmail-spam-filter should ignore case of spam
|
|
61 ;;; definitions (variable rsf-ignore-case; Thanks to
|
|
62 ;;; Ethan Brown <ethan@gso.saic.com> for the suggestion).
|
49862
|
63
|
53730
|
64 ;;; (*) Specify a "white-list" of trusted senders. If any
|
|
65 ;;; rsf-white-list string matches a substring of the "From"
|
|
66 ;;; header, the message is flagged as a valid, non-spam message (Ethan
|
|
67 ;;; Brown <ethan@gso.saic.com>).
|
49862
|
68
|
53730
|
69 ;;; (*) rmail-spam-filter is best used with a general purpose spam
|
|
70 ;;; filter such as the procmail-based http://www.spambouncer.org/.
|
|
71 ;;; Spambouncer is set to only mark messages as spam/blocked/bulk/OK
|
|
72 ;;; via special headers, and these headers may then be defined in
|
|
73 ;;; rmail-spam-filter such that the spam is rejected by
|
|
74 ;;; rmail-spam-filter itself.
|
49862
|
75
|
53730
|
76 ;;; (*) rmail spam filter also works with bbdb to prevent spam senders
|
|
77 ;;; from entering into the .bbdb file. See variable
|
|
78 ;;; "rsf-auto-delete-spam-bbdb-entries". This is done
|
|
79 ;;; in two ways: (a) bbdb is made not to auto-create entries for
|
|
80 ;;; messages that are deleted by the rmail-spam-filter, (b) when a
|
|
81 ;;; message is deleted in rmail, the user is offered to delete the
|
|
82 ;;; sender's bbdb entry as well _if_ it was created at the same day.
|
49862
|
83
|
|
84 (require 'rmail)
|
54002
|
85 (if (> emacs-major-version 20)
|
|
86 (require 'rmailsum)
|
|
87 (if (not (fboundp 'rmail-make-summary-line)) (load-library "rmailsum")))
|
49862
|
88
|
65209
afdca0591e8c
(bbdb/mail_auto_create_p, rmail-summary-mode-map): Add defvars.
Juanma Barranquero <lekktu@gmail.com>
diff
changeset
|
89 (defvar bbdb/mail_auto_create_p)
|
afdca0591e8c
(bbdb/mail_auto_create_p, rmail-summary-mode-map): Add defvars.
Juanma Barranquero <lekktu@gmail.com>
diff
changeset
|
90 (defvar rmail-summary-mode-map)
|
afdca0591e8c
(bbdb/mail_auto_create_p, rmail-summary-mode-map): Add defvars.
Juanma Barranquero <lekktu@gmail.com>
diff
changeset
|
91
|
53730
|
92 ;; For find-if and other cool common lisp functions we may want to use.
|
53685
|
93 (eval-when-compile
|
|
94 (require 'cl))
|
49862
|
95
|
|
96 (defgroup rmail-spam-filter nil
|
|
97 "Spam filter for RMAIL, the mail reader for Emacs."
|
|
98 :group 'rmail)
|
|
99
|
|
100 (defcustom rmail-use-spam-filter nil
|
|
101 "*Non-nil to activate the rmail spam filter.
|
53730
|
102 Specify `rsf-definitions-alist' to define what you consider spam
|
49862
|
103 emails."
|
|
104 :type 'boolean
|
|
105 :group 'rmail-spam-filter )
|
|
106
|
53730
|
107 (defcustom rsf-file "~/XRMAIL-SPAM"
|
49862
|
108 "*Name of rmail file for optionally saving some of the spam.
|
|
109 Spam may be either just deleted, or saved in a separate spam file to
|
|
110 be looked at at a later time. Whether the spam is just deleted or
|
|
111 also saved in a separete spam file is specified for each definition of
|
53730
|
112 spam, as one of the fields of `rsf-definitions-alist'"
|
49862
|
113 :type 'string
|
|
114 :group 'rmail-spam-filter )
|
|
115
|
53730
|
116 (defcustom rsf-no-blind-cc nil
|
49862
|
117 "*Non-nil to treat blind CC (no To: header) as spam."
|
|
118 :type 'boolean
|
|
119 :group 'rmail-spam-filter )
|
|
120
|
53730
|
121 (defcustom rsf-ignore-case nil
|
|
122 "*Non-nil to ignore case in `rsf-definitions-alist'."
|
49862
|
123 :type 'boolean
|
|
124 :group 'rmail-spam-filter )
|
|
125
|
53730
|
126 (defcustom rsf-beep nil
|
49862
|
127 "*Non-nil to beep if spam is found."
|
|
128 :type 'boolean
|
|
129 :group 'rmail-spam-filter )
|
|
130
|
53730
|
131 (defcustom rsf-sleep-after-message 2.0
|
49862
|
132 "*Seconds to wait after display of message that spam was found."
|
|
133 :type 'number
|
|
134 :group 'rmail-spam-filter )
|
53685
|
135
|
53730
|
136 (defcustom rsf-min-region-to-spam-list 7
|
72643
|
137 "*Minimum size of region that you can add to the spam list.
|
|
138 This is a size limit on text that you can specify as
|
|
139 indicating a message is spam. The aim is to avoid
|
|
140 accidentally adding a too short region, which would result
|
|
141 in false positive identification of spam."
|
53730
|
142 :type 'integer
|
|
143 :group 'rmail-spam-filter )
|
|
144
|
|
145 (defcustom rsf-auto-delete-spam-bbdb-entries nil
|
49862
|
146 "*Non-nil to make sure no entries are made in bbdb for spam emails.
|
|
147 This is done in two ways: (1) bbdb is made not to auto-create entries
|
|
148 for messages that are deleted by the `rmail-spam-filter', (2) when a
|
|
149 message is deleted in rmail, the user is offered to delete the
|
|
150 sender's bbdb entry as well if it was created at the same day. Note
|
|
151 that Emacs needs to be restarted after setting this option for it to
|
|
152 take an effect."
|
|
153 :type 'boolean
|
|
154 :group 'rmail-spam-filter )
|
|
155
|
53730
|
156 (defcustom rsf-autosave-newly-added-definitions nil
|
49862
|
157 "*Non-nil to auto save new spam entries.
|
|
158 New entries entered via the spam menu bar item are then saved to
|
|
159 customization file immediately after being added via the menu bar, and
|
|
160 do not require explicitly saving the file after adding the new
|
|
161 entries."
|
|
162 :type 'boolean
|
|
163 :group 'rmail-spam-filter )
|
|
164
|
53730
|
165 (defcustom rsf-white-list nil
|
49862
|
166 "*List of strings to identify valid senders.
|
53730
|
167 If any rsf-white-list string matches a substring of the 'From'
|
49862
|
168 header, the message is flagged as a valid, non-spam message. Example:
|
|
169 If your domain is emacs.com then including 'emacs.com' in your
|
53730
|
170 rsf-white-list would flag all mail from your colleagues as
|
49862
|
171 valid."
|
|
172 :type '(repeat string)
|
|
173 :group 'rmail-spam-filter )
|
|
174
|
53730
|
175 (defcustom rsf-definitions-alist nil
|
49862
|
176 "*Alist matching strings defining what messages are considered spam.
|
|
177 Each definition may contain specifications of one or more of the
|
|
178 elements {subject, sender, recipients or contents}, as well as a
|
|
179 definition of what to do with the spam (action item). A spam e-mail
|
|
180 is defined as one that fits all of the specified elements of any one
|
|
181 of the spam definitions. The strings that specify spam subject,
|
|
182 sender, etc, may be regexp. For example, to specify that the subject
|
|
183 may be either 'this is spam' or 'another spam', use the regexp: 'this
|
53730
|
184 is spam\\|another spam' (without the single quotes). To specify that
|
|
185 if the contents contain both this and that the message is spam,
|
|
186 specify 'this\\&that' in the appropriate spam definition field."
|
64754
|
187 :type '(repeat
|
49862
|
188 (list :format "%v"
|
|
189 (cons :format "%v" :value (from . "")
|
|
190 (const :format "" from)
|
|
191 (string :tag "From" ""))
|
|
192 (cons :format "%v" :value (to . "")
|
|
193 (const :format "" to)
|
|
194 (string :tag "To" ""))
|
|
195 (cons :format "%v" :value (subject . "")
|
|
196 (const :format "" subject)
|
|
197 (string :tag "Subject" ""))
|
53730
|
198 (cons :format "%v" :value (content-type . "")
|
|
199 (const :format "" content-type)
|
|
200 (string :tag "Content-Type" ""))
|
49862
|
201 (cons :format "%v" :value (contents . "")
|
|
202 (const :format "" contents)
|
|
203 (string :tag "Contents" ""))
|
91817
f0b22bbb77fb
;;; smtpmail.el --- simple SMTP protocol (RFC 821) for sending mail
Bastien Guerry <bzg@altern.org>
diff
changeset
|
204 (cons :format "%v" :value (x-spam-status . "")
|
f0b22bbb77fb
;;; smtpmail.el --- simple SMTP protocol (RFC 821) for sending mail
Bastien Guerry <bzg@altern.org>
diff
changeset
|
205 (const :format "" x-spam-status)
|
f0b22bbb77fb
;;; smtpmail.el --- simple SMTP protocol (RFC 821) for sending mail
Bastien Guerry <bzg@altern.org>
diff
changeset
|
206 (string :tag "X-Spam-Status" ""))
|
49862
|
207 (cons :format "%v" :value (action . output-and-delete)
|
|
208 (const :format "" action)
|
64754
|
209 (choice :tag "Action selection"
|
49862
|
210 (const :tag "output to spam folder and delete" output-and-delete)
|
|
211 (const :tag "delete spam" delete-spam)
|
|
212 ))
|
|
213 ))
|
|
214 :group 'rmail-spam-filter)
|
|
215
|
53730
|
216 (defvar rsf-scanning-messages-now nil
|
73649
|
217 "Non-nil when `rmail-spam-filter' scans messages.
|
72643
|
218 This is for interaction with `rsf-bbdb-auto-delete-spam-entries'.")
|
53730
|
219
|
|
220 ;; the advantage over the automatic filter definitions is the AND conjunction
|
|
221 ;; of in-one-definition-elements
|
54002
|
222 (defun check-field (field-symbol message-data definition result)
|
53730
|
223 "Check if field-symbol is in `rsf-definitions-alist'.
|
|
224 Capture maybe-spam and this-is-a-spam-email in a cons in result,
|
64754
|
225 where maybe-spam is in first and this-is-a-spam-email is in rest.
|
53730
|
226 The values are returned by destructively changing result.
|
|
227 If FIELD-SYMBOL field does not exist AND is not specified,
|
|
228 this may still be spam due to another element...
|
|
229 if (first result) is nil, we already have a contradiction in another
|
|
230 field"
|
|
231 (let ((definition-field (cdr (assoc field-symbol definition))))
|
|
232 (if (and (first result) (> (length definition-field) 0))
|
|
233 ;; only in this case can maybe-spam change from t to nil
|
|
234 ;; ... else, if FIELD-SYMBOL field does appear in the message,
|
|
235 ;; and it also appears in spam definition list, this
|
|
236 ;; is potentially a spam:
|
|
237 (if (and message-data
|
|
238 (string-match definition-field message-data))
|
|
239 ;; if we do not get a contradiction from another field, this is
|
|
240 ;; spam
|
|
241 (setf (rest result) t)
|
|
242 ;; the message data contradicts the specification, this is no spam
|
|
243 (setf (first result) nil)))))
|
49862
|
244
|
|
245 (defun rmail-spam-filter (msg)
|
53730
|
246 "Return nil if msg is spam based on rsf-definitions-alist.
|
|
247 If spam, optionally output msg to a file `rsf-file' and delete
|
49862
|
248 it from rmail file. Called for each new message retrieved by
|
|
249 `rmail-get-new-mail'."
|
|
250
|
|
251 (let ((old-message)
|
|
252 (return-value)
|
|
253 (this-is-a-spam-email)
|
|
254 (maybe-spam)
|
|
255 (message-sender)
|
|
256 (message-recipients)
|
|
257 (message-subject)
|
53730
|
258 (message-content-type)
|
91846
|
259 (message-spam-status)
|
49862
|
260 (num-spam-definition-elements)
|
|
261 (num-element 0)
|
|
262 (exit-while-loop nil)
|
|
263 (saved-case-fold-search case-fold-search)
|
|
264 (save-current-msg)
|
53730
|
265 (rsf-saved-bbdb/mail_auto_create_p nil)
|
49862
|
266 )
|
64754
|
267
|
49862
|
268 ;; make sure bbdb does not create entries for messages while spam
|
|
269 ;; filter is scanning the rmail file:
|
53730
|
270 (setq rsf-saved-bbdb/mail_auto_create_p 'bbdb/mail_auto_create_p)
|
49862
|
271 (setq bbdb/mail_auto_create_p nil)
|
53730
|
272 ;; let `rsf-bbdb-auto-delete-spam-entries' know that rmail spam
|
49862
|
273 ;; filter is running, so that deletion of rmail messages should be
|
|
274 ;; ignored for now:
|
53730
|
275 (setq rsf-scanning-messages-now t)
|
49862
|
276 (save-excursion
|
|
277 (save-restriction
|
|
278 (setq this-is-a-spam-email nil)
|
|
279 ;; Narrow buffer to header of message and get Sender and
|
|
280 ;; Subject fields to be used below:
|
|
281 (save-restriction
|
|
282 (goto-char (rmail-msgbeg msg))
|
|
283 (narrow-to-region (point) (progn (search-forward "\n\n") (point)))
|
|
284 (setq message-sender (mail-fetch-field "From"))
|
53730
|
285 (setq message-recipients
|
|
286 (concat (mail-fetch-field "To")
|
|
287 (if (mail-fetch-field "Cc")
|
|
288 (concat ", " (mail-fetch-field "Cc")))))
|
49862
|
289 (setq message-subject (mail-fetch-field "Subject"))
|
53730
|
290 (setq message-content-type (mail-fetch-field "Content-Type"))
|
91817
f0b22bbb77fb
;;; smtpmail.el --- simple SMTP protocol (RFC 821) for sending mail
Bastien Guerry <bzg@altern.org>
diff
changeset
|
291 (setq message-spam-status (mail-fetch-field "X-Spam-Status"))
|
49862
|
292 )
|
|
293 ;; Find number of spam-definition elements in the list
|
53730
|
294 ;; rsf-definitions-alist specified by user:
|
49862
|
295 (setq num-spam-definition-elements (safe-length
|
53730
|
296 rsf-definitions-alist))
|
49862
|
297
|
|
298 ;;; do we want to ignore case in spam definitions:
|
53730
|
299 (setq case-fold-search rsf-ignore-case)
|
64754
|
300
|
49862
|
301 ;; Check for blind CC condition. Set vars such that while
|
53730
|
302 ;; loop will be bypassed and spam condition will trigger
|
|
303 (if (and rsf-no-blind-cc
|
49862
|
304 (null message-recipients))
|
53730
|
305 (setq exit-while-loop t
|
|
306 maybe-spam t
|
|
307 this-is-a-spam-email t))
|
53685
|
308
|
53730
|
309 ;; Check white list, and likewise cause while loop
|
|
310 ;; bypass.
|
58182
875255640d7a
(rmail-spam-filter): Only check white list if `message-sender' is non-nil.
Eli Zaretskii <eliz@gnu.org>
diff
changeset
|
311 (if (and message-sender
|
875255640d7a
(rmail-spam-filter): Only check white list if `message-sender' is non-nil.
Eli Zaretskii <eliz@gnu.org>
diff
changeset
|
312 (let ((white-list rsf-white-list)
|
875255640d7a
(rmail-spam-filter): Only check white list if `message-sender' is non-nil.
Eli Zaretskii <eliz@gnu.org>
diff
changeset
|
313 (found nil))
|
875255640d7a
(rmail-spam-filter): Only check white list if `message-sender' is non-nil.
Eli Zaretskii <eliz@gnu.org>
diff
changeset
|
314 (while (and (not found) white-list)
|
875255640d7a
(rmail-spam-filter): Only check white list if `message-sender' is non-nil.
Eli Zaretskii <eliz@gnu.org>
diff
changeset
|
315 (if (string-match (car white-list) message-sender)
|
875255640d7a
(rmail-spam-filter): Only check white list if `message-sender' is non-nil.
Eli Zaretskii <eliz@gnu.org>
diff
changeset
|
316 (setq found t)
|
875255640d7a
(rmail-spam-filter): Only check white list if `message-sender' is non-nil.
Eli Zaretskii <eliz@gnu.org>
diff
changeset
|
317 (setq white-list (cdr white-list))))
|
875255640d7a
(rmail-spam-filter): Only check white list if `message-sender' is non-nil.
Eli Zaretskii <eliz@gnu.org>
diff
changeset
|
318 found))
|
53730
|
319 (setq exit-while-loop t
|
|
320 maybe-spam nil
|
|
321 this-is-a-spam-email nil))
|
53685
|
322
|
53730
|
323 ;; maybe-spam is in first, this-is-a-spam-email in rest, this
|
54002
|
324 ;; simplifies the call to check-field
|
53730
|
325 (setq maybe-spam (cons maybe-spam this-is-a-spam-email))
|
|
326
|
|
327 ;; scan all elements of the list rsf-definitions-alist
|
49862
|
328 (while (and
|
|
329 (< num-element num-spam-definition-elements)
|
|
330 (not exit-while-loop))
|
53730
|
331 (let ((definition (nth num-element rsf-definitions-alist)))
|
49862
|
332 ;; Initialize maybe-spam which is set to t in one of two
|
|
333 ;; cases: (1) unspecified definition-elements are found in
|
53730
|
334 ;; rsf-definitions-alist, (2) empty field is found
|
49862
|
335 ;; in the message being scanned (e.g. empty subject,
|
|
336 ;; sender, recipients, etc). The variable is set to nil
|
|
337 ;; if a non empty field of the scanned message does not
|
|
338 ;; match a specified field in
|
53730
|
339 ;; rsf-definitions-alist.
|
|
340
|
49862
|
341 ;; initialize this-is-a-spam-email to nil. This variable
|
|
342 ;; is set to t if one of the spam definitions matches a
|
|
343 ;; field in the scanned message.
|
53730
|
344 (setq maybe-spam (cons t nil))
|
49862
|
345
|
|
346 ;; start scanning incoming message:
|
|
347 ;;---------------------------------
|
64754
|
348
|
53730
|
349 ;; Maybe the different fields should also be done in a
|
|
350 ;; loop to make the whole thing more flexible
|
|
351 ;; if sender field is not specified in message being
|
49862
|
352 ;; scanned, AND if "from" field does not appear in spam
|
|
353 ;; definitions for this element, this may still be spam
|
|
354 ;; due to another element...
|
54002
|
355 (check-field 'from message-sender definition maybe-spam)
|
53730
|
356 ;; next, if spam was not ruled out already, check recipients:
|
54002
|
357 (check-field 'to message-recipients definition maybe-spam)
|
53730
|
358 ;; next, if spam was not ruled out already, check subject:
|
54002
|
359 (check-field 'subject message-subject definition maybe-spam)
|
53730
|
360 ;; next, if spam was not ruled out already, check content-type:
|
64754
|
361 (check-field 'content-type message-content-type
|
53730
|
362 definition maybe-spam)
|
49862
|
363 ;; next, if spam was not ruled out already, check
|
|
364 ;; contents: if contents field is not specified, this may
|
|
365 ;; still be spam due to another element...
|
64754
|
366 (check-field 'contents
|
53730
|
367 (buffer-substring
|
|
368 (rmail-msgbeg msg) (rmail-msgend msg))
|
|
369 definition maybe-spam)
|
64754
|
370
|
91817
f0b22bbb77fb
;;; smtpmail.el --- simple SMTP protocol (RFC 821) for sending mail
Bastien Guerry <bzg@altern.org>
diff
changeset
|
371 ;; finally, check the X-Spam-Status header. You will typically
|
f0b22bbb77fb
;;; smtpmail.el --- simple SMTP protocol (RFC 821) for sending mail
Bastien Guerry <bzg@altern.org>
diff
changeset
|
372 ;; look for the "Yes" string in this header field
|
f0b22bbb77fb
;;; smtpmail.el --- simple SMTP protocol (RFC 821) for sending mail
Bastien Guerry <bzg@altern.org>
diff
changeset
|
373 (check-field 'x-spam-status message-spam-status
|
f0b22bbb77fb
;;; smtpmail.el --- simple SMTP protocol (RFC 821) for sending mail
Bastien Guerry <bzg@altern.org>
diff
changeset
|
374 definition maybe-spam)
|
f0b22bbb77fb
;;; smtpmail.el --- simple SMTP protocol (RFC 821) for sending mail
Bastien Guerry <bzg@altern.org>
diff
changeset
|
375
|
53730
|
376 ;; if the search in rsf-definitions-alist found
|
49862
|
377 ;; that this email is spam, output the email to the spam
|
|
378 ;; rmail file, mark the email for deletion, leave the
|
|
379 ;; while loop and return nil so that an rmail summary line
|
|
380 ;; wont be displayed for this message:
|
53730
|
381 (if (and (first maybe-spam) (rest maybe-spam))
|
49862
|
382 ;; found that this is spam, no need to look at the
|
53730
|
383 ;; rest of the rsf-definitions-alist, exit
|
49862
|
384 ;; loop:
|
|
385 (setq exit-while-loop t)
|
|
386 ;; else, spam was not yet found, increment number of
|
53730
|
387 ;; element in rsf-definitions-alist and proceed
|
49862
|
388 ;; to next element:
|
|
389 (setq num-element (+ num-element 1)))
|
|
390 )
|
53730
|
391 )
|
64754
|
392
|
53730
|
393 ;; (BK) re-set originally used variables
|
|
394 (setq this-is-a-spam-email (rest maybe-spam)
|
|
395 maybe-spam (first maybe-spam))
|
|
396
|
49862
|
397 (if (and this-is-a-spam-email maybe-spam)
|
|
398 (progn
|
|
399 ;;(message "Found spam!")
|
|
400 ;;(ding 1) (sleep-for 2)
|
|
401
|
|
402 ;; temprarily set rmail-current-message in order to
|
|
403 ;; output and delete the spam msg if needed:
|
|
404 (setq save-current-msg rmail-current-message)
|
|
405 (setq rmail-current-message msg)
|
53730
|
406 ;; check action item and rsf-definitions-alist
|
49862
|
407 ;; and do it:
|
|
408 (cond
|
|
409 ((equal (cdr (assoc 'action
|
53730
|
410 (nth num-element rsf-definitions-alist)))
|
49862
|
411 'output-and-delete)
|
|
412 (progn
|
53730
|
413 (rmail-output-to-rmail-file rsf-file 1 t)
|
|
414 ;; Don't delete if automatic deletion after output
|
|
415 ;; is turned on
|
|
416 (unless rmail-delete-after-output (rmail-delete-message))
|
49862
|
417 ))
|
|
418 ((equal (cdr (assoc 'action
|
53730
|
419 (nth num-element rsf-definitions-alist)))
|
49862
|
420 'delete-spam)
|
|
421 (progn
|
|
422 (rmail-delete-message)
|
|
423 ))
|
|
424 )
|
|
425 (setq rmail-current-message save-current-msg)
|
53730
|
426 (setq bbdb/mail_auto_create_p
|
|
427 'rsf-saved-bbdb/mail_auto_create_p)
|
49862
|
428 ;; set return value. These lines must be last in the
|
|
429 ;; function, so that they will determine the value
|
|
430 ;; returned by rmail-spam-filter:
|
|
431 (setq return-value nil))
|
|
432 (setq return-value t))))
|
|
433 (setq case-fold-search saved-case-fold-search)
|
53730
|
434 (setq rsf-scanning-messages-now nil)
|
49862
|
435 return-value))
|
|
436
|
|
437
|
|
438 ;; define functions for interactively adding sender/subject of a
|
|
439 ;; specific message to the spam definitions while reading it, using
|
|
440 ;; the menubar:
|
53730
|
441 (defun rsf-add-subject-to-spam-list ()
|
49862
|
442 (interactive)
|
|
443 (set-buffer rmail-buffer)
|
|
444 (let ((message-subject))
|
|
445 (setq message-subject (mail-fetch-field "Subject"))
|
|
446 ;; note the use of a backquote and comma on the subject line here,
|
|
447 ;; to make sure message-subject is actually evaluated and its value
|
|
448 ;; substituted:
|
53730
|
449 (add-to-list 'rsf-definitions-alist
|
49862
|
450 (list '(from . "")
|
|
451 '(to . "")
|
|
452 `(subject . ,message-subject)
|
53730
|
453 '(content-type . "")
|
49862
|
454 '(contents . "")
|
|
455 '(action . output-and-delete))
|
|
456 t)
|
53730
|
457 (customize-mark-to-save 'rsf-definitions-alist)
|
|
458 (if rsf-autosave-newly-added-definitions
|
49862
|
459 (progn
|
|
460 (custom-save-all)
|
65587
|
461 (message "%s" (concat "added subject \n <<< \n" message-subject
|
49862
|
462 " \n >>> \n to list of spam definitions. \n"
|
|
463 "and saved the spam definitions to file.")))
|
65587
|
464 (message "%s" (concat "added subject \n <<< \n" message-subject
|
49862
|
465 " \n >>> \n to list of spam definitions. \n"
|
53730
|
466 "Don't forget to save the spam definitions to file using the spam
|
|
467 menu"))
|
49862
|
468 )))
|
|
469
|
53730
|
470 (defun rsf-add-sender-to-spam-list ()
|
49862
|
471 (interactive)
|
|
472 (set-buffer rmail-buffer)
|
|
473 (let ((message-sender))
|
|
474 (setq message-sender (mail-fetch-field "From"))
|
|
475 ;; note the use of a backquote and comma on the "from" line here,
|
|
476 ;; to make sure message-sender is actually evaluated and its value
|
|
477 ;; substituted:
|
53730
|
478 (add-to-list 'rsf-definitions-alist
|
49862
|
479 (list `(from . ,message-sender)
|
|
480 '(to . "")
|
|
481 '(subject . "")
|
53730
|
482 '(content-type . "")
|
49862
|
483 '(contents . "")
|
|
484 '(action . output-and-delete))
|
|
485 t)
|
53730
|
486 (customize-mark-to-save 'rsf-definitions-alist)
|
|
487 (if rsf-autosave-newly-added-definitions
|
49862
|
488 (progn
|
|
489 (custom-save-all)
|
65587
|
490 (message "%s" (concat "added sender \n <<< \n" message-sender
|
49862
|
491 " \n >>> \n to list of spam definitions. \n"
|
|
492 "and saved the spam definitions to file.")))
|
65587
|
493 (message "%s" (concat "added sender \n <<< \n " message-sender
|
49862
|
494 " \n >>> \n to list of spam definitions."
|
53730
|
495 "Don't forget to save the spam definitions to file using the spam
|
|
496 menu"))
|
49862
|
497 )))
|
|
498
|
|
499
|
53730
|
500 (defun rsf-add-region-to-spam-list ()
|
|
501 "Add the region makred by user in the rmail buffer to spam list.
|
|
502 Added to spam definitions as a contents field."
|
49862
|
503 (interactive)
|
|
504 (set-buffer rmail-buffer)
|
|
505 (let ((region-to-spam-list))
|
|
506 ;; check if region is inactive or has zero size:
|
|
507 (if (not (and mark-active (not (= (region-beginning) (region-end)))))
|
|
508 ;; if inactive, print error message:
|
|
509 (message "you need to first highlight some text in the rmail buffer")
|
53730
|
510 (if (< (- (region-end) (region-beginning)) rsf-min-region-to-spam-list)
|
|
511 (message
|
|
512 (concat "highlighted region is too small; min length set by variable \n"
|
|
513 "rsf-min-region-to-spam-list"
|
|
514 " is " (number-to-string rsf-min-region-to-spam-list)))
|
|
515 ;; if region active and long enough, add to list of spam definisions:
|
|
516 (progn
|
|
517 (setq region-to-spam-list (buffer-substring (region-beginning) (region-end)))
|
|
518 ;; note the use of a backquote and comma on the "from" line here,
|
|
519 ;; to make sure message-sender is actually evaluated and its value
|
|
520 ;; substituted:
|
|
521 (add-to-list 'rsf-definitions-alist
|
|
522 (list '(from . "")
|
|
523 '(to . "")
|
|
524 '(subject . "")
|
|
525 '(content-type . "")
|
|
526 `(contents . ,region-to-spam-list)
|
|
527 '(action . output-and-delete))
|
|
528 t)
|
|
529 (customize-mark-to-save 'rsf-definitions-alist)
|
|
530 (if rsf-autosave-newly-added-definitions
|
|
531 (progn
|
|
532 (custom-save-all)
|
65587
|
533 (message "%s" (concat "added highlighted text \n <<< \n" region-to-spam-list
|
53730
|
534 " \n >>> \n to list of spam definitions. \n"
|
|
535 "and saved the spam definitions to file.")))
|
65587
|
536 (message "%s" (concat "added highlighted text \n <<< \n " region-to-spam-list
|
53730
|
537 " \n >>> \n to list of spam definitions."
|
|
538 "Don't forget to save the spam definitions to file using the
|
|
539 spam menu"))
|
|
540 ))))))
|
49862
|
541
|
|
542
|
53730
|
543 (defun rsf-customize-spam-definitions ()
|
49862
|
544 (interactive)
|
53730
|
545 (customize-variable (quote rsf-definitions-alist)))
|
49862
|
546
|
53730
|
547 (defun rsf-customize-group ()
|
49862
|
548 (interactive)
|
|
549 (customize-group (quote rmail-spam-filter)))
|
|
550
|
53730
|
551 (defun rsf-custom-save-all ()
|
49862
|
552 (interactive)
|
|
553 (custom-save-all))
|
|
554
|
|
555 ;; add the actual menu items and keyboard shortcuts to both rmail and
|
|
556 ;; rmail-summary menu-bars::
|
|
557 (define-key rmail-summary-mode-map [menu-bar spam]
|
|
558 (cons "Spam" (make-sparse-keymap "Spam")))
|
|
559 (define-key rmail-mode-map [menu-bar spam]
|
|
560 (cons "Spam" (make-sparse-keymap "Spam")))
|
|
561
|
|
562 (define-key rmail-summary-mode-map [menu-bar spam customize-group]
|
53730
|
563 '("Browse customizations of rmail spam filter" . rsf-customize-group))
|
49862
|
564 (define-key rmail-mode-map [menu-bar spam customize-group]
|
53730
|
565 '("Browse customizations of rmail spam filter" . rsf-customize-group))
|
|
566 (define-key rmail-summary-mode-map "\C-cSg" 'rsf-customize-group)
|
|
567 (define-key rmail-mode-map "\C-cSg" 'rsf-customize-group)
|
49862
|
568
|
|
569 (define-key rmail-summary-mode-map [menu-bar spam customize-spam-list]
|
53730
|
570 '("Customize list of spam definitions" . rsf-customize-spam-definitions))
|
49862
|
571 (define-key rmail-mode-map [menu-bar spam customize-spam-list]
|
53730
|
572 '("Customize list of spam definitions" . rsf-customize-spam-definitions))
|
|
573 (define-key rmail-summary-mode-map "\C-cSd" 'rsf-customize-spam-definitions)
|
|
574 (define-key rmail-mode-map "\C-cSd" 'rsf-customize-spam-definitions)
|
49862
|
575
|
|
576 (define-key rmail-summary-mode-map [menu-bar spam lambda] '("----"))
|
|
577 (define-key rmail-mode-map [menu-bar spam lambda] '("----"))
|
|
578
|
|
579 (define-key rmail-summary-mode-map [menu-bar spam my-custom-save-all]
|
53730
|
580 '("save newly added spam definitions to customization file" . rsf-custom-save-all))
|
49862
|
581 (define-key rmail-mode-map [menu-bar spam my-custom-save-all]
|
53730
|
582 '("save newly added spam definitions to customization file" . rsf-custom-save-all))
|
|
583 (define-key rmail-summary-mode-map "\C-cSa" 'rsf-custom-save-all)
|
|
584 (define-key rmail-mode-map "\C-cSa" 'rsf-custom-save-all)
|
49862
|
585
|
|
586 (define-key rmail-summary-mode-map [menu-bar spam add-region-to-spam-list]
|
53730
|
587 '("add region to spam list" . rsf-add-region-to-spam-list))
|
49862
|
588 (define-key rmail-mode-map [menu-bar spam add-region-to-spam-list]
|
53730
|
589 '("add region to spam list" . rsf-add-region-to-spam-list))
|
|
590 (define-key rmail-summary-mode-map "\C-cSn" 'rsf-add-region-to-spam-list)
|
|
591 (define-key rmail-mode-map "\C-cSn" 'rsf-add-region-to-spam-list)
|
49862
|
592
|
|
593 (define-key rmail-summary-mode-map [menu-bar spam add-sender-to-spam-list]
|
53730
|
594 '("add sender to spam list" . rsf-add-sender-to-spam-list))
|
49862
|
595 (define-key rmail-mode-map [menu-bar spam add-sender-to-spam-list]
|
53730
|
596 '("add sender to spam list" . rsf-add-sender-to-spam-list))
|
|
597 (define-key rmail-summary-mode-map "\C-cSr" 'rsf-add-sender-to-spam-list)
|
|
598 (define-key rmail-mode-map "\C-cSr" 'rsf-add-sender-to-spam-list)
|
49862
|
599
|
|
600 (define-key rmail-summary-mode-map [menu-bar spam add-subject-to-spam-list]
|
53730
|
601 '("add subject to spam list" . rsf-add-subject-to-spam-list))
|
49862
|
602 (define-key rmail-mode-map [menu-bar spam add-subject-to-spam-list]
|
53730
|
603 '("add subject to spam list" . rsf-add-subject-to-spam-list))
|
|
604 (define-key rmail-summary-mode-map "\C-cSt" 'rsf-add-subject-to-spam-list)
|
|
605 (define-key rmail-mode-map "\C-cSt" 'rsf-add-subject-to-spam-list)
|
49862
|
606
|
53730
|
607 (defun rsf-add-content-type-field ()
|
72643
|
608 "Maintain backward compatibility for `rmail-spam-filter'.
|
|
609 The most recent version of `rmail-spam-filter' checks the contents
|
53730
|
610 field of the incoming mail to see if it spam. The format of
|
|
611 `rsf-definitions-alist' has therefore changed. This function
|
|
612 checks to see if old format is used, and if it is, it converts
|
|
613 `rsf-definitions-alist' to the new format. Invoked
|
|
614 automatically, no user input is required."
|
49862
|
615 (interactive)
|
53730
|
616 (if (and rsf-definitions-alist
|
|
617 (not (assoc 'content-type (car rsf-definitions-alist))))
|
|
618 (let ((result nil)
|
|
619 (current nil)
|
|
620 (definitions rsf-definitions-alist))
|
|
621 (while definitions
|
|
622 (setq current (car definitions))
|
|
623 (setq definitions (cdr definitions))
|
64754
|
624 (setq result
|
53730
|
625 (append result
|
64754
|
626 (list
|
53730
|
627 (list (assoc 'from current)
|
|
628 (assoc 'to current)
|
|
629 (assoc 'subject current)
|
|
630 (cons 'content-type "")
|
|
631 (assoc 'contents current)
|
|
632 (assoc 'action current))))))
|
|
633 (setq rsf-definitions-alist result)
|
|
634 (customize-mark-to-save 'rsf-definitions-alist)
|
|
635 (if rsf-autosave-newly-added-definitions
|
|
636 (progn
|
|
637 (custom-save-all)
|
|
638 (message (concat "converted spam definitions to new format\n"
|
|
639 "and saved the spam definitions to file.")))
|
|
640 (message (concat "converted spam definitions to new format\n"
|
|
641 "Don't forget to save the spam definitions to file using the
|
|
642 spam menu"))
|
|
643 ))))
|
49862
|
644
|
|
645 (provide 'rmail-spam-filter)
|
|
646
|
54018
|
647 ;;; arch-tag: 03e1d45d-b72f-4dd7-8f04-e7fd78249746
|
53730
|
648 ;;; rmail-spam-fitler ends here
|