comparison lisp/vm/vm-pop.el @ 100:4be1180a9e89 r20-1b2

Import from CVS: tag r20-1b2
author cvs
date Mon, 13 Aug 2007 09:15:11 +0200
parents 0d2f883870bc
children a145efe76779
comparison
equal deleted inserted replaced
99:2d83cbd90d8d 100:4be1180a9e89
22 ;; just as if we were using movemail on a spool file. 22 ;; just as if we were using movemail on a spool file.
23 (defun vm-pop-move-mail (source destination) 23 (defun vm-pop-move-mail (source destination)
24 (let ((process nil) 24 (let ((process nil)
25 (folder-type vm-folder-type) 25 (folder-type vm-folder-type)
26 (saved-password t) 26 (saved-password t)
27 (m-per-session vm-pop-messages-per-session)
28 (b-per-session vm-pop-bytes-per-session)
27 (handler (and (fboundp 'find-file-name-handler) 29 (handler (and (fboundp 'find-file-name-handler)
28 (condition-case () 30 (condition-case ()
29 (find-file-name-handler source 'vm-pop-move-mail) 31 (find-file-name-handler source 'vm-pop-move-mail)
30 (wrong-number-of-arguments 32 (wrong-number-of-arguments
31 (find-file-name-handler source))))) 33 (find-file-name-handler source)))))
32 (popdrop (vm-safe-popdrop-string source)) 34 (popdrop (vm-safe-popdrop-string source))
33 greeting timestamp n message-count 35 mailbox-count mailbox-size message-size response
34 host port auth user pass source-list process-buffer) 36 n retrieved retrieved-bytes process-buffer)
35 (unwind-protect 37 (unwind-protect
36 (catch 'done 38 (catch 'done
37 (if handler 39 (if handler
38 (throw 'done 40 (throw 'done
39 (funcall handler 'vm-pop-move-mail source destination))) 41 (funcall handler 'vm-pop-move-mail source destination)))
42 (setq process (vm-pop-make-session source))
43 (or process (throw 'done nil))
44 (setq process-buffer (process-buffer process))
45 (save-excursion
46 (set-buffer process-buffer)
47 (setq vm-folder-type (or folder-type vm-default-folder-type))
48 ;; find out how many messages are in the box.
49 (vm-pop-send-command process "STAT")
50 (setq response (vm-pop-read-stat-response process)
51 mailbox-count (nth 0 response)
52 mailbox-size (nth 1 response))
53 ;; forget it if the command fails
54 ;; or if there are no messages present.
55 (if (or (null mailbox-count)
56 (< mailbox-count 1))
57 (throw 'done nil))
58 ;; loop through the maildrop retrieving and deleting
59 ;; messages as we go.
60 (setq n 1 retrieved 0 retrieved-bytes 0)
61 (while (and (<= n mailbox-count)
62 (or (not (natnump m-per-session))
63 (< retrieved m-per-session))
64 (or (not (natnump b-per-session))
65 (< retrieved-bytes b-per-session)))
66 (if (or vm-pop-max-message-size
67 b-per-session)
68 (progn
69 (vm-pop-send-command process (format "LIST %d" n))
70 (setq message-size
71 (vm-pop-read-list-response process))))
72 (if (and (integerp vm-pop-max-message-size)
73 (> message-size vm-pop-max-message-size)
74 (progn
75 (setq response
76 (if vm-pop-ok-to-ask
77 (vm-pop-ask-about-large-message process
78 message-size
79 n)
80 'skip))
81 (not (eq response 'retrieve))))
82 (if (eq response 'delete)
83 (progn
84 (message "Deleting message %d..." n)
85 (vm-pop-send-command process (format "DELE %d" n))
86 (and (null (vm-pop-read-response process))
87 (throw 'done (not (equal retrieved 0)))))
88 (if vm-pop-ok-to-ask
89 (message "Skipping message %d..." n)
90 (message "Skipping message %d in %s, too large (%d > %d)..."
91 n popdrop message-size vm-pop-max-message-size)))
92 (message "Retrieving message %d (of %d) from %s..."
93 n mailbox-count popdrop)
94 (vm-pop-send-command process (format "RETR %d" n))
95 (and (null (vm-pop-read-response process))
96 (throw 'done (not (equal retrieved 0))))
97 (and (null (vm-pop-retrieve-to-crashbox process destination))
98 (throw 'done (not (equal retrieved 0))))
99 (vm-increment retrieved)
100 (and b-per-session
101 (setq retrieved-bytes (+ retrieved-bytes message-size)))
102 (vm-pop-send-command process (format "DELE %d" n))
103 ;; DELE can't fail but Emacs or this code might
104 ;; blow a gasket and spew filth down the
105 ;; connection, so...
106 (and (null (vm-pop-read-response process))
107 (throw 'done (not (equal retrieved 0)))))
108 (vm-increment n))
109 (not (equal retrieved 0)) ))
110 (if process
111 (vm-pop-end-session process)))))
112
113 (defun vm-pop-check-mail (source)
114 (let ((process nil)
115 (handler (and (fboundp 'find-file-name-handler)
116 (condition-case ()
117 (find-file-name-handler source 'vm-pop-check-mail)
118 (wrong-number-of-arguments
119 (find-file-name-handler source)))))
120 response)
121 (unwind-protect
122 (save-excursion
123 (catch 'done
124 (if handler
125 (throw 'done
126 (funcall handler 'vm-pop-check-mail source)))
127 (setq process (vm-pop-make-session source))
128 (or process (throw 'done nil))
129 (set-buffer (process-buffer process))
130 (vm-pop-send-command process "STAT")
131 (setq response (vm-pop-read-stat-response process))
132 (if (null response)
133 nil
134 (not (equal 0 (car response))))))
135 (and process (vm-pop-end-session process)))))
136
137 (defun vm-pop-make-session (source)
138 (let ((process-to-shutdown nil)
139 process
140 (saved-password t)
141 (popdrop (vm-safe-popdrop-string source))
142 greeting timestamp
143 host port auth user pass source-list process-buffer)
144 (unwind-protect
145 (catch 'done
40 ;; parse the maildrop 146 ;; parse the maildrop
41 (setq source-list (vm-parse source "\\([^:]+\\):?") 147 (setq source-list (vm-parse source "\\([^:]+\\):?")
42 host (nth 0 source-list) 148 host (nth 0 source-list)
43 port (nth 1 source-list) 149 port (nth 1 source-list)
44 auth (nth 2 source-list) 150 auth (nth 2 source-list)
65 source)) 171 source))
66 (if (equal pass "*") 172 (if (equal pass "*")
67 (progn 173 (progn
68 (setq pass (car (cdr (assoc source vm-pop-passwords)))) 174 (setq pass (car (cdr (assoc source vm-pop-passwords))))
69 (if (null pass) 175 (if (null pass)
70 (setq pass 176 (if (null vm-pop-ok-to-ask)
71 (vm-read-password 177 (progn (message "Need password for %s" popdrop)
72 (format "POP password for %s: " 178 (throw 'done nil))
73 popdrop)) 179 (setq pass
74 vm-pop-passwords (cons (list source pass) 180 (vm-read-password
75 vm-pop-passwords) 181 (format "POP password for %s: "
76 saved-password t)))) 182 popdrop))
183 vm-pop-passwords (cons (list source pass)
184 vm-pop-passwords)
185 saved-password t)))))
77 ;; get the trace buffer 186 ;; get the trace buffer
78 (setq process-buffer 187 (setq process-buffer
79 (get-buffer-create (format "trace of POP session to %s" host))) 188 (get-buffer-create (format "trace of POP session to %s" host)))
189 ;; Tell XEmacs/MULE not to mess with the text.
190 (and (fboundp 'set-file-coding-system)
191 (set-file-coding-system 'binary t))
80 ;; clear the trace buffer of old output 192 ;; clear the trace buffer of old output
81 (save-excursion 193 (save-excursion
82 (set-buffer process-buffer) 194 (set-buffer process-buffer)
83 (erase-buffer)) 195 (erase-buffer))
84 ;; open the connection to the server 196 ;; open the connection to the server
85 (setq process (open-network-stream "POP" process-buffer host port)) 197 (setq process (open-network-stream "POP" process-buffer host port))
86 (and (null process) (throw 'done nil)) 198 (and (null process) (throw 'done nil))
87 (set-process-filter process 'vm-pop-process-filter) 199 (process-kill-without-query process)
88 (save-excursion 200 (save-excursion
89 (set-buffer process-buffer) 201 (set-buffer process-buffer)
90 (make-local-variable 'vm-pop-read-point) 202 (make-local-variable 'vm-pop-read-point)
91 (setq vm-pop-read-point (point-min) 203 (setq vm-pop-read-point (point-min))
92 vm-folder-type (or folder-type vm-default-folder-type)) 204 (if (null (setq greeting (vm-pop-read-response process t)))
93 (and (null (setq greeting (vm-pop-read-response process t))) 205 (progn (delete-process process)
94 (throw 'done nil)) 206 (throw 'done nil)))
207 (setq process-to-shutdown process)
95 ;; authentication 208 ;; authentication
96 (cond ((equal auth "pass") 209 (cond ((equal auth "pass")
97 (vm-pop-send-command process (format "USER %s" user)) 210 (vm-pop-send-command process (format "USER %s" user))
98 (and (null (vm-pop-read-response process)) 211 (and (null (vm-pop-read-response process))
99 (throw 'done nil)) 212 (throw 'done nil))
116 (setq timestamp (vm-parse greeting "[^<]+\\(<[^>]+>\\)") 229 (setq timestamp (vm-parse greeting "[^<]+\\(<[^>]+>\\)")
117 timestamp (car timestamp)) 230 timestamp (car timestamp))
118 (if (null timestamp) 231 (if (null timestamp)
119 (progn 232 (progn
120 (goto-char (point-max)) 233 (goto-char (point-max))
121 (insert "<<< ooops, no timestamp found in greeting! >>>\n") 234 (insert-before-markers "<<< ooops, no timestamp found in greeting! >>>\n")
122 (throw 'done nil))) 235 (throw 'done nil)))
123 (vm-pop-send-command 236 (vm-pop-send-command
124 process 237 process
125 (format "APOP %s %s" 238 (format "APOP %s %s"
126 user 239 user
127 (vm-pop-md5 (concat timestamp pass)))) 240 (vm-pop-md5 (concat timestamp pass))))
128 (and (null (vm-pop-read-response process)) 241 (and (null (vm-pop-read-response process))
129 (throw 'done nil))) 242 (throw 'done nil)))
130 (t (error "Don't know how to authenticate with %s" auth))) 243 (t (error "Don't know how to authenticate with %s" auth)))
131 ;; find out how many messages are in the box. 244 (setq process-to-shutdown nil)
132 (vm-pop-send-command process "STAT") 245 process ))
133 (setq message-count (vm-pop-read-stat-response process)) 246 (if process-to-shutdown
134 ;; forget it if the command fails 247 (vm-pop-end-session process-to-shutdown)))))
135 ;; or if there are no messages present. 248
136 (if (or (null message-count) 249 (defun vm-pop-end-session (process)
137 (< message-count 1))
138 (throw 'done nil))
139 ;; loop through the maildrop retrieving and deleting
140 ;; messages as we go.
141 (setq n 1)
142 (while (<= n message-count)
143 (vm-unsaved-message "Retrieving message %d (of %d) from %s..."
144 n message-count popdrop)
145 (vm-pop-send-command process (format "RETR %d" n))
146 (and (null (vm-pop-read-response process))
147 (throw 'done (not (equal n 1))))
148 (and (null (vm-pop-retrieve-to-crashbox process destination))
149 (throw 'done (not (equal n 1))))
150 (vm-pop-send-command process (format "DELE %d" n))
151 ;; DELE can't fail but Emacs or this code might
152 ;; blow a gasket and spew filth down the
153 ;; connection, so...
154 (and (null (vm-pop-read-response process))
155 (throw 'done (not (equal n 1))))
156 (vm-increment n))
157 t ))
158 (if process
159 (save-excursion
160 (set-buffer (process-buffer process))
161 (vm-pop-send-command process "QUIT")
162 (vm-pop-read-response process)
163 (delete-process process))))))
164
165 (defun vm-pop-process-filter (process output)
166 (save-excursion 250 (save-excursion
167 (set-buffer (process-buffer process)) 251 (set-buffer (process-buffer process))
168 (goto-char (point-max)) 252 (vm-pop-send-command process "QUIT")
169 (insert output))) 253 (vm-pop-read-response process)
254 (if (fboundp 'add-async-timeout)
255 (add-async-timeout 2 'delete-process process)
256 (run-at-time 2 nil 'delete-process process))))
170 257
171 (defun vm-pop-send-command (process command) 258 (defun vm-pop-send-command (process command)
172 (goto-char (point-max)) 259 (goto-char (point-max))
173 (if (= (aref command 0) ?P) 260 (if (= (aref command 0) ?P)
174 (insert "PASS <omitted>\r\n") 261 (insert-before-markers "PASS <omitted>\r\n")
175 (insert command "\r\n")) 262 (insert-before-markers command "\r\n"))
176 (setq vm-pop-read-point (point)) 263 (setq vm-pop-read-point (point))
177 (process-send-string process command) 264 (process-send-string process command)
178 (process-send-string process "\r\n")) 265 (process-send-string process "\r\n"))
179 266
180 (defun vm-pop-read-response (process &optional return-response-string) 267 (defun vm-pop-read-response (process &optional return-response-string)
191 (setq vm-pop-read-point match-end) 278 (setq vm-pop-read-point match-end)
192 (if return-response-string 279 (if return-response-string
193 (buffer-substring (point) match-end) 280 (buffer-substring (point) match-end)
194 t )))) 281 t ))))
195 282
283 (defun vm-pop-read-past-dot-sentinel-line (process)
284 (let ((case-fold-search nil))
285 (goto-char vm-pop-read-point)
286 (while (not (search-forward "^.\r\n" nil 0))
287 (beginning-of-line)
288 ;; save-excursion doesn't work right
289 (let ((opoint (point)))
290 (accept-process-output process)
291 (goto-char opoint)))
292 (setq vm-pop-read-point (point))))
293
196 (defun vm-pop-read-stat-response (process) 294 (defun vm-pop-read-stat-response (process)
295 (let ((response (vm-pop-read-response process t))
296 list)
297 (setq list (vm-parse response "\\([^ ]+\\) *"))
298 (list (string-to-int (nth 1 list)) (string-to-int (nth 2 list)))))
299
300 (defun vm-pop-read-list-response (process)
197 (let ((response (vm-pop-read-response process t))) 301 (let ((response (vm-pop-read-response process t)))
198 (string-to-int (nth 1 (vm-parse response "\\([^ ]+\\) *"))))) 302 (string-to-int (nth 2 (vm-parse response "\\([^ ]+\\) *")))))
303
304 (defun vm-pop-ask-about-large-message (process size n)
305 (let ((work-buffer nil)
306 (pop-buffer (current-buffer))
307 start end)
308 (unwind-protect
309 (save-excursion
310 (save-window-excursion
311 (vm-pop-send-command process (format "TOP %d %d" n 0))
312 (if (vm-pop-read-response process)
313 (progn
314 (setq start vm-pop-read-point)
315 (vm-pop-read-past-dot-sentinel-line process)
316 (setq end vm-pop-read-point)
317 (setq work-buffer (generate-new-buffer "*pop-glop*"))
318 (set-buffer work-buffer)
319 (insert-buffer-substring pop-buffer start end)
320 (forward-line -1)
321 (delete-region (point) (point-max))
322 (vm-pop-cleanup-region (point-min) (point-max))
323 (vm-display-buffer work-buffer)
324 (setq minibuffer-scroll-window (selected-window))
325 (goto-char (point-min))
326 (if (re-search-forward "^Received:" nil t)
327 (progn
328 (goto-char (match-beginning 0))
329 (vm-reorder-message-headers
330 nil vm-visible-headers
331 vm-invisible-header-regexp)))
332 (set-window-point (selected-window) (point))))
333 (if (y-or-n-p (format "Message %d, size = %d, retrieve? " n size))
334 'retrieve
335 (if (y-or-n-p (format "Delete message %d from popdrop? " n size))
336 'delete
337 'skip))))
338 (and work-buffer (kill-buffer work-buffer)))))
199 339
200 (defun vm-pop-retrieve-to-crashbox (process crash) 340 (defun vm-pop-retrieve-to-crashbox (process crash)
201 (let ((start vm-pop-read-point) end) 341 (let ((start vm-pop-read-point) end)
202 (goto-char start) 342 (goto-char start)
203 (while (not (re-search-forward "^\\.\r\n" nil t)) 343 (while (not (re-search-forward "^\\.\r\n" nil 0))
204 (accept-process-output process) 344 (beginning-of-line)
205 (goto-char start)) 345 ;; save-excursion doesn't work right
346 (let ((opoint (point)))
347 (accept-process-output process)
348 (goto-char opoint)))
206 (setq vm-pop-read-point (point-marker)) 349 (setq vm-pop-read-point (point-marker))
207 (goto-char (match-beginning 0)) 350 (goto-char (match-beginning 0))
208 (setq end (point-marker)) 351 (setq end (point-marker))
209 (vm-pop-cleanup-region start end) 352 (vm-pop-cleanup-region start end)
210 ;; Some POP servers strip leading and trailing message 353 ;; Some POP servers strip leading and trailing message