- (save-excursion
- (set-buffer (process-buffer process))
- (goto-char (point-max))
- (insert output)))
-
-(defun elmo-pop3-open-connection (server user port auth passphrase ssl)
- (let ((process nil)
- (host server)
- process-buffer ret-val response capability)
- (catch 'done
- (as-binary-process
- (setq process-buffer
- (get-buffer-create (format " *POP session to %s:%d" host port)))
- (save-excursion
- (set-buffer process-buffer)
- (elmo-set-buffer-multibyte nil)
- (erase-buffer))
- (setq process
- (elmo-open-network-stream "POP" process-buffer host port ssl))
- (and (null process) (throw 'done nil))
- (set-process-filter process 'elmo-pop3-process-filter)
- ;; flush connections when exiting...
- (save-excursion
- (set-buffer process-buffer)
- (make-local-variable 'elmo-pop3-read-point)
- (setq elmo-pop3-read-point (point-min))
- (when (null (setq response
- (elmo-pop3-read-response process-buffer process t)))
- (setq ret-val (cons nil process))
- (throw 'done nil))
- (when (eq ssl 'starttls)
- (elmo-pop3-send-command process-buffer process "stls")
- (string-match "^\+OK"
- (elmo-pop3-read-response
- process-buffer process))
- (starttls-negotiate process))
- (cond ((string= auth "apop")
- ;; try only APOP
- (if (string-match "^\+OK .*\\(<[^\>]+>\\)" response)
- ;; good, APOP ready server
- (progn
- (require 'md5)
- (elmo-pop3-send-command
- process-buffer process
- (format "apop %s %s"
- user
- (md5
- (concat (match-string 1 response)
- passphrase)))))
- ;; otherwise, fail (only APOP authentication)
- (setq ret-val (cons nil process))
- (throw 'done nil)))
- ((string= auth "cram-md5")
- (elmo-pop3-send-command
- process-buffer process "auth cram-md5")
- (when (null (setq response
- (elmo-pop3-read-response
- process-buffer process t)))
- (setq ret-val (cons nil process))
- (throw 'done nil))
- (elmo-pop3-send-command
- process-buffer process
- (elmo-base64-encode-string
- (sasl-cram-md5 user passphrase
- (elmo-base64-decode-string
- (cadr (split-string response " ")))))))
- ((string= auth "digest-md5")
- (elmo-pop3-send-command
- process-buffer process "auth digest-md5")
- (when (null (setq response
- (elmo-pop3-read-response
- process-buffer process t)))
- (setq ret-val (cons nil process))
- (throw 'done nil))
- (elmo-pop3-send-command
- process-buffer process
- (elmo-base64-encode-string
- (sasl-digest-md5-digest-response
- (elmo-base64-decode-string
- (cadr (split-string response " ")))
- user passphrase "pop" host)
- 'no-line-break))
- (when (null (setq response
- (elmo-pop3-read-response
- process-buffer process t)))
- (setq ret-val (cons nil process))
- (throw 'done nil))
- (elmo-pop3-send-command process-buffer process ""))
- ((string= auth "scram-md5")
- (let (server-msg-1 server-msg-2 client-msg-1 client-msg-2
- salted-pass)
- (elmo-pop3-send-command
- process-buffer process
- (format "auth scram-md5 %s"
+ (when (buffer-live-p (process-buffer process))
+ (with-current-buffer (process-buffer process)
+ (goto-char (point-max))
+ (insert output)
+ (elmo-pop3-debug "RECEIVED: %s\n" output)
+ (if (and elmo-pop3-total-size
+ (> elmo-pop3-total-size
+ (min elmo-display-retrieval-progress-threshold 100)))
+ (elmo-display-progress
+ 'elmo-display-retrieval-progress
+ (format "Retrieving (%d/%d bytes)..."
+ (buffer-size)
+ elmo-pop3-total-size)
+ (/ (buffer-size) (/ elmo-pop3-total-size 100)))))))
+
+(defun elmo-pop3-auth-user (session)
+ (let ((process (elmo-network-session-process-internal session)))
+ ;; try USER/PASS
+ (elmo-pop3-send-command
+ process
+ (format "user %s" (elmo-network-session-user-internal session))
+ nil 'no-log)
+ (or (elmo-pop3-read-response process t)
+ (progn
+ (delete-process process)
+ (signal 'elmo-authenticate-error
+ '(elmo-pop-auth-user))))
+ (elmo-pop3-send-command process
+ (format
+ "pass %s"
+ (elmo-get-passwd
+ (elmo-network-session-password-key session)))
+ nil 'no-log)
+ (or (elmo-pop3-read-response process t)
+ (progn
+ (delete-process process)
+ (signal 'elmo-authenticate-error
+ '(elmo-pop-auth-user))))))
+
+(defun elmo-pop3-auth-apop (session)
+ (if (string-match "^\+OK .*\\(<[^\>]+>\\)"
+ (elmo-network-session-greeting-internal session))
+ ;; good, APOP ready server
+ (progn
+ (elmo-pop3-send-command
+ (elmo-network-session-process-internal session)
+ (format "apop %s %s"
+ (elmo-network-session-user-internal session)
+ (md5
+ (concat (match-string
+ 1
+ (elmo-network-session-greeting-internal session))
+ (elmo-get-passwd
+ (elmo-network-session-password-key session)))))
+ nil 'no-log)
+ (or (elmo-pop3-read-response
+ (elmo-network-session-process-internal session)
+ t)
+ (progn
+ (delete-process (elmo-network-session-process-internal session))
+ (signal 'elmo-authenticate-error
+ '(elmo-pop3-auth-apop)))))
+ (signal 'elmo-open-error '(elmo-pop3-auth-apop))))
+
+(luna-define-method elmo-network-initialize-session-buffer :after
+ ((session elmo-pop3-session) buffer)
+ (with-current-buffer buffer
+ (mapcar 'make-variable-buffer-local elmo-pop3-local-variables)))
+
+(luna-define-method elmo-network-initialize-session ((session
+ elmo-pop3-session))
+ (let ((process (elmo-network-session-process-internal session))
+ response mechanism)
+ (with-current-buffer (process-buffer process)
+ (set-process-filter process 'elmo-pop3-process-filter)
+ (setq elmo-pop3-read-point (point-min))
+ ;; Skip garbage output from process before greeting.
+ (while (and (memq (process-status process) '(open run))
+ (goto-char (point-max))
+ (forward-line -1)
+ (not (looking-at "+OK")))
+ (accept-process-output process 1))
+ (setq elmo-pop3-read-point (point))
+ (or (elmo-network-session-set-greeting-internal
+ session
+ (elmo-pop3-read-response process t))
+ (signal 'elmo-open-error
+ '(elmo-network-intialize-session)))
+ (when (eq (elmo-network-stream-type-symbol
+ (elmo-network-session-stream-type-internal session))
+ 'starttls)
+ (elmo-pop3-send-command process "stls")
+ (if (string-match "^\+OK"
+ (elmo-pop3-read-response process))
+ (starttls-negotiate process)
+ (signal 'elmo-open-error
+ '(elmo-pop3-starttls-error)))))))
+
+(luna-define-method elmo-network-authenticate-session ((session
+ elmo-pop3-session))
+ (with-current-buffer (process-buffer
+ (elmo-network-session-process-internal session))
+ (let* ((process (elmo-network-session-process-internal session))
+ (auth (elmo-network-session-auth-internal session))
+ (auth (mapcar '(lambda (mechanism) (upcase (symbol-name mechanism)))
+ (if (listp auth) auth (list auth))))
+ sasl-mechanisms
+ client name step response mechanism
+ sasl-read-passphrase)
+ (or (and (string= "USER" (car auth))
+ (elmo-pop3-auth-user session))
+ (and (string= "APOP" (car auth))
+ (elmo-pop3-auth-apop session))
+ (progn
+ (require 'sasl)
+ (setq sasl-mechanisms (mapcar 'car sasl-mechanism-alist))
+ (setq mechanism (sasl-find-mechanism auth))
+ (unless mechanism
+ (signal 'elmo-authenticate-error '(elmo-pop3-auth-no-mechanisms)))
+ (setq client
+ (sasl-make-client
+ mechanism
+ (elmo-network-session-user-internal session)
+ "pop"
+ (elmo-network-session-server-internal session)))
+;;; (if elmo-pop3-auth-user-realm
+;;; (sasl-client-set-property client 'realm elmo-pop3-auth-user-realm))
+ (setq name (sasl-mechanism-name mechanism))
+ (elmo-network-session-set-auth-internal session
+ (intern (downcase name)))
+ (setq sasl-read-passphrase
+ (function
+ (lambda (prompt)
+ (elmo-get-passwd
+ (elmo-network-session-password-key session)))))
+ (setq step (sasl-next-step client nil))
+ (elmo-pop3-send-command
+ process
+ (concat "AUTH " name
+ (and (sasl-step-data step)
+ (concat
+ " "