comparison lisp/vm/vm-pop.el @ 30:ec9a17fef872 r19-15b98

Import from CVS: tag r19-15b98
author cvs
date Mon, 13 Aug 2007 08:52:29 +0200
parents 441bb1e64a06
children 05472e90ae02
comparison
equal deleted inserted replaced
29:7976500f47f9 30:ec9a17fef872
1 ;;; Simple POP (RFC 1460) client for VM 1 ;;; Simple POP (RFC 1939) client for VM
2 ;;; Copyright (C) 1993, 1994 Kyle E. Jones 2 ;;; Copyright (C) 1993, 1994, 1997 Kyle E. Jones
3 ;;; 3 ;;;
4 ;;; This program is free software; you can redistribute it and/or modify 4 ;;; This program is free software; you can redistribute it and/or modify
5 ;;; it under the terms of the GNU General Public License as published by 5 ;;; it under the terms of the GNU General Public License as published by
6 ;;; the Free Software Foundation; either version 1, or (at your option) 6 ;;; the Free Software Foundation; either version 1, or (at your option)
7 ;;; any later version. 7 ;;; any later version.
30 (condition-case () 30 (condition-case ()
31 (find-file-name-handler source 'vm-pop-move-mail) 31 (find-file-name-handler source 'vm-pop-move-mail)
32 (wrong-number-of-arguments 32 (wrong-number-of-arguments
33 (find-file-name-handler source))))) 33 (find-file-name-handler source)))))
34 (popdrop (vm-safe-popdrop-string source)) 34 (popdrop (vm-safe-popdrop-string source))
35 (statblob nil)
35 mailbox-count mailbox-size message-size response 36 mailbox-count mailbox-size message-size response
36 n retrieved retrieved-bytes process-buffer) 37 n retrieved retrieved-bytes process-buffer)
37 (unwind-protect 38 (unwind-protect
38 (catch 'done 39 (catch 'done
39 (if handler 40 (if handler
56 (< mailbox-count 1)) 57 (< mailbox-count 1))
57 (throw 'done nil)) 58 (throw 'done nil))
58 ;; loop through the maildrop retrieving and deleting 59 ;; loop through the maildrop retrieving and deleting
59 ;; messages as we go. 60 ;; messages as we go.
60 (setq n 1 retrieved 0 retrieved-bytes 0) 61 (setq n 1 retrieved 0 retrieved-bytes 0)
62 (setq statblob (vm-pop-start-status-timer))
63 (vm-set-pop-stat-x-box statblob popdrop)
64 (vm-set-pop-stat-x-maxmsg statblob mailbox-count)
61 (while (and (<= n mailbox-count) 65 (while (and (<= n mailbox-count)
62 (or (not (natnump m-per-session)) 66 (or (not (natnump m-per-session))
63 (< retrieved m-per-session)) 67 (< retrieved m-per-session))
64 (or (not (natnump b-per-session)) 68 (or (not (natnump b-per-session))
65 (< retrieved-bytes b-per-session))) 69 (< retrieved-bytes b-per-session)))
66 (if (or vm-pop-max-message-size 70 (vm-set-pop-stat-x-currmsg statblob n)
67 b-per-session) 71 (vm-pop-send-command process (format "LIST %d" n))
68 (progn 72 (setq message-size (vm-pop-read-list-response process))
69 (vm-pop-send-command process (format "LIST %d" n)) 73 (vm-set-pop-stat-x-need statblob message-size)
70 (setq message-size
71 (vm-pop-read-list-response process))))
72 (if (and (integerp vm-pop-max-message-size) 74 (if (and (integerp vm-pop-max-message-size)
73 (> message-size vm-pop-max-message-size) 75 (> message-size vm-pop-max-message-size)
74 (progn 76 (progn
75 (setq response 77 (setq response
76 (if vm-pop-ok-to-ask 78 (if vm-pop-ok-to-ask
92 (message "Retrieving message %d (of %d) from %s..." 94 (message "Retrieving message %d (of %d) from %s..."
93 n mailbox-count popdrop) 95 n mailbox-count popdrop)
94 (vm-pop-send-command process (format "RETR %d" n)) 96 (vm-pop-send-command process (format "RETR %d" n))
95 (and (null (vm-pop-read-response process)) 97 (and (null (vm-pop-read-response process))
96 (throw 'done (not (equal retrieved 0)))) 98 (throw 'done (not (equal retrieved 0))))
97 (and (null (vm-pop-retrieve-to-crashbox process destination)) 99 (and (null (vm-pop-retrieve-to-crashbox process destination
100 statblob))
98 (throw 'done (not (equal retrieved 0)))) 101 (throw 'done (not (equal retrieved 0))))
99 (vm-increment retrieved) 102 (vm-increment retrieved)
100 (and b-per-session 103 (and b-per-session
101 (setq retrieved-bytes (+ retrieved-bytes message-size))) 104 (setq retrieved-bytes (+ retrieved-bytes message-size)))
102 (vm-pop-send-command process (format "DELE %d" n)) 105 (vm-pop-send-command process (format "DELE %d" n))
105 ;; connection, so... 108 ;; connection, so...
106 (and (null (vm-pop-read-response process)) 109 (and (null (vm-pop-read-response process))
107 (throw 'done (not (equal retrieved 0))))) 110 (throw 'done (not (equal retrieved 0)))))
108 (vm-increment n)) 111 (vm-increment n))
109 (not (equal retrieved 0)) )) 112 (not (equal retrieved 0)) ))
113 (and statblob (vm-pop-stop-status-timer statblob))
110 (if process 114 (if process
111 (vm-pop-end-session process))))) 115 (vm-pop-end-session process)))))
112 116
113 (defun vm-pop-check-mail (source) 117 (defun vm-pop-check-mail (source)
114 (let ((process nil) 118 (let ((process nil)
238 (format "APOP %s %s" 242 (format "APOP %s %s"
239 user 243 user
240 (vm-pop-md5 (concat timestamp pass)))) 244 (vm-pop-md5 (concat timestamp pass))))
241 (and (null (vm-pop-read-response process)) 245 (and (null (vm-pop-read-response process))
242 (throw 'done nil))) 246 (throw 'done nil)))
243 (t (error "Don't know how to authenticate with %s" auth))) 247 (t (error "Don't know how to authenticate using %s" auth)))
244 (setq process-to-shutdown nil) 248 (setq process-to-shutdown nil)
245 process )) 249 process ))
246 (if process-to-shutdown 250 (if process-to-shutdown
247 (vm-pop-end-session process-to-shutdown))))) 251 (vm-pop-end-session process-to-shutdown)))))
248 252
252 (vm-pop-send-command process "QUIT") 256 (vm-pop-send-command process "QUIT")
253 (vm-pop-read-response process) 257 (vm-pop-read-response process)
254 (if (fboundp 'add-async-timeout) 258 (if (fboundp 'add-async-timeout)
255 (add-async-timeout 2 'delete-process process) 259 (add-async-timeout 2 'delete-process process)
256 (run-at-time 2 nil 'delete-process process)))) 260 (run-at-time 2 nil 'delete-process process))))
261
262 (defun vm-pop-stat-timer (o) (aref o 0))
263 (defun vm-pop-stat-x-box (o) (aref o 1))
264 (defun vm-pop-stat-x-currmsg (o) (aref o 2))
265 (defun vm-pop-stat-x-maxmsg (o) (aref o 3))
266 (defun vm-pop-stat-x-got (o) (aref o 4))
267 (defun vm-pop-stat-x-need (o) (aref o 5))
268 (defun vm-pop-stat-y-box (o) (aref o 6))
269 (defun vm-pop-stat-y-currmsg (o) (aref o 7))
270 (defun vm-pop-stat-y-maxmsg (o) (aref o 8))
271 (defun vm-pop-stat-y-got (o) (aref o 9))
272 (defun vm-pop-stat-y-need (o) (aref o 10))
273
274 (defun vm-set-pop-stat-timer (o val) (aset o 0 val))
275 (defun vm-set-pop-stat-x-box (o val) (aset o 1 val))
276 (defun vm-set-pop-stat-x-currmsg (o val) (aset o 2 val))
277 (defun vm-set-pop-stat-x-maxmsg (o val) (aset o 3 val))
278 (defun vm-set-pop-stat-x-got (o val) (aset o 4 val))
279 (defun vm-set-pop-stat-x-need (o val) (aset o 5 val))
280 (defun vm-set-pop-stat-y-box (o val) (aset o 6 val))
281 (defun vm-set-pop-stat-y-currmsg (o val) (aset o 7 val))
282 (defun vm-set-pop-stat-y-maxmsg (o val) (aset o 8 val))
283 (defun vm-set-pop-stat-y-got (o val) (aset o 9 val))
284 (defun vm-set-pop-stat-y-need (o val) (aset o 10 val))
285
286 (defun vm-pop-start-status-timer ()
287 (let ((blob (make-vector 11 nil))
288 timer)
289 (setq timer (add-timeout 5 'vm-pop-report-retrieval-status blob 5))
290 (vm-set-pop-stat-timer blob timer)
291 blob ))
292
293 (defun vm-pop-stop-status-timer (status-blob)
294 (if (fboundp 'disable-timeout)
295 (disable-timeout (vm-pop-stat-timer status-blob))
296 (cancel-timer (vm-pop-stat-timer status-blob))))
297
298 (defun vm-pop-report-retrieval-status (o)
299 (cond ((null (vm-pop-stat-x-got o)) t)
300 ;; should not be possible, but better safe...
301 ((not (eq (vm-pop-stat-x-box o) (vm-pop-stat-y-box o))) t)
302 ((not (eq (vm-pop-stat-x-currmsg o) (vm-pop-stat-y-currmsg o))) t)
303 (t (message "Retrieving message %d (of %d) from %s, %s..."
304 (vm-pop-stat-x-currmsg o)
305 (vm-pop-stat-x-maxmsg o)
306 (vm-pop-stat-x-box o)
307 (format "%d%s of %d%s"
308 (vm-pop-stat-x-got o)
309 (if (> (vm-pop-stat-x-got o)
310 (vm-pop-stat-x-need o))
311 "!"
312 "")
313 (vm-pop-stat-x-need o)
314 (if (eq (vm-pop-stat-x-got o)
315 (vm-pop-stat-y-got o))
316 " (stalled)"
317 "")))))
318 (vm-set-pop-stat-y-box o (vm-pop-stat-x-box o))
319 (vm-set-pop-stat-y-currmsg o (vm-pop-stat-x-currmsg o))
320 (vm-set-pop-stat-y-maxmsg o (vm-pop-stat-x-maxmsg o))
321 (vm-set-pop-stat-y-got o (vm-pop-stat-x-got o))
322 (vm-set-pop-stat-y-need o (vm-pop-stat-x-need o)))
257 323
258 (defun vm-pop-send-command (process command) 324 (defun vm-pop-send-command (process command)
259 (goto-char (point-max)) 325 (goto-char (point-max))
260 (if (= (aref command 0) ?P) 326 (if (= (aref command 0) ?P)
261 (insert-before-markers "PASS <omitted>\r\n") 327 (insert-before-markers "PASS <omitted>\r\n")
281 t )))) 347 t ))))
282 348
283 (defun vm-pop-read-past-dot-sentinel-line (process) 349 (defun vm-pop-read-past-dot-sentinel-line (process)
284 (let ((case-fold-search nil)) 350 (let ((case-fold-search nil))
285 (goto-char vm-pop-read-point) 351 (goto-char vm-pop-read-point)
286 (while (not (search-forward "^.\r\n" nil 0)) 352 (while (not (re-search-forward "^\\.\r\n" nil 0))
287 (beginning-of-line) 353 (beginning-of-line)
288 ;; save-excursion doesn't work right 354 ;; save-excursion doesn't work right
289 (let ((opoint (point))) 355 (let ((opoint (point)))
290 (accept-process-output process) 356 (accept-process-output process)
291 (goto-char opoint))) 357 (goto-char opoint)))
335 (if (y-or-n-p (format "Delete message %d from popdrop? " n size)) 401 (if (y-or-n-p (format "Delete message %d from popdrop? " n size))
336 'delete 402 'delete
337 'skip)))) 403 'skip))))
338 (and work-buffer (kill-buffer work-buffer))))) 404 (and work-buffer (kill-buffer work-buffer)))))
339 405
340 (defun vm-pop-retrieve-to-crashbox (process crash) 406 (defun vm-pop-retrieve-to-crashbox (process crash statblob)
341 (let ((start vm-pop-read-point) end) 407 (let ((start vm-pop-read-point) end)
342 (goto-char start) 408 (goto-char start)
409 (vm-set-pop-stat-x-got statblob 0)
343 (while (not (re-search-forward "^\\.\r\n" nil 0)) 410 (while (not (re-search-forward "^\\.\r\n" nil 0))
344 (beginning-of-line) 411 (beginning-of-line)
345 ;; save-excursion doesn't work right 412 ;; save-excursion doesn't work right
346 (let ((opoint (point))) 413 (let* ((opoint (point))
414 (func
415 (function
416 (lambda (beg end len)
417 (if vm-pop-read-point
418 (progn
419 (vm-set-pop-stat-x-got statblob (- end start))
420 (if (zerop (% (random) 10))
421 (vm-pop-report-retrieval-status statblob)))))))
422 (after-change-functions (cons func after-change-functions)))
347 (accept-process-output process) 423 (accept-process-output process)
348 (goto-char opoint))) 424 (goto-char opoint)))
425 (vm-set-pop-stat-x-got statblob nil)
349 (setq vm-pop-read-point (point-marker)) 426 (setq vm-pop-read-point (point-marker))
350 (goto-char (match-beginning 0)) 427 (goto-char (match-beginning 0))
351 (setq end (point-marker)) 428 (setq end (point-marker))
352 (vm-pop-cleanup-region start end) 429 (vm-pop-cleanup-region start end)
353 ;; Some POP servers strip leading and trailing message 430 ;; Some POP servers strip leading and trailing message
387 (write-region start end crash t 0)) 464 (write-region start end crash t 0))
388 (delete-region start end) 465 (delete-region start end)
389 t )) 466 t ))
390 467
391 (defun vm-pop-cleanup-region (start end) 468 (defun vm-pop-cleanup-region (start end)
469 (if (> (- end start) 30000)
470 (message "CRLF conversion and char unstuffing..."))
392 (setq end (vm-marker end)) 471 (setq end (vm-marker end))
393 (save-excursion 472 (save-excursion
394 (goto-char start) 473 (goto-char start)
395 ;; CRLF -> LF 474 ;; CRLF -> LF
396 (while (and (< (point) end) (search-forward "\r\n" end t)) 475 (while (and (< (point) end) (search-forward "\r\n" end t))
398 (goto-char start) 477 (goto-char start)
399 ;; chop leading dots 478 ;; chop leading dots
400 (while (and (< (point) end) (re-search-forward "^\\." end t)) 479 (while (and (< (point) end) (re-search-forward "^\\." end t))
401 (replace-match "" t t) 480 (replace-match "" t t)
402 (forward-char))) 481 (forward-char)))
482 (if (> (- end start) 30000)
483 (message "CRLF conversion and dot unstuffing... done"))
403 (set-marker end nil)) 484 (set-marker end nil))
404 485
405 (defun vm-pop-md5 (string) 486 (defun vm-pop-md5 (string)
406 (let ((buffer nil)) 487 (let ((buffer nil))
407 (unwind-protect 488 (unwind-protect