1 ;;; wl-refile.el -- Refile modules for Wanderlust.
3 ;; Copyright 1998,1999,2000 Yuuichi Teranishi <teranisi@gohome.org>
5 ;; Author: Yuuichi Teranishi <teranisi@gohome.org>
6 ;; Keywords: mail, net news
7 ;; Time-stamp: <00/04/05 01:20:16 teranisi>
9 ;; This file is part of Wanderlust (Yet Another Message Interface on Emacsen).
11 ;; This program is free software; you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation; either version 2, or (at your option)
16 ;; This program is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 ;; GNU General Public License for more details.
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs; see the file COPYING. If not, write to the
23 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24 ;; Boston, MA 02111-1307, USA.
38 (defvar wl-refile-alist nil)
39 (defvar wl-refile-alist-file-name "refile-alist")
40 ;; should be renamed to "refile-from-alist"
41 (defvar wl-refile-msgid-alist nil)
42 (defvar wl-refile-msgid-alist-file-name "refile-msgid-alist")
44 (defvar wl-refile-alist-max-length 1000)
46 (defun wl-refile-alist-setup ()
49 (expand-file-name wl-refile-alist-file-name
51 (setq wl-refile-msgid-alist
53 (expand-file-name wl-refile-msgid-alist-file-name
56 (defun wl-refile-alist-save (file-name alist)
58 (let ((filename (expand-file-name file-name
60 (tmp-buffer (get-buffer-create " *wl-refile-alist-tmp*")))
61 (set-buffer tmp-buffer)
63 (if (> (length alist) wl-refile-alist-max-length)
64 (setcdr (nthcdr (1- wl-refile-alist-max-length) alist) nil))
65 (prin1 alist tmp-buffer)
66 (princ "\n" tmp-buffer)
67 (if (file-writable-p filename)
68 (write-region (point-min) (point-max)
70 (message (format "%s is not writable." filename)))
71 (kill-buffer tmp-buffer))))
73 (defun wl-refile-learn (entity dst)
74 (let (tocc-list from key hit ml)
75 (setq dst (elmo-string dst))
79 (downcase (wl-address-header-extract-address entity))))
82 (elmo-msgdb-overview-entity-get-to entity) ","
83 (elmo-msgdb-overview-entity-get-cc entity)))))
87 (mapcar (function downcase) wl-subscribed-mailing-list))
88 (setq ml (car tocc-list)
90 (setq tocc-list (cdr tocc-list))))
92 (setq key ml) ; subscribed entity!!
93 (or (wl-address-user-mail-address-p
96 (wl-address-header-extract-address
97 (elmo-msgdb-overview-entity-get-from
101 (wl-refile-msgid-learn entity dst))
103 (if (setq hit (assoc key wl-refile-alist))
105 (setq wl-refile-alist
106 (nconc wl-refile-alist (list (cons key dst))))))))
108 (defun wl-refile-msgid-learn (entity dst)
109 (let ((key (elmo-msgdb-overview-entity-get-id entity))
111 (setq dst (elmo-string dst))
113 (if (setq hit (assoc key wl-refile-msgid-alist))
115 (setq wl-refile-msgid-alist (cons (cons key dst)
116 wl-refile-msgid-alist))))))
121 (defvar wl-refile-guess-func-list
122 '(wl-refile-guess-by-rule
123 wl-refile-guess-by-msgid
124 wl-refile-guess-by-history)
125 "*Functions in this list are used for guessing refile destination folder.")
127 (defun wl-refile-guess (entity)
128 (let ((flist wl-refile-guess-func-list) guess)
130 (if (setq guess (funcall (car flist) entity))
132 (setq flist (cdr flist))))
135 (defun wl-refile-evaluate-rule (rule entity)
136 "Returns folder string if RULE is matched to ENTITY.
137 If RULE does not match ENTITY, returns nil."
138 (let ((case-fold-search t)
139 fields guess pairs value)
141 ((stringp rule) rule)
143 (setq fields (car rule))
145 (if (setq guess (wl-refile-evaluate-rule (append (list (car fields))
149 (setq fields (cdr fields))))
151 ((stringp (car rule))
152 (setq pairs (cdr rule))
153 (setq value (wl-refile-get-field-value entity (car rule)))
155 (if (and (stringp value)
159 (setq guess (wl-refile-expand-newtext
160 (wl-refile-evaluate-rule (cdr (car pairs))
164 (setq pairs (cdr pairs))))
166 (t (error "Invalid structure for wl-refile-rule-alist")))))
168 (defun wl-refile-get-field-value (entity field)
169 "Get FIELD value from ENTITY."
170 (let ((field (downcase field))
171 (fixed-fields '("from" "subject" "to" "cc")))
172 (if (member field fixed-fields)
173 (funcall (symbol-function
175 "elmo-msgdb-overview-entity-get-"
178 (elmo-msgdb-overview-entity-get-extra-field entity field))))
180 (defun wl-refile-expand-newtext (newtext original)
181 (let ((len (length newtext))
183 c expanded beg N did-expand)
186 (while (and (< pos len)
187 (not (= (aref newtext pos) ?\\)))
190 (push (substring newtext beg pos) expanded))
192 ;; We hit a \; expand it.
195 c (aref newtext pos))
196 (if (not (or (= c ?\&)
199 ;; \ followed by some character we don't expand.
200 (push (char-to-string c) expanded)
205 (when (match-beginning N)
206 (push (substring original (match-beginning N) (match-end N))
210 (apply (function concat) (nreverse expanded))
213 (defun wl-refile-guess-by-rule (entity)
214 (let ((rules wl-refile-rule-alist)
217 (if (setq guess (wl-refile-evaluate-rule (car rules) entity))
219 (setq rules (cdr rules))))
222 (defun wl-refile-guess-by-history (entity)
226 (downcase (wl-address-header-extract-address entity))))
229 (elmo-msgdb-overview-entity-get-to entity) ","
230 (elmo-msgdb-overview-entity-get-cc entity)))))
232 (setq tocc-list (elmo-list-delete
233 (or wl-user-mail-address-list
234 (list (wl-address-header-extract-address wl-from)))
237 (if (setq ret-val (cdr (assoc (car tocc-list) wl-refile-alist)))
239 (setq tocc-list (cdr tocc-list))))
241 (wl-refile-guess-by-from entity))))
243 (defun wl-refile-get-account-part-from-address (address)
244 (if (string-match "\\([^@]+\\)@[^@]+" address)
245 (wl-match-string 1 address)
248 (defun wl-refile-guess-by-from (entity)
250 (downcase (wl-address-header-extract-address
251 (elmo-msgdb-overview-entity-get-from entity)))))
253 (or (cdr (assoc from wl-refile-alist))
254 (format "%s/%s" wl-refile-default-from-folder
255 (wl-refile-get-account-part-from-address from)))))
257 (defun wl-refile-guess-by-msgid (entity)
258 (cdr (assoc (elmo-msgdb-overview-entity-get-references entity)
259 wl-refile-msgid-alist)))
261 ;;; wl-refile.el ends here