avoid recursive `require' when loading semantic
[bpt/emacs.git] / lisp / mh-e / mh-junk.el
CommitLineData
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
41This command trains the spam program in use (see the option
42`mh-junk-program') with the content of RANGE and then handles the
43message(s) as specified by the option `mh-junk-disposition'.
2be362c2 44
2dcf34f9
BW
45Check the documentation of `mh-interactive-range' to see how RANGE is
46read in interactive use.
924df208 47
2dcf34f9
BW
48For more information about using your particular spam fighting
49program, 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.
61If MESSAGE is nil then the message at point is blacklisted.
62The hook `mh-blacklisted-msg-hook' is called after you mark a message
63for 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.
102This command trains the spam program in use (see the option
103`mh-junk-program') with the content of RANGE and then handles the
104message(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
118This command reclassifies the RANGE as ham if it were incorrectly
119classified as spam (see the option `mh-junk-program'). It then
120refiles the message into the \"+inbox\" folder.
924df208 121
2dcf34f9
BW
122Check the documentation of `mh-interactive-range' to see how
123RANGE 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.
131If MESSAGE is nil then the message at point is whitelisted. The
132hook `mh-whitelist-msg-hook' is called after you mark a message
133for 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
159This command reclassifies the RANGE as ham if it were incorrectly
160classified 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 181SpamAssassin is one of the more popular spam filtering programs.
a9cc50d9
BW
182Get it from your local distribution or from the SpamAssassin web
183site at URL `http://spamassassin.org/'.
924df208 184
af435184
BW
185To 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 204If you don't use \"spamc\", use \"spamassassin -P -a\".
924df208 205
af435184
BW
206Note that one of the recipes above throws away messages with a
207score greater than or equal to 10. Here's how you can determine a
208value that works best for you.
924df208 209
af435184
BW
210First, run \"spamassassin -t\" on every mail message in your
211archive and use Gnumeric to verify that the average plus the
212standard deviation of good mail is under 5, the SpamAssassin
213default for \"spam\".
924df208 214
af435184
BW
215Using Gnumeric, sort the messages by score and view the messages
216with the highest score. Determine the score which encompasses all
217of your interesting messages and add a couple of points to be
218conservative. Add that many dots to the \"X-Spam-Level:\" header
219field above to send messages with that score down the drain.
924df208 220
af435184
BW
221In the example above, messages with a score of 5-9 are set aside
222in the \"+spam\" folder for later review. The major weakness of
223rules-based filters is a plethora of false positives so it is
224worthwhile to check.
924df208 225
af435184
BW
226If SpamAssassin classifies a message incorrectly, or is unsure,
227you can use the MH-E commands \\[mh-junk-blacklist] and
2dcf34f9 228\\[mh-junk-whitelist].
924df208 229
af435184
BW
230The command \\[mh-junk-blacklist] adds a \"blacklist_from\" entry
231to \"~/spamassassin/user_prefs\", deletes the message, and sends
232the message to the Razor, so that others might not see this spam.
233If the \"sa-learn\" command is available, the message is also
234recategorized as spam.
924df208 235
af435184
BW
236The command \\[mh-junk-whitelist] adds a \"whitelist_from\" rule
237to the \"~/.spamassassin/user_prefs\" file. If the \"sa-learn\"
238command is available, the message is also recategorized as ham.
2dcf34f9
BW
239
240Over time, you'll observe that the same host or domain occurs
af435184
BW
241repeatedly in the \"blacklist_from\" entries, so you might think
242that you could avoid future spam by blacklisting all mail from a
243particular domain. The utility function
244`mh-spamassassin-identify-spammers' helps you do precisely that.
245This function displays a frequency count of the hosts and domains
246in the \"blacklist_from\" entries from the last blank line in
247\"~/.spamassassin/user_prefs\" to the end of the file. This
2dcf34f9 248information 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 253In versions of SpamAssassin (2.50 and on) that support a Bayesian
af435184
BW
254classifier, \\[mh-junk-blacklist] uses the program \"sa-learn\"
255to recategorize the message as spam. Neither MH-E, nor
256SpamAssassin, rebuilds the database after adding words, so you
257will need to run \"sa-learn --rebuild\" periodically. This can be
258done 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
298The \\[mh-junk-whitelist] command adds a \"whitelist_from\" rule to
299the \"~/.spamassassin/user_prefs\" file. If the \"sa-learn\" command
2dcf34f9 300is available, the message is also recategorized as ham.
f0d73c14
BW
301
302See `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
336The 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 355This function displays a frequency count of the hosts and domains
5a4aad03
BW
356in the \"blacklist_from\" entries from the last blank line in
357\"~/.spamassassin/user_prefs\" to the end of the file. This
2dcf34f9 358information 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 405Bogofilter is a Bayesian spam filtering program. Get it from your
a9cc50d9
BW
406local distribution or from the bogofilter web site at URL
407`http://bogofilter.sourceforge.net/'.
f0d73c14
BW
408
409Bogofilter is taught by running:
410
411 bogofilter -n < good-message
412
413on every good message, and
414
415 bogofilter -s < spam-message
416
417on every spam message. This is called a full training; three other
2dcf34f9
BW
418training methods are described in the FAQ that is distributed with
419bogofilter. Note that most Bayesian filters need 1000 to 5000 of each
420type of message to start doing a good job.
f0d73c14 421
5a4aad03 422To 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
439If bogofilter classifies a message incorrectly, or is unsure, you can
440use the MH-E commands \\[mh-junk-blacklist] and \\[mh-junk-whitelist]
441to update bogofilter's training.
f0d73c14
BW
442
443The \"Bogofilter FAQ\" suggests that you run the following
444occasionally 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
450The \"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
465See `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
486SpamProbe is a Bayesian spam filtering program. Get it from your
487local distribution or from the SpamProbe web site at URL
488`http://spamprobe.sourceforge.net'.
f0d73c14 489
5a4aad03 490To 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
506If SpamProbe classifies a message incorrectly, you can use the
507MH-E commands \\[mh-junk-blacklist] and \\[mh-junk-whitelist] to
508update 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
523See `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