Mercurial > emacs
comparison lisp/gnus/nnimap.el @ 111789:f97704487fb3
Merge changes made in Gnus trunk.
nnir.el: Batch header retrieval.
proto-stream.el: New library to provide protocol-specific TLS/STARTTLS connections for IMAP, NNTP, SMTP, POP3 and similar protocols.
nnimap.el (nnimap-open-connection): Use it.
proto-stream.el (open-proto-stream): Complete the documentation.
nnimap.el (nnimap-open-connection): Check for "OK" from the greeting.
nntp.el: Use proto-streams for the relevant connections types.
nntp.el (nntp-open-connection): Switch on STARTTLS on supported servers.
proto-stream.el (open-proto-stream): Add a way to specify what the end of a command is.
proto-stream.el (proto-stream-open-tls): Delete output from openssl if we're using tls.el.
proto-stream.el (proto-stream-open-network): If we don't have gnutls-cli or gnutls built in, then don't try to establish a STARTTLS connection.
color.el (color-lab->srgb): Fix function call name.
proto-stream.el: Fix the syntax in the comment.
nntp.el (nntp-open-connection): Fix the STARTTLS command syntax.
proto-stream.el (proto-stream-open-starttls): Actually implement the starttls.el STARTTLS.
proto-stream.el (proto-stream-always-use-starttls): New variable.
proto-stream.el (proto-stream-open-starttls): De-duplicate the starttls code.
proto-stream.el (proto-stream-open-starttls): Folded back into the main function.
proto-stream.el (proto-stream-command): Refactor out.
nnimap.el (nnimap-stream): Change default to `undecided'.
nnimap.el (nnimap-open-connection): If `nnimap-stream' is `undecided', try ssl first, and then network.
nnimap.el (nnimap-open-connection-1): Respect nnimap-server-port.
nnimap.el (nnimap-open-connection): Be more backwards-compatible.
proto-stream.el (open-protocol-stream): Renamed from open-proto-stream.
proto-stream.el (proto-stream-open-network): When doing opportunistic TLS upgrades we don't really care about the identity of the peer.
gnus.texi (Customizing the IMAP Connection): Note the new defaults.
gnus.texi (Direct Functions): Note the STARTTLS upgrade.
proto-stream.el (proto-stream-open-network): Force starttls.el to use gnutls-cli, since that what we've checked for.
proto-stream.el (proto-stream-always-use-starttls): Only default to t if open-gnutls-stream exists.
proto-stream.el (proto-stream-open-network): If STARTTLS failed, then just open a normal connection.
proto-stream.el (proto-stream-open-network): Wait until the greeting before doing STARTTLS.
nnimap.el (nnimap-open-connection-1): Always upgrade to STARTTLS (for backwards compatibility).
nnimap.el (nnimap-open-connection-1): Really respect nnimap-server-port.
nntp.el (nntp-open-connection): Provide a :success condition.
nnimap.el (nnimap-open-connection-1): Ditto.
proto-stream.el (proto-stream-open-network): See what the response to the STARTTLS command is.
proto-stream.el (proto-stream-open-network): Add some comments.
proto-stream.el: Fix example.
proto-stream.el (open-protocol-stream): Actually mention the STARTTLS upgrade.
nnir.el (nnir-get-active): Skip nnir-ignored-newsgroups when searching.
nnir.el (nnir-ignore-newsgroups): Fix default value.
nnir.el (nnir-run-gmane): Use mm-delete-duplicates instead of delete-dups that is not available in XEmacs 21.4.
mm-util.el (mm-delete-duplicates): Add comment.
gnus-sum.el (gnus-summary-delete-article): If delete fails don't change the registry.
nnimap.el (nnimap-open-connection-1): w32 open-network-stream doesn't seem to accept strings-with-numbers as port numbers.
color.el: fix docstring to use English rather than math notation for intervals.
shr.el (shr-find-fill-point): Don't break before apostrophes.
nnir.el (nnir-request-move-article): Bail out if no move support in group.
color.el (color-rgb->hsv): Fix docstring.
nnir.el (nnir-get-active): Improve active list retrieval.
shr.el (shr-find-fill-point): Work better for kinsoku chars and apostrophes.
gnus-gravatar.el (gnus-gravatar-size): Set gnus-gravatar-size to nil.
nnimap.el (nnimap-open-connection-1): Use gnus-string-match-p.
nnimap.el (nnimap-open-connection-1): Fix PREAUTH.
proto-stream.el (open-protocol-stream): All starttls connections are handled by the network handler.
gnus-gravatar.el (gnus-gravatar-insert): Delete unnecessary binding to t of inhibit-read-only since it is inside gnus-with-article-headers.
gnus-gravatar.el (gnus-gravatar-transform-address): Use mail-extract-address-components that supports non-ASCII names rather than mail-header-parse-addresses.
shr.el (shr-find-fill-point): Don't break line between kinsoku-bol characters.
gnus-gravatar.el (gnus-gravatar-insert): Allow LWSP in the middle of names.
nnmaildir.el (nnmaildir-request-set-mark): Add article to add-mark funcall.
gnus-msg.el: Remove nastygram thing.
message.el (message-from-style): Fix comment.
message.el (message-user-organization): Do not use gnus-local-organization.
gnus.el: Remove gnus-local-organization.
rtree.el: New file to handle range trees.
nnir.el, gnus-sum.el: Redo the way nnir handles registry updates.
rtree.el (rtree-extract): Simplify.
gnus-win.el (gnus-configure-windows): Remove Gnus 3.x setting support.
gnus-msg.el: Mark gnus-outgoing-message-group as obsolete.
gnus.texi (Archived Messages): Remove gnus-outgoing-message-group.
gnus-win.el (gnus-configure-frame): Remove old compatibility code.
rtree.el (rtree-memq): Rewrite it as a non-recursive function.
rtree.el (rtree-add, rtree-delq, rtree-length): Implement.
rtree.el (rtree-add): Make code slightly faster.
nnir.el: Allow modified summary-line-format in nnir summary buffers.
author | Katsumi Yamaoka <yamaoka@jpl.org> |
---|---|
date | Thu, 02 Dec 2010 22:21:31 +0000 |
parents | 8071f778f77e |
children | 79219ca01c7b |
comparison
equal
deleted
inserted
replaced
111788:8e746f396237 | 111789:f97704487fb3 |
---|---|
43 (require 'netrc) | 43 (require 'netrc) |
44 (require 'utf7) | 44 (require 'utf7) |
45 (require 'tls) | 45 (require 'tls) |
46 (require 'parse-time) | 46 (require 'parse-time) |
47 (require 'nnmail) | 47 (require 'nnmail) |
48 (require 'proto-stream) | |
48 | 49 |
49 (eval-when-compile | 50 (eval-when-compile |
50 (require 'gnus-sum)) | 51 (require 'gnus-sum)) |
51 | 52 |
52 (autoload 'auth-source-forget-user-or-password "auth-source") | 53 (autoload 'auth-source-forget-user-or-password "auth-source") |
60 (defvoo nnimap-server-port nil | 61 (defvoo nnimap-server-port nil |
61 "The IMAP port used. | 62 "The IMAP port used. |
62 If nnimap-stream is `ssl', this will default to `imaps'. If not, | 63 If nnimap-stream is `ssl', this will default to `imaps'. If not, |
63 it will default to `imap'.") | 64 it will default to `imap'.") |
64 | 65 |
65 (defvoo nnimap-stream 'ssl | 66 (defvoo nnimap-stream 'undecided |
66 "How nnimap will talk to the IMAP server. | 67 "How nnimap will talk to the IMAP server. |
67 Values are `ssl', `network', `starttls' or `shell'.") | 68 Values are `ssl', `network', `starttls' or `shell'. |
69 The default is to try `ssl' first, and then `network'.") | |
68 | 70 |
69 (defvoo nnimap-shell-program (if (boundp 'imap-shell-program) | 71 (defvoo nnimap-shell-program (if (boundp 'imap-shell-program) |
70 (if (listp imap-shell-program) | 72 (if (listp imap-shell-program) |
71 (car imap-shell-program) | 73 (car imap-shell-program) |
72 imap-shell-program) | 74 imap-shell-program) |
269 (make-nnimap :server (nnoo-current-server 'nnimap))) | 271 (make-nnimap :server (nnoo-current-server 'nnimap))) |
270 (push (list buffer (current-buffer)) nnimap-connection-alist) | 272 (push (list buffer (current-buffer)) nnimap-connection-alist) |
271 (push (current-buffer) nnimap-process-buffers) | 273 (push (current-buffer) nnimap-process-buffers) |
272 (current-buffer))) | 274 (current-buffer))) |
273 | 275 |
274 (defun nnimap-open-shell-stream (name buffer host port) | |
275 (let ((process-connection-type nil)) | |
276 (start-process name buffer shell-file-name | |
277 shell-command-switch | |
278 (format-spec | |
279 nnimap-shell-program | |
280 (format-spec-make | |
281 ?s host | |
282 ?p port))))) | |
283 | |
284 (defun nnimap-credentials (address ports &optional inhibit-create) | 276 (defun nnimap-credentials (address ports &optional inhibit-create) |
285 (let (port credentials) | 277 (let (port credentials) |
286 ;; Request the credentials from all ports, but only query on the | 278 ;; Request the credentials from all ports, but only query on the |
287 ;; last port if all the previous ones have failed. | 279 ;; last port if all the previous ones have failed. |
288 (while (and (null credentials) | 280 (while (and (null credentials) |
308 (nnimap-last-command-time nnimap-object))) | 300 (nnimap-last-command-time nnimap-object))) |
309 ;; More than five minutes since the last command. | 301 ;; More than five minutes since the last command. |
310 (* 5 60))) | 302 (* 5 60))) |
311 (nnimap-send-command "NOOP"))))))) | 303 (nnimap-send-command "NOOP"))))))) |
312 | 304 |
313 (declare-function gnutls-negotiate "gnutls" | |
314 (proc type &optional priority-string trustfiles keyfiles)) | |
315 | |
316 (defun nnimap-open-connection (buffer) | 305 (defun nnimap-open-connection (buffer) |
306 ;; Be backwards-compatible -- the earlier value of nnimap-stream was | |
307 ;; `ssl' when nnimap-server-port was nil. Sort of. | |
308 (when (and nnimap-server-port | |
309 (eq nnimap-stream 'undecided)) | |
310 (setq nnimap-stream 'ssl)) | |
311 (let ((stream | |
312 (if (eq nnimap-stream 'undecided) | |
313 (loop for type in '(ssl network) | |
314 for stream = (let ((nnimap-stream type)) | |
315 (nnimap-open-connection-1 buffer)) | |
316 while (eq stream 'no-connect) | |
317 finally (return stream)) | |
318 (nnimap-open-connection-1 buffer)))) | |
319 (if (eq stream 'no-connect) | |
320 nil | |
321 stream))) | |
322 | |
323 (defun nnimap-open-connection-1 (buffer) | |
317 (unless nnimap-keepalive-timer | 324 (unless nnimap-keepalive-timer |
318 (setq nnimap-keepalive-timer (run-at-time (* 60 15) (* 60 15) | 325 (setq nnimap-keepalive-timer (run-at-time (* 60 15) (* 60 15) |
319 'nnimap-keepalive))) | 326 'nnimap-keepalive))) |
320 (block nil | 327 (with-current-buffer (nnimap-make-process-buffer buffer) |
321 (with-current-buffer (nnimap-make-process-buffer buffer) | 328 (let* ((coding-system-for-read 'binary) |
322 (let* ((coding-system-for-read 'binary) | 329 (coding-system-for-write 'binary) |
323 (coding-system-for-write 'binary) | 330 (port nil) |
324 (port nil) | 331 (ports |
325 (ports | 332 (cond |
326 (cond | 333 ((or (eq nnimap-stream 'network) |
327 ((or (eq nnimap-stream 'network) | 334 (eq nnimap-stream 'starttls)) |
328 (and (eq nnimap-stream 'starttls) | 335 (nnheader-message 7 "Opening connection to %s..." |
329 (fboundp 'open-gnutls-stream))) | 336 nnimap-address) |
330 (nnheader-message 7 "Opening connection to %s..." | 337 '("143" "imap")) |
331 nnimap-address) | 338 ((eq nnimap-stream 'shell) |
332 (open-network-stream | 339 (nnheader-message 7 "Opening connection to %s via shell..." |
333 "*nnimap*" (current-buffer) nnimap-address | 340 nnimap-address) |
334 (setq port | 341 '("imap")) |
335 (or nnimap-server-port | 342 ((memq nnimap-stream '(ssl tls)) |
336 (if (netrc-find-service-number "imap") | 343 (nnheader-message 7 "Opening connection to %s via tls..." |
337 "imap" | 344 nnimap-address) |
338 "143")))) | 345 '("143" "993" "imap" "imaps")) |
339 '("143" "imap")) | 346 (t |
340 ((eq nnimap-stream 'shell) | 347 (error "Unknown stream type: %s" nnimap-stream)))) |
341 (nnheader-message 7 "Opening connection to %s via shell..." | 348 (proto-stream-always-use-starttls t) |
342 nnimap-address) | 349 login-result credentials) |
343 (nnimap-open-shell-stream | 350 (when nnimap-server-port |
344 "*nnimap*" (current-buffer) nnimap-address | 351 (setq ports (append ports (list nnimap-server-port)))) |
345 (setq port (or nnimap-server-port "imap"))) | 352 (destructuring-bind (stream greeting capabilities) |
346 '("imap")) | 353 (open-protocol-stream |
347 ((eq nnimap-stream 'starttls) | 354 "*nnimap*" (current-buffer) nnimap-address (car (last ports)) |
348 (nnheader-message 7 "Opening connection to %s via starttls..." | 355 :type nnimap-stream |
349 nnimap-address) | 356 :shell-command nnimap-shell-program |
350 (let ((tls-program | 357 :capability-command "1 CAPABILITY\r\n" |
351 '("openssl s_client -connect %h:%p -no_ssl2 -ign_eof -starttls imap"))) | 358 :success " OK " |
352 (open-tls-stream | 359 :starttls-function |
353 "*nnimap*" (current-buffer) nnimap-address | 360 (lambda (capabilities) |
354 (setq port (or nnimap-server-port "imap")))) | 361 (when (gnus-string-match-p "STARTTLS" capabilities) |
355 '("imap")) | 362 "1 STARTTLS\r\n"))) |
356 ((memq nnimap-stream '(ssl tls)) | 363 (setf (nnimap-process nnimap-object) stream) |
357 (nnheader-message 7 "Opening connection to %s via tls..." | 364 (if (not stream) |
358 nnimap-address) | 365 (progn |
359 (funcall (if (fboundp 'open-gnutls-stream) | 366 (nnheader-report 'nnimap "Unable to contact %s:%s via %s" |
360 'open-gnutls-stream | 367 nnimap-address port nnimap-stream) |
361 'open-tls-stream) | 368 'no-connect) |
362 "*nnimap*" (current-buffer) nnimap-address | 369 (gnus-set-process-query-on-exit-flag stream nil) |
363 (setq port | 370 (if (not (gnus-string-match-p "[*.] \\(OK\\|PREAUTH\\)" greeting)) |
364 (or nnimap-server-port | 371 (nnheader-report 'nnimap "%s" greeting) |
365 (if (netrc-find-service-number "imaps") | |
366 "imaps" | |
367 "993")))) | |
368 '("143" "993" "imap" "imaps")) | |
369 (t | |
370 (error "Unknown stream type: %s" nnimap-stream)))) | |
371 connection-result login-result credentials) | |
372 (setf (nnimap-process nnimap-object) | |
373 (get-buffer-process (current-buffer))) | |
374 (if (not (and (nnimap-process nnimap-object) | |
375 (memq (process-status (nnimap-process nnimap-object)) | |
376 '(open run)))) | |
377 (nnheader-report 'nnimap "Unable to contact %s:%s via %s" | |
378 nnimap-address port nnimap-stream) | |
379 (gnus-set-process-query-on-exit-flag | |
380 (nnimap-process nnimap-object) nil) | |
381 (if (not (setq connection-result (nnimap-wait-for-connection))) | |
382 (nnheader-report 'nnimap | |
383 "%s" (buffer-substring | |
384 (point) (line-end-position))) | |
385 ;; Store the greeting (for debugging purposes). | 372 ;; Store the greeting (for debugging purposes). |
386 (setf (nnimap-greeting nnimap-object) | 373 (setf (nnimap-greeting nnimap-object) greeting) |
387 (buffer-substring (line-beginning-position) | 374 (setf (nnimap-capabilities nnimap-object) |
388 (line-end-position))) | 375 (mapcar #'upcase |
389 (nnimap-get-capabilities) | 376 (split-string capabilities))) |
390 (when nnimap-server-port | 377 (unless (gnus-string-match-p "[*.] PREAUTH" greeting) |
391 (push (format "%s" nnimap-server-port) ports)) | |
392 ;; If this is a STARTTLS-capable server, then sever the | |
393 ;; connection and start a STARTTLS connection instead. | |
394 (cond | |
395 ((and (or (and (eq nnimap-stream 'network) | |
396 (nnimap-capability "STARTTLS")) | |
397 (eq nnimap-stream 'starttls)) | |
398 (fboundp 'open-gnutls-stream)) | |
399 (nnimap-command "STARTTLS") | |
400 (gnutls-negotiate (nnimap-process nnimap-object) nil) | |
401 ;; Get the capabilities again -- they may have changed | |
402 ;; after doing STARTTLS. | |
403 (nnimap-get-capabilities)) | |
404 ((and (eq nnimap-stream 'network) | |
405 (nnimap-capability "STARTTLS")) | |
406 (let ((nnimap-stream 'starttls)) | |
407 (let ((tls-process | |
408 (nnimap-open-connection buffer))) | |
409 ;; If the STARTTLS connection was successful, we | |
410 ;; kill our first non-encrypted connection. If it | |
411 ;; wasn't successful, we just use our unencrypted | |
412 ;; connection. | |
413 (when (memq (process-status tls-process) '(open run)) | |
414 (delete-process (nnimap-process nnimap-object)) | |
415 (kill-buffer (current-buffer)) | |
416 (return tls-process)))))) | |
417 (unless (equal connection-result "PREAUTH") | |
418 (if (not (setq credentials | 378 (if (not (setq credentials |
419 (if (eq nnimap-authenticator 'anonymous) | 379 (if (eq nnimap-authenticator 'anonymous) |
420 (list "anonymous" | 380 (list "anonymous" |
421 (message-make-address)) | 381 (message-make-address)) |
422 (or | 382 (or |
453 (setq nnimap-object nil)))) | 413 (setq nnimap-object nil)))) |
454 (when nnimap-object | 414 (when nnimap-object |
455 (when (nnimap-capability "QRESYNC") | 415 (when (nnimap-capability "QRESYNC") |
456 (nnimap-command "ENABLE QRESYNC")) | 416 (nnimap-command "ENABLE QRESYNC")) |
457 (nnimap-process nnimap-object)))))))) | 417 (nnimap-process nnimap-object)))))))) |
458 | |
459 (defun nnimap-get-capabilities () | |
460 (setf (nnimap-capabilities nnimap-object) | |
461 (mapcar | |
462 #'upcase | |
463 (nnimap-find-parameter | |
464 "CAPABILITY" (cdr (nnimap-command "CAPABILITY")))))) | |
465 | 418 |
466 (defun nnimap-quote-specials (string) | 419 (defun nnimap-quote-specials (string) |
467 (with-temp-buffer | 420 (with-temp-buffer |
468 (insert string) | 421 (insert string) |
469 (goto-char (point-min)) | 422 (goto-char (point-min)) |
1108 (setf (nnimap-examined nnimap-object) group) | 1061 (setf (nnimap-examined nnimap-object) group) |
1109 (if (and qresyncp | 1062 (if (and qresyncp |
1110 uidvalidity | 1063 uidvalidity |
1111 modseq) | 1064 modseq) |
1112 (push | 1065 (push |
1113 (list (nnimap-send-command "EXAMINE %S (QRESYNC (%s %s))" | 1066 (list (nnimap-send-command "EXAMINE %S (QRESYNC (%s %s))" |
1114 (utf7-encode group t) | 1067 (utf7-encode group t) |
1115 uidvalidity modseq) | 1068 uidvalidity modseq) |
1116 'qresync | 1069 'qresync |
1117 nil group 'qresync) | 1070 nil group 'qresync) |
1118 sequences) | 1071 sequences) |