(elmo-flatten): Use `append' and `listp' instead of
[elisp/wanderlust.git] / elmo / elsp-sa.el
1 ;;; elsp-sa.el --- SpamAssassin support for elmo-spam.
2 ;; Copyright (C) 2004 Yuuichi Teranishi <teranisi@gohome.org>
3
4 ;; Author: Yuuichi Teranishi <teranisi@gohome.org>
5 ;; Keywords: mail, net news, spam
6
7 ;; This file is part of Wanderlust (Yet Another Message Interface on Emacsen).
8
9 ;; This program is free software; you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation; either version 2, or (at your option)
12 ;; any later version.
13 ;;
14 ;; This program 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
21 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 ;; Boston, MA 02111-1307, USA.
23 ;;
24
25 ;;; Commentary:
26 ;;
27
28 ;;; Code:
29 ;;
30 (require 'elmo-spam)
31
32 (defgroup elmo-spam-spamassassin nil
33   "Spam SpamAssassin configuration."
34   :group 'elmo-spam)
35
36 (defcustom elmo-spam-spamassassin-program "spamassassin"
37   "Program name for SpamAssassin."
38   :type '(file :tag "Program name of SpamAssassin.")
39   :group 'elmo-spam-spamassassin)
40
41 (defcustom elmo-spam-spamassassin-learn-program "sa-learn"
42   "Program name for SpamAssassin Learner."
43   :type '(file :tag "Program name of SpamAssassin Learner.")
44   :group 'elmo-spam-spamassassin)
45
46 (defcustom elmo-spam-spamassassin-program-arguments '("-e")
47   "Program argument list for SpamAssassin."
48   :type '(file :tag "Program name of SpamAssassin Learner.")
49   :group 'elmo-spam-spamassassin)
50
51 (defcustom elmo-spam-spamassassin-learn-program-arguments nil
52   "Program argument list for SpamAssassin Learner."
53   :type '(file :tag "Program name of SpamAssassin Learner.")
54   :group 'elmo-spam-spamassassin)
55
56 (defcustom elmo-spam-spamassassin-max-messages-per-process 30
57   "Number of messages processed at once."
58   :type 'integer
59   :group 'elmo-spam-spamassassin)
60
61 (defcustom elmo-spamassassin-debug nil
62   "Non-nil to debug elmo spamassassin spam backend."
63   :type 'boolean
64   :group 'elmo-spam-spamassassin)
65
66 (eval-and-compile
67   (luna-define-class elsp-sa (elsp-generic))
68   (luna-define-internal-accessors 'elsp-sa))
69
70 (defun elmo-spamassassin-call (type &rest args)
71   (let ((pair (cond
72                ((eq type 'check)
73                 (cons elmo-spam-spamassassin-program
74                       elmo-spam-spamassassin-program-arguments))
75                ((eq type 'learn)
76                 (cons
77                  elmo-spam-spamassassin-learn-program
78                  elmo-spam-spamassassin-learn-program-arguments))
79                (t (error "Internal error")))))
80     (apply #'call-process-region
81            (point-min) (point-max)
82            (car pair)
83            nil (if elmo-spamassassin-debug
84                    (get-buffer-create "*Debug ELMO SpamAssassin*"))
85            nil (delq nil (append (cdr pair) args)))))
86
87 (luna-define-method elmo-spam-buffer-spam-p ((processor elsp-sa)
88                                              buffer &optional register)
89   (let ((result (with-current-buffer buffer
90                   (not (eq 0 (elmo-spamassassin-call 'check))))))
91     (when register
92       (if result
93           (elmo-spam-register-spam-buffer processor buffer)
94         (elmo-spam-register-good-buffer processor buffer)))
95     result))
96
97 (luna-define-method elmo-spam-register-spam-buffer ((processor elsp-sa)
98                                                     buffer &optional restore)
99   (with-current-buffer buffer
100     (eq 0 (apply 'elmo-spamassassin-call 'learn
101                  (list "--spam")))))
102
103 (luna-define-method elmo-spam-register-good-buffer ((processor elsp-sa)
104                                                     buffer &optional restore)
105   (with-current-buffer buffer
106     (eq 0 (apply 'elmo-spamassassin-call 'learn
107                  (list "--ham")))))
108
109 (defsubst elmo-spam-spamassassin-register-messages (folder
110                                                     numbers
111                                                     spam
112                                                     restore)
113   (if (not (< 0 elmo-spam-spamassassin-max-messages-per-process))
114       (error
115  "non-positive value for `elmo-spam-spamassassin-max-messages-per-process'"))
116   (with-temp-buffer
117     (while numbers
118       (let ((count 0))
119         (while (and numbers
120                     (< count elmo-spam-spamassassin-max-messages-per-process))
121           (insert "From MAILER-DAEMON@example.com\n"
122                   (with-temp-buffer
123                     (elmo-spam-message-fetch folder (car numbers))
124                     (goto-char (point-min))
125                     (while (re-search-forward "^>*From " nil t)
126                       (goto-char (match-beginning 0))
127                       (insert ?>)
128                       (forward-line))
129                     (buffer-substring (point-min) (point-max)))
130                   "\n\n")
131           (setq count (1+ count)
132                 numbers (cdr numbers)))
133         (apply 'elmo-spamassassin-call 'learn
134                (delq nil
135                      (list "--mbox"
136                            (if spam "--spam" "--ham"))))
137         (elmo-progress-notify 'elmo-spam-register count)
138         (erase-buffer)))))
139
140 (luna-define-method elmo-spam-register-spam-messages :around
141   ((processor elsp-sa) folder &optional numbers restore)
142   (let ((numbers (or numbers (elmo-folder-list-messages folder t t))))
143     (if (> (length numbers) 1)
144         (elmo-spam-spamassassin-register-messages folder numbers t restore)
145       (luna-call-next-method))))
146
147 (luna-define-method elmo-spam-register-good-messages :around
148   ((processor elsp-sa) folder &optional numbers restore)
149   (let ((numbers (or numbers (elmo-folder-list-messages folder t t))))
150     (if (> (length numbers) 1)
151         (elmo-spam-spamassassin-register-messages folder numbers nil restore)
152       (luna-call-next-method))))
153
154 (require 'product)
155 (product-provide (provide 'elsp-sa) (require 'elmo-version))
156
157 ;;; elsp-sa.el ends here