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: