1 ;;; wl-refile.el --- Refile modules for Wanderlust.
3 ;; Copyright (C) 1998,1999,2000 Yuuichi Teranishi <teranisi@gohome.org>
5 ;; Author: Yuuichi Teranishi <teranisi@gohome.org>
6 ;; Keywords: mail, net news
8 ;; This file is part of Wanderlust (Yet Another Message Interface on Emacsen).
10 ;; This program is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 2, or (at your option)
15 ;; This program is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs; see the file COPYING. If not, write to the
22 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
35 (defvar wl-refile-alist nil)
36 (defvar wl-refile-alist-file-name "refile-alist")
37 ;; should be renamed to "refile-from-alist"
38 (defvar wl-refile-msgid-alist nil)
39 (defvar wl-refile-msgid-alist-file-name "refile-msgid-alist")
40 (defvar wl-refile-subject-alist nil)
41 (defvar wl-refile-subject-alist-file-name "refile-subject-alist")
43 (defvar wl-refile-default-from-folder-path-separator "/")
45 (defvar wl-refile-alist-max-length 1000)
47 (defun wl-refile-alist-setup ()
48 (let ((flist wl-refile-guess-functions))
51 ((eq (car flist) 'wl-refile-guess-by-history)
54 (expand-file-name wl-refile-alist-file-name
55 elmo-msgdb-directory) elmo-mime-charset)))
56 ((eq (car flist) 'wl-refile-guess-by-msgid)
57 (setq wl-refile-msgid-alist
59 (expand-file-name wl-refile-msgid-alist-file-name
60 elmo-msgdb-directory) elmo-mime-charset)))
61 ((eq (car flist) 'wl-refile-guess-by-subject)
62 (setq wl-refile-subject-alist
64 (expand-file-name wl-refile-subject-alist-file-name
65 elmo-msgdb-directory) elmo-mime-charset))))
66 (setq flist (cdr flist)))))
68 (defun wl-refile-alist-save ()
70 (wl-refile-alist-save-file
71 wl-refile-alist-file-name wl-refile-alist))
72 (if wl-refile-msgid-alist
73 (wl-refile-alist-save-file
74 wl-refile-msgid-alist-file-name wl-refile-msgid-alist))
75 (if wl-refile-subject-alist
76 (wl-refile-alist-save-file
77 wl-refile-subject-alist-file-name wl-refile-subject-alist)))
79 (defun wl-refile-alist-save-file (file-name alist)
80 (if (> (length alist) wl-refile-alist-max-length)
81 (setcdr (nthcdr (1- wl-refile-alist-max-length) alist) nil))
82 (elmo-object-save (expand-file-name file-name elmo-msgdb-directory)
83 alist elmo-mime-charset))
85 (defun wl-refile-learn (entity dst)
86 (let (tocc-list from key hit ml)
87 (setq dst (elmo-string dst))
91 (downcase (wl-address-header-extract-address entity))))
94 (elmo-message-entity-field entity 'to) ","
95 (elmo-message-entity-field entity 'cc)))))
99 (mapcar (function downcase) wl-subscribed-mailing-list))
100 (setq ml (car tocc-list)
102 (setq tocc-list (cdr tocc-list))))
104 (setq key ml) ; subscribed entity!!
105 (or (wl-address-user-mail-address-p
108 (wl-address-header-extract-address
109 (elmo-message-entity-field entity 'from)))))
111 (if (or wl-refile-msgid-alist
112 (memq 'wl-refile-guess-by-msgid
113 wl-refile-guess-functions))
114 (wl-refile-msgid-learn entity dst))
115 (if (or wl-refile-subject-alist
116 (memq 'wl-refile-guess-by-subject
117 wl-refile-guess-functions))
118 (wl-refile-subject-learn entity dst)))
120 (if (setq hit (assoc key wl-refile-alist))
121 (setq wl-refile-alist (delq hit wl-refile-alist)))
122 (setq wl-refile-alist (cons (cons key dst)
125 (defun wl-refile-msgid-learn (entity dst)
126 (let ((key (elmo-message-entity-field entity 'message-id))
128 (setq dst (elmo-string dst))
130 (if (setq hit (assoc key wl-refile-msgid-alist))
132 (setq wl-refile-msgid-alist (cons (cons key dst)
133 wl-refile-msgid-alist))))))
135 (defun wl-refile-subject-learn (entity dst)
136 (let ((subject (funcall wl-summary-subject-filter-function
137 (elmo-message-entity-field entity 'subject 'decode)))
139 (setq dst (elmo-string dst))
140 (if (and subject (not (string= subject "")))
141 (if (setq hit (assoc subject wl-refile-subject-alist))
143 (setq wl-refile-subject-alist (cons (cons subject dst)
144 wl-refile-subject-alist))))))
149 (defvar wl-refile-guess-functions
150 '(wl-refile-guess-by-rule
151 wl-refile-guess-by-msgid
152 wl-refile-guess-by-subject
153 wl-refile-guess-by-history
154 wl-refile-guess-by-from)
155 "*Functions in this list are used for guessing refile destination folder.")
157 ;; 2000-11-05: *-func-list -> *-functions
158 (elmo-define-obsolete-variable 'wl-refile-guess-func-list
159 'wl-refile-guess-functions)
161 (defun wl-refile-guess (entity &optional functions)
162 (let ((flist (or functions wl-refile-guess-functions))
165 (if (setq guess (funcall (car flist) entity))
167 (setq flist (cdr flist))))
170 (defun wl-refile-evaluate-rule (rule entity)
171 "Return folder string if RULE is matched to ENTITY.
172 If RULE does not match ENTITY, returns nil."
173 (let ((case-fold-search t)
174 fields guess pairs value)
176 ((stringp rule) rule)
178 (setq fields (car rule))
180 (if (setq guess (wl-refile-evaluate-rule (append (list (car fields))
184 (setq fields (cdr fields))))
186 ((stringp (car rule))
187 (setq pairs (cdr rule))
188 (setq value (wl-refile-get-field-value entity (car rule)))
190 (if (and (stringp value)
194 (setq guess (wl-expand-newtext
195 (wl-refile-evaluate-rule (cdr (car pairs))
199 (setq pairs (cdr pairs))))
201 (t (error "Invalid structure for wl-refile-rule-alist")))))
203 (defun wl-refile-get-field-value (entity field)
204 "Get FIELD value from ENTITY."
205 (elmo-message-entity-field entity (intern (downcase field)) 'decode))
207 (defun wl-refile-guess-by-rule (entity)
208 (let ((rules wl-refile-rule-alist)
211 (if (setq guess (wl-refile-evaluate-rule (car rules) entity))
213 (setq rules (cdr rules))))
216 (defun wl-refile-guess-by-history (entity)
220 (downcase (wl-address-header-extract-address entity))))
223 (elmo-message-entity-field entity 'to) ","
224 (elmo-message-entity-field entity 'cc)))))
226 (setq tocc-list (wl-address-delete-user-mail-addresses tocc-list))
228 (if (setq ret-val (cdr (assoc (car tocc-list) wl-refile-alist)))
230 (setq tocc-list (cdr tocc-list))))
233 (defun wl-refile-get-account-part-from-address (address)
234 (if (string-match "\\([^@]+\\)@[^@]+" address)
235 (wl-match-string 1 address)
238 (defun wl-refile-guess-by-from (entity)
239 (let ((from (downcase (wl-address-header-extract-address
240 (elmo-message-entity-field entity 'from))))
241 (folder (elmo-make-folder wl-refile-default-from-folder))
242 (elmo-path-sep wl-refile-default-from-folder-path-separator))
244 (or (cdr (assoc from wl-refile-alist))
246 (elmo-folder-prefix-internal folder)
248 (substring wl-refile-default-from-folder
249 (length (elmo-folder-prefix-internal folder)))
250 (wl-refile-get-account-part-from-address from))))))
252 (defun wl-refile-guess-by-msgid (entity)
253 (cdr (assoc (elmo-message-entity-field entity 'references)
254 wl-refile-msgid-alist)))
256 (defun wl-refile-guess-by-subject (entity)
257 (cdr (assoc (funcall wl-summary-subject-filter-function
258 (elmo-message-entity-field entity 'subject 'decode))
259 wl-refile-subject-alist)))
262 (product-provide (provide 'wl-refile) (require 'wl-version))
264 ;;; wl-refile.el ends here