(defstruct nnimap
group process commands capabilities select-result newlinep server
- last-command-time greeting examined)
+ last-command-time greeting examined stream-type)
(defvar nnimap-object nil)
login-result credentials)
(when nnimap-server-port
(setq ports (append ports (list nnimap-server-port))))
- (destructuring-bind (stream greeting capabilities)
+ (destructuring-bind (stream greeting capabilities stream-type)
(open-protocol-stream
"*nnimap*" (current-buffer) nnimap-address (car (last ports))
:type nnimap-stream
(when (gnus-string-match-p "STARTTLS" capabilities)
"1 STARTTLS\r\n")))
(setf (nnimap-process nnimap-object) stream)
+ (setf (nnimap-stream-type nnimap-object) stream-type)
(if (not stream)
(progn
(nnheader-report 'nnimap "Unable to contact %s:%s via %s"
(defun nnimap-login (user password)
(cond
+ ;; Prefer plain LOGIN if it's enabled (since it requires fewer
+ ;; round trips than CRAM-MD5, and it's less likely to be buggy),
+ ;; and we're using an encrypted connection.
+ ((and (not (nnimap-capability "LOGINDISABLED"))
+ (eq (nnimap-stream-type nnimap-object) 'tls))
+ (nnimap-command "LOGIN %S %S" user password))
((nnimap-capability "AUTH=CRAM-MD5")
(erase-buffer)
(let ((sequence (nnimap-send-command "AUTHENTICATE CRAM-MD5"))
(with-current-buffer (nnimap-buffer)
(when (stringp article)
(setq article (nnimap-find-article-by-message-id group article)))
- (nnimap-get-whole-article
- article (format "UID FETCH %%d %s"
- (nnimap-header-parameters)))
- (let ((buffer (current-buffer)))
- (with-current-buffer (or to-buffer nntp-server-buffer)
- (erase-buffer)
- (insert-buffer-substring buffer)
- (nnheader-ms-strip-cr)
- (cons group article))))))
+ (if (null article)
+ nil
+ (nnimap-get-whole-article
+ article (format "UID FETCH %%d %s"
+ (nnimap-header-parameters)))
+ (let ((buffer (current-buffer)))
+ (with-current-buffer (or to-buffer nntp-server-buffer)
+ (erase-buffer)
+ (insert-buffer-substring buffer)
+ (nnheader-ms-strip-cr)
+ (cons group article)))))))
(defun nnimap-get-whole-article (article &optional command)
(let ((result
(goto-char (point-max))
(while (and (setq openp (memq (process-status process)
'(open run)))
- (not (re-search-backward
- (format "^%d .*\n" sequence)
- (if nnimap-streaming
- (max (point-min)
- (min
- (- (point) 500)
- (save-excursion
- (forward-line -3)
- (point))))
- (point-min))
- t)))
+ (progn
+ ;; Skip past any "*" lines that the server has
+ ;; output.
+ (while (and (not (bobp))
+ (progn
+ (forward-line -1)
+ (looking-at "\\*"))))
+ (not (looking-at (format "%d " sequence)))))
(when messagep
(nnheader-message 7 "nnimap read %dk" (/ (buffer-size) 1000)))
(nnheader-accept-process-output process)