Mercurial > emacs
comparison lisp/gnus/imap.el @ 32995:3720ccaca161
2000-10-27 Simon Josefsson <simon@josefsson.org>
* nnimap.el (nnimap-group-overview-filename): Create directory for
newfile (when use long filenames is nil). Copy+delete file if
rename didn't work.
(nnimap-group-overview-filename): `rename-file' and `copy-file'
doesn't return anything useful, use ignore-errors instead.
(nnimap-verify-uidvalidity): Delete overview file when
uid validity changes.
(nnimap-group-overview-filename): Store uidvalidity in filenames.
Rename old files into new format.
(nnimap-request-accept-article): Remove \n's from
From_ lines.
(nnimap-request-accept-article): Remove From[^:] lines.
(imap-starttls-p): Check for starttls binary.
(imap-starttls-open): More verbose.
(imap-gssapi-auth): Ditto.
(imap-kerberos4-auth): Ditto.
(imap-cram-md5-auth): Ditto.
(imap-login-auth): Ditto.
(imap-anonymous-auth): Ditto.
(imap-digest-md5-auth): Ditto.
(imap-open): Ditto.
(imap-digest-md5-p): Check capability first.
(imap-parse-flag-list): Correctly parse empty lists.
(imap-login-p): Support LOGINDISABLED.
(imap-parse-body): Work around bug in Sun SIMS.
author | Dave Love <fx@gnu.org> |
---|---|
date | Fri, 27 Oct 2000 23:20:38 +0000 |
parents | 6b20b7e85e3c |
children | be95f43e08db |
comparison
equal
deleted
inserted
replaced
32994:aa53b96ab835 | 32995:3720ccaca161 |
---|---|
73 ;; explanatory for someone that know IMAP. All functions have | 73 ;; explanatory for someone that know IMAP. All functions have |
74 ;; additional documentation on how to invoke them. | 74 ;; additional documentation on how to invoke them. |
75 ;; | 75 ;; |
76 ;; imap.el support RFC1730/2060 (IMAP4/IMAP4rev1), implemented IMAP | 76 ;; imap.el support RFC1730/2060 (IMAP4/IMAP4rev1), implemented IMAP |
77 ;; extensions are RFC2195 (CRAM-MD5), RFC2086 (ACL), RFC2342 | 77 ;; extensions are RFC2195 (CRAM-MD5), RFC2086 (ACL), RFC2342 |
78 ;; (NAMESPACE), RFC2359 (UIDPLUS), the IMAP-part of RFC2595 (STARTTLS) | 78 ;; (NAMESPACE), RFC2359 (UIDPLUS), the IMAP-part of RFC2595 (STARTTLS, |
79 ;; (with use of external library starttls.el and program starttls) and | 79 ;; LOGINDISABLED) (with use of external library starttls.el and |
80 ;; the GSSAPI / kerberos V4 sections of RFC1731 (with use of external | 80 ;; program starttls) and the GSSAPI / kerberos V4 sections of RFC1731 |
81 ;; program `imtest'). It also take advantage the UNSELECT extension | 81 ;; (with use of external program `imtest'). It also take advantage |
82 ;; in Cyrus IMAPD. | 82 ;; the UNSELECT extension in Cyrus IMAPD. |
83 ;; | 83 ;; |
84 ;; Without the work of John McClary Prevost and Jim Radford this library | 84 ;; Without the work of John McClary Prevost and Jim Radford this library |
85 ;; would not have seen the light of day. Many thanks. | 85 ;; would not have seen the light of day. Many thanks. |
86 ;; | 86 ;; |
87 ;; This is a transcript of short interactive session for demonstration | 87 ;; This is a transcript of short interactive session for demonstration |
478 (imap-disable-multibyte) | 478 (imap-disable-multibyte) |
479 (buffer-disable-undo) | 479 (buffer-disable-undo) |
480 (goto-char (point-max)) | 480 (goto-char (point-max)) |
481 (insert-buffer-substring buffer))) | 481 (insert-buffer-substring buffer))) |
482 (erase-buffer) | 482 (erase-buffer) |
483 (message "Kerberos 4 IMAP connection: %s" (or response "failed")) | 483 (message "Opening Kerberos 4 IMAP connection with `%s'...%s" cmd |
484 (if response (concat "done, " response) "failed")) | |
484 (if (and response (let ((case-fold-search nil)) | 485 (if (and response (let ((case-fold-search nil)) |
485 (not (string-match "failed" response)))) | 486 (not (string-match "failed" response)))) |
486 (setq done process) | 487 (setq done process) |
487 (if (memq (process-status process) '(open run)) | 488 (if (memq (process-status process) '(open run)) |
488 (imap-send-command-wait "LOGOUT")) | 489 (imap-send-command-wait "LOGOUT")) |
588 (setq done process)))))) | 589 (setq done process)))))) |
589 (if done | 590 (if done |
590 (progn | 591 (progn |
591 (message "imap: Opening SSL connection with `%s'...done" cmd) | 592 (message "imap: Opening SSL connection with `%s'...done" cmd) |
592 done) | 593 done) |
593 (message "imap: Failed opening SSL connection") | 594 (message "imap: Opening SSL connection with `%s'...failed" cmd) |
594 nil))) | 595 nil))) |
595 | 596 |
596 (defun imap-network-p (buffer) | 597 (defun imap-network-p (buffer) |
597 t) | 598 t) |
598 | 599 |
654 (setq done process))))) | 655 (setq done process))))) |
655 (if done | 656 (if done |
656 (progn | 657 (progn |
657 (message "imap: Opening IMAP connection with `%s'...done" cmd) | 658 (message "imap: Opening IMAP connection with `%s'...done" cmd) |
658 done) | 659 done) |
659 (message "imap: Failed opening IMAP connection") | 660 (message "imap: Opening IMAP connection with `%s'...failed" cmd) |
660 nil))) | 661 nil))) |
661 | 662 |
662 (defun imap-starttls-p (buffer) | 663 (defun imap-starttls-p (buffer) |
663 (and (condition-case () | 664 (and (imap-capability 'STARTTLS buffer) |
664 (require 'starttls) | 665 (condition-case () |
665 (error nil)) | 666 (progn |
666 (imap-capability 'STARTTLS buffer))) | 667 (require 'starttls) |
668 (call-process "starttls")) | |
669 (error nil)))) | |
667 | 670 |
668 (defun imap-starttls-open (name buffer server port) | 671 (defun imap-starttls-open (name buffer server port) |
669 (let* ((port (or port imap-default-port)) | 672 (let* ((port (or port imap-default-port)) |
670 (coding-system-for-read imap-coding-system-for-read) | 673 (coding-system-for-read imap-coding-system-for-read) |
671 (coding-system-for-write imap-coding-system-for-write) | 674 (coding-system-for-write imap-coding-system-for-write) |
672 (process (starttls-open-stream name buffer server port))) | 675 (process (starttls-open-stream name buffer server port)) |
676 done) | |
677 (message "imap: Connecting with STARTTLS...") | |
673 (when process | 678 (when process |
674 (while (and (memq (process-status process) '(open run)) | 679 (while (and (memq (process-status process) '(open run)) |
675 (goto-char (point-min)) | 680 (goto-char (point-min)) |
676 (not (imap-parse-greeting))) | 681 (not (imap-parse-greeting))) |
677 (accept-process-output process 1) | 682 (accept-process-output process 1) |
688 (when (and (eq imap-stream 'starttls) | 693 (when (and (eq imap-stream 'starttls) |
689 (imap-ok-p (imap-send-command-wait "STARTTLS"))) | 694 (imap-ok-p (imap-send-command-wait "STARTTLS"))) |
690 (starttls-negotiate imap-process))) | 695 (starttls-negotiate imap-process))) |
691 (set-process-filter imap-process nil))) | 696 (set-process-filter imap-process nil))) |
692 (when (memq (process-status process) '(open run)) | 697 (when (memq (process-status process) '(open run)) |
693 process)))) | 698 (setq done process))) |
699 (if done | |
700 (progn | |
701 (message "imap: Connecting with STARTTLS...done") | |
702 done) | |
703 (message "imap: Connecting with STARTTLS...failed") | |
704 nil))) | |
694 | 705 |
695 ;; Server functions; authenticator stuff: | 706 ;; Server functions; authenticator stuff: |
696 | 707 |
697 (defun imap-interactive-login (buffer loginfunc) | 708 (defun imap-interactive-login (buffer loginfunc) |
698 "Login to server in BUFFER. | 709 "Login to server in BUFFER. |
734 | 745 |
735 (defun imap-gssapi-auth-p (buffer) | 746 (defun imap-gssapi-auth-p (buffer) |
736 (imap-capability 'AUTH=GSSAPI buffer)) | 747 (imap-capability 'AUTH=GSSAPI buffer)) |
737 | 748 |
738 (defun imap-gssapi-auth (buffer) | 749 (defun imap-gssapi-auth (buffer) |
750 (message "imap: Authenticating using GSSAPI...%s" | |
751 (if (eq imap-stream 'gssapi) "done" "failed")) | |
739 (eq imap-stream 'gssapi)) | 752 (eq imap-stream 'gssapi)) |
740 | 753 |
741 (defun imap-kerberos4-auth-p (buffer) | 754 (defun imap-kerberos4-auth-p (buffer) |
742 (imap-capability 'AUTH=KERBEROS_V4 buffer)) | 755 (imap-capability 'AUTH=KERBEROS_V4 buffer)) |
743 | 756 |
744 (defun imap-kerberos4-auth (buffer) | 757 (defun imap-kerberos4-auth (buffer) |
758 (message "imap: Authenticating using Kerberos 4...%s" | |
759 (if (eq imap-stream 'kerberos4) "done" "failed")) | |
745 (eq imap-stream 'kerberos4)) | 760 (eq imap-stream 'kerberos4)) |
746 | 761 |
747 (defun imap-cram-md5-p (buffer) | 762 (defun imap-cram-md5-p (buffer) |
748 (imap-capability 'AUTH=CRAM-MD5 buffer)) | 763 (imap-capability 'AUTH=CRAM-MD5 buffer)) |
749 | 764 |
750 (defun imap-cram-md5-auth (buffer) | 765 (defun imap-cram-md5-auth (buffer) |
751 "Login to server using the AUTH CRAM-MD5 method." | 766 "Login to server using the AUTH CRAM-MD5 method." |
752 (imap-interactive-login | 767 (message "imap: Authenticating using CRAM-MD5...") |
753 buffer | 768 (let ((done (imap-interactive-login |
754 (lambda (user passwd) | 769 buffer |
755 (imap-ok-p | 770 (lambda (user passwd) |
756 (imap-send-command-wait | 771 (imap-ok-p |
757 (list | 772 (imap-send-command-wait |
758 "AUTHENTICATE CRAM-MD5" | 773 (list |
759 (lambda (challenge) | 774 "AUTHENTICATE CRAM-MD5" |
760 (let* ((decoded (base64-decode-string challenge)) | 775 (lambda (challenge) |
761 (hash (rfc2104-hash 'md5 64 16 passwd decoded)) | 776 (let* ((decoded (base64-decode-string challenge)) |
762 (response (concat user " " hash)) | 777 (hash (rfc2104-hash 'md5 64 16 passwd decoded)) |
763 (encoded (base64-encode-string response))) | 778 (response (concat user " " hash)) |
764 encoded)))))))) | 779 (encoded (base64-encode-string response))) |
780 encoded))))))))) | |
781 (if done | |
782 (message "imap: Authenticating using CRAM-MD5...done") | |
783 (message "imap: Authenticating using CRAM-MD5...failed")))) | |
784 | |
785 | |
765 | 786 |
766 (defun imap-login-p (buffer) | 787 (defun imap-login-p (buffer) |
767 (not (imap-capability 'X-LOGIN-CMD-DISABLED buffer))) | 788 (and (not (imap-capability 'LOGINDISABLED buffer)) |
789 (not (imap-capability 'X-LOGIN-CMD-DISABLED buffer)))) | |
768 | 790 |
769 (defun imap-login-auth (buffer) | 791 (defun imap-login-auth (buffer) |
770 "Login to server using the LOGIN command." | 792 "Login to server using the LOGIN command." |
793 (message "imap: Plaintext authentication...") | |
771 (imap-interactive-login buffer | 794 (imap-interactive-login buffer |
772 (lambda (user passwd) | 795 (lambda (user passwd) |
773 (imap-ok-p (imap-send-command-wait | 796 (imap-ok-p (imap-send-command-wait |
774 (concat "LOGIN \"" user "\" \"" | 797 (concat "LOGIN \"" user "\" \"" |
775 passwd "\"")))))) | 798 passwd "\"")))))) |
776 | 799 |
777 (defun imap-anonymous-p (buffer) | 800 (defun imap-anonymous-p (buffer) |
778 t) | 801 t) |
779 | 802 |
780 (defun imap-anonymous-auth (buffer) | 803 (defun imap-anonymous-auth (buffer) |
804 (message "imap: Loging in anonymously...") | |
781 (with-current-buffer buffer | 805 (with-current-buffer buffer |
782 (imap-ok-p (imap-send-command-wait | 806 (imap-ok-p (imap-send-command-wait |
783 (concat "LOGIN anonymous \"" (concat (user-login-name) "@" | 807 (concat "LOGIN anonymous \"" (concat (user-login-name) "@" |
784 (system-name)) "\""))))) | 808 (system-name)) "\""))))) |
785 | 809 |
786 (defun imap-digest-md5-p (buffer) | 810 (defun imap-digest-md5-p (buffer) |
787 (and (condition-case () | 811 (and (imap-capability 'AUTH=DIGEST-MD5 buffer) |
812 (condition-case () | |
788 (require 'digest-md5) | 813 (require 'digest-md5) |
789 (error nil)) | 814 (error nil)))) |
790 (imap-capability 'AUTH=DIGEST-MD5 buffer))) | |
791 | 815 |
792 (defun imap-digest-md5-auth (buffer) | 816 (defun imap-digest-md5-auth (buffer) |
793 "Login to server using the AUTH DIGEST-MD5 method." | 817 "Login to server using the AUTH DIGEST-MD5 method." |
818 (message "imap: Authenticating using DIGEST-MD5...") | |
794 (imap-interactive-login | 819 (imap-interactive-login |
795 buffer | 820 buffer |
796 (lambda (user passwd) | 821 (lambda (user passwd) |
797 (let ((tag | 822 (let ((tag |
798 (imap-send-command | 823 (imap-send-command |
859 (buffer-disable-undo) | 884 (buffer-disable-undo) |
860 (setq imap-server (or server imap-server)) | 885 (setq imap-server (or server imap-server)) |
861 (setq imap-port (or port imap-port)) | 886 (setq imap-port (or port imap-port)) |
862 (setq imap-auth (or auth imap-auth)) | 887 (setq imap-auth (or auth imap-auth)) |
863 (setq imap-stream (or stream imap-stream)) | 888 (setq imap-stream (or stream imap-stream)) |
864 (when (let ((imap-stream (or imap-stream imap-default-stream))) | 889 (message "imap: Connecting to %s..." imap-server) |
865 (imap-open-1 buffer)) | 890 (if (let ((imap-stream (or imap-stream imap-default-stream))) |
866 ;; Choose stream. | 891 (imap-open-1 buffer)) |
867 (let (stream-changed) | 892 ;; Choose stream. |
868 (when (null imap-stream) | 893 (let (stream-changed) |
869 (let ((streams imap-streams)) | 894 (message "imap: Connecting to %s...done" imap-server) |
870 (while (setq stream (pop streams)) | 895 (when (null imap-stream) |
871 (if (funcall (nth 1 (assq stream imap-stream-alist)) buffer) | 896 (let ((streams imap-streams)) |
872 (setq stream-changed (not (eq (or imap-stream | 897 (while (setq stream (pop streams)) |
873 imap-default-stream) | 898 (if (funcall (nth 1 (assq stream imap-stream-alist)) buffer) |
874 stream)) | 899 (setq stream-changed (not (eq (or imap-stream |
875 imap-stream stream | 900 imap-default-stream) |
876 streams nil))) | 901 stream)) |
877 (unless imap-stream | 902 imap-stream stream |
878 (error "Couldn't figure out a stream for server")))) | 903 streams nil))) |
879 (when stream-changed | 904 (unless imap-stream |
880 (message "Reconnecting with %s..." imap-stream) | 905 (error "Couldn't figure out a stream for server")))) |
881 (imap-close buffer) | 906 (when stream-changed |
882 (imap-open-1 buffer) | 907 (message "imap: Reconnecting with stream `%s'..." imap-stream) |
883 (setq imap-capability nil))) | 908 (imap-close buffer) |
884 (if (imap-opened buffer) | 909 (if (imap-open-1 buffer) |
885 ;; Choose authenticator | 910 (message "imap: Reconnecting with stream `%s'...done" |
886 (when (and (null imap-auth) (not (eq imap-state 'auth))) | 911 imap-stream) |
887 (let ((auths imap-authenticators)) | 912 (message "imap: Reconnecting with stream `%s'...failed" |
888 (while (setq auth (pop auths)) | 913 imap-stream)) |
889 (if (funcall (nth 1 (assq auth imap-authenticator-alist)) | 914 (setq imap-capability nil)) |
890 buffer) | 915 (if (imap-opened buffer) |
891 (setq imap-auth auth | 916 ;; Choose authenticator |
892 auths nil))) | 917 (when (and (null imap-auth) (not (eq imap-state 'auth))) |
893 (unless imap-auth | 918 (let ((auths imap-authenticators)) |
894 (error "Couldn't figure out authenticator for server")))))) | 919 (while (setq auth (pop auths)) |
920 (if (funcall (nth 1 (assq auth imap-authenticator-alist)) | |
921 buffer) | |
922 (setq imap-auth auth | |
923 auths nil))) | |
924 (unless imap-auth | |
925 (error "Couldn't figure out authenticator for server")))))) | |
926 (message "imap: Connecting to %s...failed" imap-server)) | |
895 (when (imap-opened buffer) | 927 (when (imap-opened buffer) |
896 (setq imap-mailbox-data (make-vector imap-mailbox-prime 0)) | 928 (setq imap-mailbox-data (make-vector imap-mailbox-prime 0)) |
897 buffer))) | 929 buffer))) |
898 | 930 |
899 (defun imap-opened (&optional buffer) | 931 (defun imap-opened (&optional buffer) |
2180 ;; ; future standard or standards-track | 2212 ;; ; future standard or standards-track |
2181 ;; ; revisions of this specification. | 2213 ;; ; revisions of this specification. |
2182 | 2214 |
2183 (defun imap-parse-flag-list () | 2215 (defun imap-parse-flag-list () |
2184 (let (flag-list start) | 2216 (let (flag-list start) |
2185 (when (eq (char-after) ?\() | 2217 (assert (eq (char-after) ?\()) |
2186 (imap-forward) | 2218 (while (and (not (eq (char-after) ?\))) |
2187 (while (and (not (eq (char-before) ?\))) | 2219 (setq start (progn (imap-forward) (point))) |
2188 (setq start (point)) | 2220 (> (skip-chars-forward "^ )" (gnus-point-at-eol)) 0)) |
2189 (> (skip-chars-forward "^ )" (gnus-point-at-eol)) 0)) | 2221 (push (buffer-substring start (point)) flag-list)) |
2190 (push (buffer-substring start (point)) flag-list) | 2222 (assert (eq (char-after) ?\))) |
2191 (imap-forward)) | 2223 (imap-forward) |
2192 (nreverse flag-list)))) | 2224 (nreverse flag-list))) |
2193 | 2225 |
2194 ;; envelope = "(" env-date SP env-subject SP env-from SP env-sender SP | 2226 ;; envelope = "(" env-date SP env-subject SP env-from SP env-sender SP |
2195 ;; env-reply-to SP env-to SP env-cc SP env-bcc SP | 2227 ;; env-reply-to SP env-to SP env-cc SP env-bcc SP |
2196 ;; env-in-reply-to SP env-message-id ")" | 2228 ;; env-in-reply-to SP env-message-id ")" |
2197 ;; | 2229 ;; |
2412 (imap-forward) | 2444 (imap-forward) |
2413 (push (imap-parse-nstring) body);; body-fld-id | 2445 (push (imap-parse-nstring) body);; body-fld-id |
2414 (imap-forward) | 2446 (imap-forward) |
2415 (push (imap-parse-nstring) body);; body-fld-desc | 2447 (push (imap-parse-nstring) body);; body-fld-desc |
2416 (imap-forward) | 2448 (imap-forward) |
2417 (push (imap-parse-string) body);; body-fld-enc | 2449 ;; next `or' for Sun SIMS bug, it regard body-fld-enc as a |
2450 ;; nstring and return NIL instead of defaulting back to 7BIT | |
2451 ;; as the standard says. | |
2452 (push (or (imap-parse-nstring) "7BIT") body);; body-fld-enc | |
2418 (imap-forward) | 2453 (imap-forward) |
2419 (push (imap-parse-number) body);; body-fld-octets | 2454 (push (imap-parse-number) body);; body-fld-octets |
2420 | 2455 |
2421 ;; ok, we're done parsing the required parts, what comes now is one | 2456 ;; ok, we're done parsing the required parts, what comes now is one |
2422 ;; of three things: | 2457 ;; of three things: |