Commit | Line | Data |
---|---|---|
dda00b2c | 1 | ;;; mh-junk.el --- MH-E interface to anti-spam measures |
924df208 | 2 | |
ba318903 | 3 | ;; Copyright (C) 2003-2014 Free Software Foundation, Inc. |
924df208 BW |
4 | |
5 | ;; Author: Satyaki Das <satyaki@theforce.stanford.edu>, | |
6 | ;; Bill Wohler <wohler@newt.com> | |
7 | ;; Maintainer: Bill Wohler <wohler@newt.com> | |
8 | ;; Keywords: mail, spam | |
9 | ||
10 | ;; This file is part of GNU Emacs. | |
11 | ||
5e809f55 | 12 | ;; GNU Emacs is free software: you can redistribute it and/or modify |
924df208 | 13 | ;; it under the terms of the GNU General Public License as published by |
5e809f55 GM |
14 | ;; the Free Software Foundation, either version 3 of the License, or |
15 | ;; (at your option) any later version. | |
924df208 BW |
16 | |
17 | ;; GNU Emacs is distributed in the hope that it will be useful, | |
18 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
20 | ;; GNU General Public License for more details. | |
21 | ||
22 | ;; You should have received a copy of the GNU General Public License | |
5e809f55 | 23 | ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. |
924df208 BW |
24 | |
25 | ;;; Commentary: | |
26 | ||
27 | ;; Spam handling in MH-E. | |
28 | ||
29 | ;;; Change Log: | |
30 | ||
31 | ;;; Code: | |
32 | ||
33 | (require 'mh-e) | |
dda00b2c BW |
34 | (require 'mh-scan) |
35 | (mh-require-cl) | |
924df208 | 36 | |
924df208 | 37 | ;;;###mh-autoload |
a66894d8 BW |
38 | (defun mh-junk-blacklist (range) |
39 | "Blacklist RANGE as spam. | |
40 | ||
2dcf34f9 BW |
41 | This command trains the spam program in use (see the option |
42 | `mh-junk-program') with the content of RANGE and then handles the | |
43 | message(s) as specified by the option `mh-junk-disposition'. | |
2be362c2 | 44 | |
2dcf34f9 BW |
45 | Check the documentation of `mh-interactive-range' to see how RANGE is |
46 | read in interactive use. | |
924df208 | 47 | |
2dcf34f9 BW |
48 | For more information about using your particular spam fighting |
49 | program, see: | |
924df208 | 50 | |
f0d73c14 | 51 | - `mh-spamassassin-blacklist' |
924df208 | 52 | - `mh-bogofilter-blacklist' |
f0d73c14 | 53 | - `mh-spamprobe-blacklist'" |
a66894d8 | 54 | (interactive (list (mh-interactive-range "Blacklist"))) |
41b97610 BW |
55 | (mh-iterate-on-range () range (mh-blacklist-a-msg nil)) |
56 | (if (looking-at mh-scan-blacklisted-msg-regexp) | |
57 | (mh-next-msg))) | |
58 | ||
59 | (defun mh-blacklist-a-msg (message) | |
60 | "Blacklist MESSAGE. | |
61 | If MESSAGE is nil then the message at point is blacklisted. | |
62 | The hook `mh-blacklisted-msg-hook' is called after you mark a message | |
63 | for blacklisting." | |
64 | (save-excursion | |
65 | (if (numberp message) | |
66 | (mh-goto-msg message nil t) | |
67 | (beginning-of-line) | |
68 | (setq message (mh-get-msg-num t))) | |
69 | (cond ((looking-at mh-scan-refiled-msg-regexp) | |
70 | (error "Message %d is refiled; undo refile before blacklisting" | |
71 | message)) | |
72 | ((looking-at mh-scan-deleted-msg-regexp) | |
73 | (error "Message %d is deleted; undo delete before blacklisting" | |
74 | message)) | |
75 | ((looking-at mh-scan-whitelisted-msg-regexp) | |
76 | (error "Message %d is whitelisted; undo before blacklisting" | |
77 | message)) | |
78 | ((looking-at mh-scan-blacklisted-msg-regexp) nil) | |
79 | (t | |
80 | (mh-set-folder-modified-p t) | |
81 | (setq mh-blacklist (cons message mh-blacklist)) | |
82 | (if (not (memq message mh-seen-list)) | |
83 | (setq mh-seen-list (cons message mh-seen-list))) | |
84 | (mh-notate nil mh-note-blacklisted mh-cmd-note) | |
85 | (run-hooks 'mh-blacklist-msg-hook))))) | |
86 | ||
87 | ;;;###mh-autoload | |
88 | (defun mh-junk-blacklist-disposition () | |
89 | "Determines the fate of the selected spam." | |
90 | (cond ((null mh-junk-disposition) nil) | |
91 | ((equal mh-junk-disposition "") "+") | |
92 | ((eq (aref mh-junk-disposition 0) ?+) | |
93 | mh-junk-disposition) | |
94 | ((eq (aref mh-junk-disposition 0) ?@) | |
95 | (concat mh-current-folder "/" | |
96 | (substring mh-junk-disposition 1))) | |
97 | (t (concat "+" mh-junk-disposition)))) | |
98 | ||
99 | ;;;###mh-autoload | |
100 | (defun mh-junk-process-blacklist (range) | |
101 | "Blacklist RANGE as spam. | |
102 | This command trains the spam program in use (see the option | |
103 | `mh-junk-program') with the content of RANGE and then handles the | |
104 | message(s) as specified by the option `mh-junk-disposition'." | |
924df208 BW |
105 | (let ((blacklist-func (nth 1 (assoc mh-junk-choice mh-junk-function-alist)))) |
106 | (unless blacklist-func | |
107 | (error "Customize `mh-junk-program' appropriately")) | |
41b97610 BW |
108 | (mh-iterate-on-range msg range |
109 | (message "Blacklisting message %d..." msg) | |
110 | (funcall (symbol-function blacklist-func) msg) | |
111 | (message "Blacklisting message %d...done" msg)) | |
112 | (mh-next-msg))) | |
924df208 BW |
113 | |
114 | ;;;###mh-autoload | |
a66894d8 | 115 | (defun mh-junk-whitelist (range) |
f0d73c14 | 116 | "Whitelist RANGE as ham. |
924df208 | 117 | |
2dcf34f9 BW |
118 | This command reclassifies the RANGE as ham if it were incorrectly |
119 | classified as spam (see the option `mh-junk-program'). It then | |
120 | refiles the message into the \"+inbox\" folder. | |
924df208 | 121 | |
2dcf34f9 BW |
122 | Check the documentation of `mh-interactive-range' to see how |
123 | RANGE is read in interactive use." | |
a66894d8 | 124 | (interactive (list (mh-interactive-range "Whitelist"))) |
41b97610 BW |
125 | (mh-iterate-on-range () range (mh-junk-whitelist-a-msg nil)) |
126 | (if (looking-at mh-scan-whitelisted-msg-regexp) | |
127 | (mh-next-msg))) | |
128 | ||
129 | (defun mh-junk-whitelist-a-msg (message) | |
130 | "Whitelist MESSAGE. | |
131 | If MESSAGE is nil then the message at point is whitelisted. The | |
132 | hook `mh-whitelist-msg-hook' is called after you mark a message | |
133 | for whitelisting." | |
134 | (save-excursion | |
135 | (if (numberp message) | |
136 | (mh-goto-msg message nil t) | |
137 | (beginning-of-line) | |
138 | (setq message (mh-get-msg-num t))) | |
139 | (cond ((looking-at mh-scan-refiled-msg-regexp) | |
140 | (error "Message %d is refiled; undo refile before whitelisting" | |
141 | message)) | |
142 | ((looking-at mh-scan-deleted-msg-regexp) | |
143 | (error "Message %d is deleted; undo delete before whitelisting" | |
144 | message)) | |
145 | ((looking-at mh-scan-blacklisted-msg-regexp) | |
146 | (error "Message %d is blacklisted; undo before whitelisting" | |
147 | message)) | |
148 | ((looking-at mh-scan-whitelisted-msg-regexp) nil) | |
149 | (t | |
150 | (mh-set-folder-modified-p t) | |
151 | (setq mh-whitelist (cons message mh-whitelist)) | |
152 | (mh-notate nil mh-note-whitelisted mh-cmd-note) | |
153 | (run-hooks 'mh-whitelist-msg-hook))))) | |
154 | ||
155 | ;;;###mh-autoload | |
156 | (defun mh-junk-process-whitelist (range) | |
157 | "Whitelist RANGE as ham. | |
158 | ||
159 | This command reclassifies the RANGE as ham if it were incorrectly | |
160 | classified as spam (see the option `mh-junk-program')." | |
924df208 BW |
161 | (let ((whitelist-func (nth 2 (assoc mh-junk-choice mh-junk-function-alist)))) |
162 | (unless whitelist-func | |
163 | (error "Customize `mh-junk-program' appropriately")) | |
a66894d8 | 164 | (mh-iterate-on-range msg range |
47570699 | 165 | (message "Whitelisting message %d..." msg) |
924df208 | 166 | (funcall (symbol-function whitelist-func) msg) |
41b97610 | 167 | (message "Whitelisting message %d...done" msg)) |
924df208 BW |
168 | (mh-next-msg))) |
169 | ||
170 | \f | |
171 | ||
f0d73c14 | 172 | ;; Spamassassin Interface |
924df208 | 173 | |
f0d73c14 BW |
174 | (defvar mh-spamassassin-executable (executable-find "spamassassin")) |
175 | (defvar mh-sa-learn-executable (executable-find "sa-learn")) | |
924df208 | 176 | |
dda00b2c | 177 | ;;;###mh-autoload |
f0d73c14 BW |
178 | (defun mh-spamassassin-blacklist (msg) |
179 | "Blacklist MSG with SpamAssassin. | |
924df208 | 180 | |
af435184 | 181 | SpamAssassin is one of the more popular spam filtering programs. |
a9cc50d9 BW |
182 | Get it from your local distribution or from the SpamAssassin web |
183 | site at URL `http://spamassassin.org/'. | |
924df208 | 184 | |
af435184 BW |
185 | To use SpamAssassin, add the following recipes to |
186 | \".procmailrc\": | |
924df208 | 187 | |
25173d93 | 188 | PATH=$PATH:/usr/bin/mh |
f0d73c14 | 189 | MAILDIR=$HOME/`mhparam Path` |
924df208 | 190 | |
f0d73c14 BW |
191 | # Fight spam with SpamAssassin. |
192 | :0fw | |
193 | | spamc | |
924df208 | 194 | |
f0d73c14 BW |
195 | # Anything with a spam level of 10 or more is junked immediately. |
196 | :0: | |
197 | * ^X-Spam-Level: .......... | |
198 | /dev/null | |
924df208 | 199 | |
f0d73c14 BW |
200 | :0: |
201 | * ^X-Spam-Status: Yes | |
202 | spam/. | |
924df208 | 203 | |
5a4aad03 | 204 | If you don't use \"spamc\", use \"spamassassin -P -a\". |
924df208 | 205 | |
af435184 BW |
206 | Note that one of the recipes above throws away messages with a |
207 | score greater than or equal to 10. Here's how you can determine a | |
208 | value that works best for you. | |
924df208 | 209 | |
af435184 BW |
210 | First, run \"spamassassin -t\" on every mail message in your |
211 | archive and use Gnumeric to verify that the average plus the | |
212 | standard deviation of good mail is under 5, the SpamAssassin | |
213 | default for \"spam\". | |
924df208 | 214 | |
af435184 BW |
215 | Using Gnumeric, sort the messages by score and view the messages |
216 | with the highest score. Determine the score which encompasses all | |
217 | of your interesting messages and add a couple of points to be | |
218 | conservative. Add that many dots to the \"X-Spam-Level:\" header | |
219 | field above to send messages with that score down the drain. | |
924df208 | 220 | |
af435184 BW |
221 | In the example above, messages with a score of 5-9 are set aside |
222 | in the \"+spam\" folder for later review. The major weakness of | |
223 | rules-based filters is a plethora of false positives so it is | |
224 | worthwhile to check. | |
924df208 | 225 | |
af435184 BW |
226 | If SpamAssassin classifies a message incorrectly, or is unsure, |
227 | you can use the MH-E commands \\[mh-junk-blacklist] and | |
2dcf34f9 | 228 | \\[mh-junk-whitelist]. |
924df208 | 229 | |
af435184 BW |
230 | The command \\[mh-junk-blacklist] adds a \"blacklist_from\" entry |
231 | to \"~/spamassassin/user_prefs\", deletes the message, and sends | |
232 | the message to the Razor, so that others might not see this spam. | |
233 | If the \"sa-learn\" command is available, the message is also | |
234 | recategorized as spam. | |
924df208 | 235 | |
af435184 BW |
236 | The command \\[mh-junk-whitelist] adds a \"whitelist_from\" rule |
237 | to the \"~/.spamassassin/user_prefs\" file. If the \"sa-learn\" | |
238 | command is available, the message is also recategorized as ham. | |
2dcf34f9 BW |
239 | |
240 | Over time, you'll observe that the same host or domain occurs | |
af435184 BW |
241 | repeatedly in the \"blacklist_from\" entries, so you might think |
242 | that you could avoid future spam by blacklisting all mail from a | |
243 | particular domain. The utility function | |
244 | `mh-spamassassin-identify-spammers' helps you do precisely that. | |
245 | This function displays a frequency count of the hosts and domains | |
246 | in the \"blacklist_from\" entries from the last blank line in | |
247 | \"~/.spamassassin/user_prefs\" to the end of the file. This | |
2dcf34f9 | 248 | information can be used so that you can replace multiple |
5a4aad03 | 249 | \"blacklist_from\" entries with a single wildcard entry such as: |
924df208 | 250 | |
f0d73c14 | 251 | blacklist_from *@*amazingoffersdirect2u.com |
924df208 | 252 | |
2dcf34f9 | 253 | In versions of SpamAssassin (2.50 and on) that support a Bayesian |
af435184 BW |
254 | classifier, \\[mh-junk-blacklist] uses the program \"sa-learn\" |
255 | to recategorize the message as spam. Neither MH-E, nor | |
256 | SpamAssassin, rebuilds the database after adding words, so you | |
257 | will need to run \"sa-learn --rebuild\" periodically. This can be | |
258 | done by adding the following to your crontab: | |
924df208 | 259 | |
dda00b2c | 260 | 0 * * * * sa-learn --rebuild > /dev/null 2>&1" |
924df208 | 261 | (unless mh-spamassassin-executable |
f0d73c14 | 262 | (error "Unable to find the spamassassin executable")) |
924df208 BW |
263 | (let ((current-folder mh-current-folder) |
264 | (msg-file (mh-msg-filename msg mh-current-folder)) | |
265 | (sender)) | |
a4de8c3d SG |
266 | (message "Reporting message %d..." msg) |
267 | (mh-truncate-log-buffer) | |
268 | ;; Put call-process output in log buffer if we are saving it | |
269 | ;; (this happens if mh-junk-background is t). | |
270 | (with-current-buffer mh-log-buffer | |
271 | (call-process mh-spamassassin-executable msg-file mh-junk-background nil | |
f0d73c14 BW |
272 | ;;"--report" "--remove-from-whitelist" |
273 | "-r" "-R") ; spamassassin V2.20 | |
a4de8c3d SG |
274 | (when mh-sa-learn-executable |
275 | (message "Recategorizing message %d as spam..." msg) | |
276 | (mh-truncate-log-buffer) | |
277 | (call-process mh-sa-learn-executable msg-file mh-junk-background nil | |
278 | "--single" "--spam" "--local" "--no-rebuild"))) | |
279 | (message "Blacklisting sender of message %d..." msg) | |
280 | (with-current-buffer (get-buffer-create mh-temp-buffer) | |
924df208 | 281 | (erase-buffer) |
e495eaec | 282 | (call-process (expand-file-name mh-scan-prog mh-progs) |
a4de8c3d SG |
283 | nil t nil |
284 | (format "%d" msg) current-folder | |
924df208 BW |
285 | "-format" "%<(mymbox{from})%|%(addr{from})%>") |
286 | (goto-char (point-min)) | |
287 | (if (search-forward-regexp "^\\(.+\\)$" nil t) | |
288 | (progn | |
289 | (setq sender (match-string 0)) | |
290 | (mh-spamassassin-add-rule "blacklist_from" sender) | |
a4de8c3d SG |
291 | (message "Blacklisting sender of message %d...done" msg)) |
292 | (message "Blacklisting sender of message %d...not done (from my address)" msg))))) | |
924df208 | 293 | |
dda00b2c | 294 | ;;;###mh-autoload |
924df208 | 295 | (defun mh-spamassassin-whitelist (msg) |
f0d73c14 BW |
296 | "Whitelist MSG with SpamAssassin. |
297 | ||
5a4aad03 BW |
298 | The \\[mh-junk-whitelist] command adds a \"whitelist_from\" rule to |
299 | the \"~/.spamassassin/user_prefs\" file. If the \"sa-learn\" command | |
2dcf34f9 | 300 | is available, the message is also recategorized as ham. |
f0d73c14 BW |
301 | |
302 | See `mh-spamassassin-blacklist' for more information." | |
924df208 | 303 | (unless mh-spamassassin-executable |
f0d73c14 | 304 | (error "Unable to find the spamassassin executable")) |
924df208 BW |
305 | (let ((msg-file (mh-msg-filename msg mh-current-folder)) |
306 | (show-buffer (get-buffer mh-show-buffer)) | |
307 | from) | |
a4de8c3d | 308 | (with-current-buffer (get-buffer-create mh-temp-buffer) |
924df208 | 309 | (erase-buffer) |
a4de8c3d SG |
310 | (message "Removing spamassassin markup from message %d..." msg) |
311 | (call-process mh-spamassassin-executable msg-file t nil | |
f0d73c14 BW |
312 | ;; "--remove-markup" |
313 | "-d") ; spamassassin V2.20 | |
924df208 BW |
314 | (if show-buffer |
315 | (kill-buffer show-buffer)) | |
316 | (write-file msg-file) | |
317 | (when mh-sa-learn-executable | |
a4de8c3d SG |
318 | (message "Recategorizing message %d as ham..." msg) |
319 | (mh-truncate-log-buffer) | |
320 | ;; Put call-process output in log buffer if we are saving it | |
321 | ;; (this happens if mh-junk-background is t). | |
322 | (with-current-buffer mh-log-buffer | |
323 | (call-process mh-sa-learn-executable msg-file mh-junk-background nil | |
324 | "--single" "--ham" "--local" "--no-rebuild"))) | |
325 | (message "Whitelisting sender of message %d..." msg) | |
f0d73c14 BW |
326 | (setq from |
327 | (car (mh-funcall-if-exists | |
328 | ietf-drums-parse-address (mh-get-header-field "From:")))) | |
924df208 | 329 | (kill-buffer nil) |
f0d73c14 | 330 | (unless (or (null from) (equal from "")) |
924df208 | 331 | (mh-spamassassin-add-rule "whitelist_from" from)) |
a4de8c3d | 332 | (message "Whitelisting sender of message %d...done" msg)))) |
924df208 BW |
333 | |
334 | (defun mh-spamassassin-add-rule (rule body) | |
5a4aad03 | 335 | "Add a new rule to \"~/.spamassassin/user_prefs\". |
924df208 BW |
336 | The name of the rule is RULE and its body is BODY." |
337 | (save-window-excursion | |
338 | (let* ((line (format "%s\t%s\n" rule body)) | |
339 | (case-fold-search t) | |
340 | (file (expand-file-name "~/.spamassassin/user_prefs")) | |
341 | (buffer-exists (find-buffer-visiting file))) | |
342 | (find-file file) | |
343 | (if (not (search-forward (format "\n%s" line) nil t)) | |
344 | (progn | |
345 | (goto-char (point-max)) | |
346 | (insert (if (bolp) "" "\n") line) | |
347 | (save-buffer))) | |
348 | (if (not buffer-exists) | |
349 | (kill-buffer nil))))) | |
350 | ||
dda00b2c | 351 | ;;;###mh-autoload |
924df208 | 352 | (defun mh-spamassassin-identify-spammers () |
f0d73c14 | 353 | "Identify spammers who are repeat offenders. |
924df208 | 354 | |
2dcf34f9 | 355 | This function displays a frequency count of the hosts and domains |
5a4aad03 BW |
356 | in the \"blacklist_from\" entries from the last blank line in |
357 | \"~/.spamassassin/user_prefs\" to the end of the file. This | |
2dcf34f9 | 358 | information can be used so that you can replace multiple |
5a4aad03 | 359 | \"blacklist_from\" entries with a single wildcard entry such as: |
924df208 | 360 | |
f0d73c14 | 361 | blacklist_from *@*amazingoffersdirect2u.com" |
924df208 BW |
362 | (interactive) |
363 | (let* ((file (expand-file-name "~/.spamassassin/user_prefs")) | |
364 | (domains (make-hash-table :test 'equal))) | |
365 | (find-file file) | |
366 | ;; Only consider entries between last blank line and end of file. | |
367 | (goto-char (1- (point-max))) | |
368 | (search-backward-regexp "^$") | |
369 | ;; Perform frequency count. | |
370 | (save-excursion | |
371 | (while (search-forward-regexp "^blacklist_from\\s-*\\(.*\\)@\\(.*\\)$" | |
372 | nil t) | |
373 | (let ((host (match-string 2)) | |
374 | value) | |
375 | ;; Remove top-level-domain from hostname. | |
376 | (setq host (cdr (reverse (split-string host "\\.")))) | |
377 | ;; Add counts for each host and domain part. | |
378 | (while host | |
379 | (setq value (gethash (car host) domains)) | |
f0d73c14 | 380 | (setf (gethash (car host) domains) (1+ (if (not value) 0 value))) |
924df208 BW |
381 | (setq host (cdr host)))))) |
382 | ||
383 | ;; Output | |
384 | (delete-other-windows) | |
385 | (pop-to-buffer (get-buffer-create "*MH-E Spammer Frequencies*")) | |
386 | (erase-buffer) | |
4f91a816 SM |
387 | (maphash (lambda (key value) "" |
388 | (if (> value 2) | |
389 | (insert (format "%s %s\n" key value)))) | |
924df208 BW |
390 | domains) |
391 | (sort-numeric-fields 2 (point-min) (point-max)) | |
392 | (reverse-region (point-min) (point-max)) | |
393 | (goto-char (point-min)))) | |
394 | ||
f0d73c14 BW |
395 | \f |
396 | ||
397 | ;; Bogofilter Interface | |
398 | ||
399 | (defvar mh-bogofilter-executable (executable-find "bogofilter")) | |
400 | ||
dda00b2c | 401 | ;;;###mh-autoload |
f0d73c14 | 402 | (defun mh-bogofilter-blacklist (msg) |
f09e2a44 | 403 | "Blacklist MSG with bogofilter. |
f0d73c14 | 404 | |
2dcf34f9 | 405 | Bogofilter is a Bayesian spam filtering program. Get it from your |
a9cc50d9 BW |
406 | local distribution or from the bogofilter web site at URL |
407 | `http://bogofilter.sourceforge.net/'. | |
f0d73c14 BW |
408 | |
409 | Bogofilter is taught by running: | |
410 | ||
411 | bogofilter -n < good-message | |
412 | ||
413 | on every good message, and | |
414 | ||
415 | bogofilter -s < spam-message | |
416 | ||
417 | on every spam message. This is called a full training; three other | |
2dcf34f9 BW |
418 | training methods are described in the FAQ that is distributed with |
419 | bogofilter. Note that most Bayesian filters need 1000 to 5000 of each | |
420 | type of message to start doing a good job. | |
f0d73c14 | 421 | |
5a4aad03 | 422 | To use bogofilter, add the following recipes to \".procmailrc\": |
f0d73c14 | 423 | |
b4f8b162 | 424 | PATH=$PATH:/usr/bin/mh |
f0d73c14 BW |
425 | MAILDIR=$HOME/`mhparam Path` |
426 | ||
f09e2a44 | 427 | # Fight spam with bogofilter. |
f0d73c14 BW |
428 | :0fw |
429 | | bogofilter -3 -e -p | |
430 | ||
431 | :0: | |
432 | * ^X-Bogosity: Yes, tests=bogofilter | |
433 | spam/. | |
434 | ||
435 | :0: | |
436 | * ^X-Bogosity: Unsure, tests=bogofilter | |
437 | spam/unsure/. | |
438 | ||
2dcf34f9 BW |
439 | If bogofilter classifies a message incorrectly, or is unsure, you can |
440 | use the MH-E commands \\[mh-junk-blacklist] and \\[mh-junk-whitelist] | |
441 | to update bogofilter's training. | |
f0d73c14 BW |
442 | |
443 | The \"Bogofilter FAQ\" suggests that you run the following | |
444 | occasionally to shrink the database: | |
445 | ||
446 | bogoutil -d wordlist.db | bogoutil -l wordlist.db.new | |
447 | mv wordlist.db wordlist.db.prv | |
448 | mv wordlist.db.new wordlist.db | |
449 | ||
450 | The \"Bogofilter tuning HOWTO\" describes how you can fine-tune Bogofilter." | |
451 | (unless mh-bogofilter-executable | |
452 | (error "Unable to find the bogofilter executable")) | |
453 | (let ((msg-file (mh-msg-filename msg mh-current-folder))) | |
a4de8c3d SG |
454 | (mh-truncate-log-buffer) |
455 | ;; Put call-process output in log buffer if we are saving it | |
456 | ;; (this happens if mh-junk-background is t). | |
457 | (with-current-buffer mh-log-buffer | |
458 | (call-process mh-bogofilter-executable msg-file mh-junk-background | |
459 | nil "-s")))) | |
f0d73c14 | 460 | |
dda00b2c | 461 | ;;;###mh-autoload |
f0d73c14 | 462 | (defun mh-bogofilter-whitelist (msg) |
f09e2a44 | 463 | "Whitelist MSG with bogofilter. |
f0d73c14 BW |
464 | |
465 | See `mh-bogofilter-blacklist' for more information." | |
466 | (unless mh-bogofilter-executable | |
467 | (error "Unable to find the bogofilter executable")) | |
468 | (let ((msg-file (mh-msg-filename msg mh-current-folder))) | |
a4de8c3d SG |
469 | (mh-truncate-log-buffer) |
470 | ;; Put call-process output in log buffer if we are saving it | |
471 | ;; (this happens if mh-junk-background is t). | |
472 | (with-current-buffer mh-log-buffer | |
473 | (call-process mh-bogofilter-executable msg-file mh-junk-background | |
474 | nil "-n")))) | |
f0d73c14 BW |
475 | |
476 | \f | |
477 | ||
478 | ;; Spamprobe Interface | |
479 | ||
480 | (defvar mh-spamprobe-executable (executable-find "spamprobe")) | |
481 | ||
dda00b2c | 482 | ;;;###mh-autoload |
f0d73c14 BW |
483 | (defun mh-spamprobe-blacklist (msg) |
484 | "Blacklist MSG with SpamProbe. | |
485 | ||
a9cc50d9 BW |
486 | SpamProbe is a Bayesian spam filtering program. Get it from your |
487 | local distribution or from the SpamProbe web site at URL | |
488 | `http://spamprobe.sourceforge.net'. | |
f0d73c14 | 489 | |
5a4aad03 | 490 | To use SpamProbe, add the following recipes to \".procmailrc\": |
f0d73c14 | 491 | |
b4f8b162 | 492 | PATH=$PATH:/usr/bin/mh |
f0d73c14 BW |
493 | MAILDIR=$HOME/`mhparam Path` |
494 | ||
495 | # Fight spam with SpamProbe. | |
496 | :0 | |
497 | SCORE=| spamprobe receive | |
498 | ||
499 | :0 wf | |
500 | | formail -I \"X-SpamProbe: $SCORE\" | |
501 | ||
502 | :0: | |
503 | *^X-SpamProbe: SPAM | |
504 | spam/. | |
505 | ||
2dcf34f9 BW |
506 | If SpamProbe classifies a message incorrectly, you can use the |
507 | MH-E commands \\[mh-junk-blacklist] and \\[mh-junk-whitelist] to | |
508 | update SpamProbe's training." | |
f0d73c14 BW |
509 | (unless mh-spamprobe-executable |
510 | (error "Unable to find the spamprobe executable")) | |
511 | (let ((msg-file (mh-msg-filename msg mh-current-folder))) | |
a4de8c3d SG |
512 | (mh-truncate-log-buffer) |
513 | ;; Put call-process output in log buffer if we are saving it | |
514 | ;; (this happens if mh-junk-background is t). | |
515 | (with-current-buffer mh-log-buffer | |
516 | (call-process mh-spamprobe-executable msg-file mh-junk-background | |
517 | nil "spam")))) | |
f0d73c14 | 518 | |
dda00b2c | 519 | ;;;###mh-autoload |
f0d73c14 BW |
520 | (defun mh-spamprobe-whitelist (msg) |
521 | "Whitelist MSG with SpamProbe. | |
522 | ||
523 | See `mh-spamprobe-blacklist' for more information." | |
524 | (unless mh-spamprobe-executable | |
525 | (error "Unable to find the spamprobe executable")) | |
526 | (let ((msg-file (mh-msg-filename msg mh-current-folder))) | |
a4de8c3d SG |
527 | (mh-truncate-log-buffer) |
528 | ;; Put call-process output in log buffer if we are saving it | |
529 | ;; (this happens if mh-junk-background is t). | |
530 | (with-current-buffer mh-log-buffer | |
531 | (call-process mh-spamprobe-executable msg-file mh-junk-background | |
532 | nil "good")))) | |
f0d73c14 | 533 | |
924df208 BW |
534 | (provide 'mh-junk) |
535 | ||
cee9f5c6 BW |
536 | ;; Local Variables: |
537 | ;; indent-tabs-mode: nil | |
538 | ;; sentence-end-double-space: nil | |
539 | ;; End: | |
924df208 BW |
540 | |
541 | ;;; mh-junk.el ends here |