Mercurial > hg > xemacs-beta
diff lisp/vm/vm-pop.el @ 70:131b0175ea99 r20-0b30
Import from CVS: tag r20-0b30
author | cvs |
---|---|
date | Mon, 13 Aug 2007 09:02:59 +0200 |
parents | 05472e90ae02 |
children | 0d2f883870bc |
line wrap: on
line diff
--- a/lisp/vm/vm-pop.el Mon Aug 13 09:00:04 2007 +0200 +++ b/lisp/vm/vm-pop.el Mon Aug 13 09:02:59 2007 +0200 @@ -1,5 +1,5 @@ -;;; Simple POP (RFC 1939) client for VM -;;; Copyright (C) 1993, 1994, 1997 Kyle E. Jones +;;; Simple POP (RFC 1460) client for VM +;;; Copyright (C) 1993, 1994 Kyle E. Jones ;;; ;;; This program is free software; you can redistribute it and/or modify ;;; it under the terms of the GNU General Public License as published by @@ -24,129 +24,19 @@ (let ((process nil) (folder-type vm-folder-type) (saved-password t) - (m-per-session vm-pop-messages-per-session) - (b-per-session vm-pop-bytes-per-session) (handler (and (fboundp 'find-file-name-handler) (condition-case () (find-file-name-handler source 'vm-pop-move-mail) (wrong-number-of-arguments (find-file-name-handler source))))) (popdrop (vm-safe-popdrop-string source)) - (statblob nil) - mailbox-count mailbox-size message-size response - n retrieved retrieved-bytes process-buffer) + greeting timestamp n message-count + host port auth user pass source-list process-buffer) (unwind-protect (catch 'done (if handler (throw 'done (funcall handler 'vm-pop-move-mail source destination))) - (setq process (vm-pop-make-session source)) - (or process (throw 'done nil)) - (setq process-buffer (process-buffer process)) - (save-excursion - (set-buffer process-buffer) - (setq vm-folder-type (or folder-type vm-default-folder-type)) - ;; find out how many messages are in the box. - (vm-pop-send-command process "STAT") - (setq response (vm-pop-read-stat-response process) - mailbox-count (nth 0 response) - mailbox-size (nth 1 response)) - ;; forget it if the command fails - ;; or if there are no messages present. - (if (or (null mailbox-count) - (< mailbox-count 1)) - (throw 'done nil)) - ;; loop through the maildrop retrieving and deleting - ;; messages as we go. - (setq n 1 retrieved 0 retrieved-bytes 0) - (setq statblob (vm-pop-start-status-timer)) - (vm-set-pop-stat-x-box statblob popdrop) - (vm-set-pop-stat-x-maxmsg statblob mailbox-count) - (while (and (<= n mailbox-count) - (or (not (natnump m-per-session)) - (< retrieved m-per-session)) - (or (not (natnump b-per-session)) - (< retrieved-bytes b-per-session))) - (vm-set-pop-stat-x-currmsg statblob n) - (vm-pop-send-command process (format "LIST %d" n)) - (setq message-size (vm-pop-read-list-response process)) - (vm-set-pop-stat-x-need statblob message-size) - (if (and (integerp vm-pop-max-message-size) - (> message-size vm-pop-max-message-size) - (progn - (setq response - (if vm-pop-ok-to-ask - (vm-pop-ask-about-large-message process - message-size - n) - 'skip)) - (not (eq response 'retrieve)))) - (if (eq response 'delete) - (progn - (message "Deleting message %d..." n) - (vm-pop-send-command process (format "DELE %d" n)) - (and (null (vm-pop-read-response process)) - (throw 'done (not (equal retrieved 0))))) - (if vm-pop-ok-to-ask - (message "Skipping message %d..." n) - (message "Skipping message %d in %s, too large (%d > %d)..." - n popdrop message-size vm-pop-max-message-size))) - (message "Retrieving message %d (of %d) from %s..." - n mailbox-count popdrop) - (vm-pop-send-command process (format "RETR %d" n)) - (and (null (vm-pop-read-response process)) - (throw 'done (not (equal retrieved 0)))) - (and (null (vm-pop-retrieve-to-crashbox process destination - statblob)) - (throw 'done (not (equal retrieved 0)))) - (vm-increment retrieved) - (and b-per-session - (setq retrieved-bytes (+ retrieved-bytes message-size))) - (vm-pop-send-command process (format "DELE %d" n)) - ;; DELE can't fail but Emacs or this code might - ;; blow a gasket and spew filth down the - ;; connection, so... - (and (null (vm-pop-read-response process)) - (throw 'done (not (equal retrieved 0))))) - (vm-increment n)) - (not (equal retrieved 0)) )) - (and statblob (vm-pop-stop-status-timer statblob)) - (if process - (vm-pop-end-session process))))) - -(defun vm-pop-check-mail (source) - (let ((process nil) - (handler (and (fboundp 'find-file-name-handler) - (condition-case () - (find-file-name-handler source 'vm-pop-check-mail) - (wrong-number-of-arguments - (find-file-name-handler source))))) - response) - (unwind-protect - (save-excursion - (catch 'done - (if handler - (throw 'done - (funcall handler 'vm-pop-check-mail source))) - (setq process (vm-pop-make-session source)) - (or process (throw 'done nil)) - (set-buffer (process-buffer process)) - (vm-pop-send-command process "STAT") - (setq response (vm-pop-read-stat-response process)) - (if (null response) - nil - (not (equal 0 (car response)))))) - (and process (vm-pop-end-session process))))) - -(defun vm-pop-make-session (source) - (let ((process-to-shutdown nil) - process - (saved-password t) - (popdrop (vm-safe-popdrop-string source)) - greeting timestamp - host port auth user pass source-list process-buffer) - (unwind-protect - (catch 'done ;; parse the maildrop (setq source-list (vm-parse source "\\([^:]+\\):?") host (nth 0 source-list) @@ -177,39 +67,31 @@ (progn (setq pass (car (cdr (assoc source vm-pop-passwords)))) (if (null pass) - (if (null vm-pop-ok-to-ask) - (progn (message "Need password for %s" popdrop) - (throw 'done nil)) - (setq pass - (vm-read-password - (format "POP password for %s: " - popdrop)) - vm-pop-passwords (cons (list source pass) - vm-pop-passwords) - saved-password t))))) + (setq pass + (vm-read-password + (format "POP password for %s: " + popdrop)) + vm-pop-passwords (cons (list source pass) + vm-pop-passwords) + saved-password t)))) ;; get the trace buffer (setq process-buffer (get-buffer-create (format "trace of POP session to %s" host))) - ;; Tell XEmacs/MULE not to mess with the text. - (and vm-xemacs-mule-p - (set-buffer-file-coding-system 'binary t)) ;; clear the trace buffer of old output (save-excursion (set-buffer process-buffer) - (buffer-disable-undo) (erase-buffer)) ;; open the connection to the server (setq process (open-network-stream "POP" process-buffer host port)) (and (null process) (throw 'done nil)) - (process-kill-without-query process) + (set-process-filter process 'vm-pop-process-filter) (save-excursion (set-buffer process-buffer) (make-local-variable 'vm-pop-read-point) - (setq vm-pop-read-point (point-min)) - (if (null (setq greeting (vm-pop-read-response process t))) - (progn (delete-process process) - (throw 'done nil))) - (setq process-to-shutdown process) + (setq vm-pop-read-point (point-min) + vm-folder-type (or folder-type vm-default-folder-type)) + (and (null (setq greeting (vm-pop-read-response process t))) + (throw 'done nil)) ;; authentication (cond ((equal auth "pass") (vm-pop-send-command process (format "USER %s" user)) @@ -236,7 +118,7 @@ (if (null timestamp) (progn (goto-char (point-max)) - (insert-before-markers "<<< ooops, no timestamp found in greeting! >>>\n") + (insert "<<< ooops, no timestamp found in greeting! >>>\n") (throw 'done nil))) (vm-pop-send-command process @@ -245,88 +127,52 @@ (vm-pop-md5 (concat timestamp pass)))) (and (null (vm-pop-read-response process)) (throw 'done nil))) - (t (error "Don't know how to authenticate using %s" auth))) - (setq process-to-shutdown nil) - process )) - (if process-to-shutdown - (vm-pop-end-session process-to-shutdown))))) + (t (error "Don't know how to authenticate with %s" auth))) + ;; find out how many messages are in the box. + (vm-pop-send-command process "STAT") + (setq message-count (vm-pop-read-stat-response process)) + ;; forget it if the command fails + ;; or if there are no messages present. + (if (or (null message-count) + (< message-count 1)) + (throw 'done nil)) + ;; loop through the maildrop retrieving and deleting + ;; messages as we go. + (setq n 1) + (while (<= n message-count) + (vm-unsaved-message "Retrieving message %d (of %d) from %s..." + n message-count popdrop) + (vm-pop-send-command process (format "RETR %d" n)) + (and (null (vm-pop-read-response process)) + (throw 'done (not (equal n 1)))) + (and (null (vm-pop-retrieve-to-crashbox process destination)) + (throw 'done (not (equal n 1)))) + (vm-pop-send-command process (format "DELE %d" n)) + ;; DELE can't fail but Emacs or this code might + ;; blow a gasket and spew filth down the + ;; connection, so... + (and (null (vm-pop-read-response process)) + (throw 'done (not (equal n 1)))) + (vm-increment n)) + t )) + (if process + (save-excursion + (set-buffer (process-buffer process)) + (vm-pop-send-command process "QUIT") + (vm-pop-read-response process) + (delete-process process)))))) -(defun vm-pop-end-session (process) +(defun vm-pop-process-filter (process output) (save-excursion (set-buffer (process-buffer process)) - (vm-pop-send-command process "QUIT") - (vm-pop-read-response process) - (if (fboundp 'add-async-timeout) - (add-async-timeout 2 'delete-process process) - (run-at-time 2 nil 'delete-process process)))) - -(defun vm-pop-stat-timer (o) (aref o 0)) -(defun vm-pop-stat-x-box (o) (aref o 1)) -(defun vm-pop-stat-x-currmsg (o) (aref o 2)) -(defun vm-pop-stat-x-maxmsg (o) (aref o 3)) -(defun vm-pop-stat-x-got (o) (aref o 4)) -(defun vm-pop-stat-x-need (o) (aref o 5)) -(defun vm-pop-stat-y-box (o) (aref o 6)) -(defun vm-pop-stat-y-currmsg (o) (aref o 7)) -(defun vm-pop-stat-y-maxmsg (o) (aref o 8)) -(defun vm-pop-stat-y-got (o) (aref o 9)) -(defun vm-pop-stat-y-need (o) (aref o 10)) - -(defun vm-set-pop-stat-timer (o val) (aset o 0 val)) -(defun vm-set-pop-stat-x-box (o val) (aset o 1 val)) -(defun vm-set-pop-stat-x-currmsg (o val) (aset o 2 val)) -(defun vm-set-pop-stat-x-maxmsg (o val) (aset o 3 val)) -(defun vm-set-pop-stat-x-got (o val) (aset o 4 val)) -(defun vm-set-pop-stat-x-need (o val) (aset o 5 val)) -(defun vm-set-pop-stat-y-box (o val) (aset o 6 val)) -(defun vm-set-pop-stat-y-currmsg (o val) (aset o 7 val)) -(defun vm-set-pop-stat-y-maxmsg (o val) (aset o 8 val)) -(defun vm-set-pop-stat-y-got (o val) (aset o 9 val)) -(defun vm-set-pop-stat-y-need (o val) (aset o 10 val)) - -(defun vm-pop-start-status-timer () - (let ((blob (make-vector 11 nil)) - timer) - (setq timer (add-timeout 5 'vm-pop-report-retrieval-status blob 5)) - (vm-set-pop-stat-timer blob timer) - blob )) - -(defun vm-pop-stop-status-timer (status-blob) - (if (fboundp 'disable-timeout) - (disable-timeout (vm-pop-stat-timer status-blob)) - (cancel-timer (vm-pop-stat-timer status-blob)))) - -(defun vm-pop-report-retrieval-status (o) - (cond ((null (vm-pop-stat-x-got o)) t) - ;; should not be possible, but better safe... - ((not (eq (vm-pop-stat-x-box o) (vm-pop-stat-y-box o))) t) - ((not (eq (vm-pop-stat-x-currmsg o) (vm-pop-stat-y-currmsg o))) t) - (t (message "Retrieving message %d (of %d) from %s, %s..." - (vm-pop-stat-x-currmsg o) - (vm-pop-stat-x-maxmsg o) - (vm-pop-stat-x-box o) - (format "%d%s of %d%s" - (vm-pop-stat-x-got o) - (if (> (vm-pop-stat-x-got o) - (vm-pop-stat-x-need o)) - "!" - "") - (vm-pop-stat-x-need o) - (if (eq (vm-pop-stat-x-got o) - (vm-pop-stat-y-got o)) - " (stalled)" - ""))))) - (vm-set-pop-stat-y-box o (vm-pop-stat-x-box o)) - (vm-set-pop-stat-y-currmsg o (vm-pop-stat-x-currmsg o)) - (vm-set-pop-stat-y-maxmsg o (vm-pop-stat-x-maxmsg o)) - (vm-set-pop-stat-y-got o (vm-pop-stat-x-got o)) - (vm-set-pop-stat-y-need o (vm-pop-stat-x-need o))) + (goto-char (point-max)) + (insert output))) (defun vm-pop-send-command (process command) (goto-char (point-max)) (if (= (aref command 0) ?P) - (insert-before-markers "PASS <omitted>\r\n") - (insert-before-markers command "\r\n")) + (insert "PASS <omitted>\r\n") + (insert command "\r\n")) (setq vm-pop-read-point (point)) (process-send-string process command) (process-send-string process "\r\n")) @@ -347,83 +193,16 @@ (buffer-substring (point) match-end) t )))) -(defun vm-pop-read-past-dot-sentinel-line (process) - (let ((case-fold-search nil)) - (goto-char vm-pop-read-point) - (while (not (re-search-forward "^\\.\r\n" nil 0)) - (beginning-of-line) - ;; save-excursion doesn't work right - (let ((opoint (point))) - (accept-process-output process) - (goto-char opoint))) - (setq vm-pop-read-point (point)))) - (defun vm-pop-read-stat-response (process) - (let ((response (vm-pop-read-response process t)) - list) - (setq list (vm-parse response "\\([^ ]+\\) *")) - (list (string-to-int (nth 1 list)) (string-to-int (nth 2 list))))) - -(defun vm-pop-read-list-response (process) (let ((response (vm-pop-read-response process t))) - (string-to-int (nth 2 (vm-parse response "\\([^ ]+\\) *"))))) + (string-to-int (nth 1 (vm-parse response "\\([^ ]+\\) *"))))) -(defun vm-pop-ask-about-large-message (process size n) - (let ((work-buffer nil) - (pop-buffer (current-buffer)) - start end) - (unwind-protect - (save-excursion - (save-window-excursion - (vm-pop-send-command process (format "TOP %d %d" n 0)) - (if (vm-pop-read-response process) - (progn - (setq start vm-pop-read-point) - (vm-pop-read-past-dot-sentinel-line process) - (setq end vm-pop-read-point) - (setq work-buffer (generate-new-buffer "*pop-glop*")) - (set-buffer work-buffer) - (insert-buffer-substring pop-buffer start end) - (forward-line -1) - (delete-region (point) (point-max)) - (vm-pop-cleanup-region (point-min) (point-max)) - (vm-display-buffer work-buffer) - (setq minibuffer-scroll-window (selected-window)) - (goto-char (point-min)) - (if (re-search-forward "^Received:" nil t) - (progn - (goto-char (match-beginning 0)) - (vm-reorder-message-headers - nil vm-visible-headers - vm-invisible-header-regexp))) - (set-window-point (selected-window) (point)))) - (if (y-or-n-p (format "Message %d, size = %d, retrieve? " n size)) - 'retrieve - (if (y-or-n-p (format "Delete message %d from popdrop? " n size)) - 'delete - 'skip)))) - (and work-buffer (kill-buffer work-buffer))))) - -(defun vm-pop-retrieve-to-crashbox (process crash statblob) +(defun vm-pop-retrieve-to-crashbox (process crash) (let ((start vm-pop-read-point) end) (goto-char start) - (vm-set-pop-stat-x-got statblob 0) - (while (not (re-search-forward "^\\.\r\n" nil 0)) - (beginning-of-line) - ;; save-excursion doesn't work right - (let* ((opoint (point)) - (func - (function - (lambda (beg end len) - (if vm-pop-read-point - (progn - (vm-set-pop-stat-x-got statblob (- end start)) - (if (zerop (% (random) 10)) - (vm-pop-report-retrieval-status statblob))))))) - (after-change-functions (cons func after-change-functions))) - (accept-process-output process) - (goto-char opoint))) - (vm-set-pop-stat-x-got statblob nil) + (while (not (re-search-forward "^\\.\r\n" nil t)) + (accept-process-output process) + (goto-char start)) (setq vm-pop-read-point (point-marker)) (goto-char (match-beginning 0)) (setq end (point-marker)) @@ -456,19 +235,11 @@ (vm-convert-folder-type-headers nil vm-folder-type) (goto-char end) (insert-before-markers (vm-trailing-message-separator)))) - ;; Set file type to binary for DOS/Windows. I don't know if - ;; this is correct to do or not; it depends on whether the - ;; the CRLF or the LF newline convention is used on the inbox - ;; associated with this crashbox. This setting assumes the LF - ;; newline convention is used. - (let ((buffer-file-type t)) - (write-region start end crash t 0)) + (write-region start end crash t 0) (delete-region start end) t )) (defun vm-pop-cleanup-region (start end) - (if (> (- end start) 30000) - (message "CRLF conversion and char unstuffing...")) (setq end (vm-marker end)) (save-excursion (goto-char start) @@ -480,8 +251,6 @@ (while (and (< (point) end) (re-search-forward "^\\." end t)) (replace-match "" t t) (forward-char))) - (if (> (- end start) 30000) - (message "CRLF conversion and dot unstuffing... done")) (set-marker end nil)) (defun vm-pop-md5 (string) @@ -493,7 +262,7 @@ (insert string) (call-process-region (point-min) (point-max) "/bin/sh" t buffer nil - shell-command-switch vm-pop-md5-program) + "-c" vm-pop-md5-program) ;; MD5 digest is 32 chars long ;; mddriver adds a newline to make neaten output for tty ;; viewing, make sure we leave it behind.