comparison lisp/mail/rmail.el @ 90072:cb67264d6096

Revision: miles@gnu.org--gnu-2005/emacs--unicode--0--patch-2 Merge from emacs--cvs-trunk--0 Patches applied: * miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-83 - miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-84 Update from CVS * miles@gnu.org--gnu-2005/emacs--cvs-trunk--0--patch-3 - miles@gnu.org--gnu-2005/emacs--cvs-trunk--0--patch-4 Update from CVS * miles@gnu.org--gnu-2005/emacs--cvs-trunk--0--patch-5 Merge from gnus--rel--5.10 * miles@gnu.org--gnu-2005/emacs--cvs-trunk--0--patch-6 - miles@gnu.org--gnu-2005/emacs--cvs-trunk--0--patch-11 Update from CVS * miles@gnu.org--gnu-2005/emacs--cvs-trunk--0--patch-12 Remove "-face" suffix from lazy-highlight face name * miles@gnu.org--gnu-2005/emacs--cvs-trunk--0--patch-13 - miles@gnu.org--gnu-2005/emacs--cvs-trunk--0--patch-16 Update from CVS * miles@gnu.org--gnu-2005/emacs--cvs-trunk--0--patch-17 Merge from gnus--rel--5.10 * miles@gnu.org--gnu-2005/emacs--cvs-trunk--0--patch-18 - miles@gnu.org--gnu-2005/emacs--cvs-trunk--0--patch-21 Update from CVS * miles@gnu.org--gnu-2005/emacs--cvs-trunk--0--patch-22 <no summary provided> * miles@gnu.org--gnu-2005/emacs--cvs-trunk--0--patch-23 - miles@gnu.org--gnu-2005/emacs--cvs-trunk--0--patch-39 Update from CVS * miles@gnu.org--gnu-2005/emacs--cvs-trunk--0--patch-40 Fix regressions from latest reftex update * miles@gnu.org--gnu-2005/gnus--rel--5.10--base-0 tag of miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-82 * miles@gnu.org--gnu-2005/gnus--rel--5.10--patch-1 Merge from emacs--cvs-trunk--0 * miles@gnu.org--gnu-2005/gnus--rel--5.10--patch-2 Merge from miles@gnu.org--gnu-2004 * miles@gnu.org--gnu-2005/gnus--rel--5.10--patch-3 Merge from emacs--cvs-trunk--0
author Miles Bader <miles@gnu.org>
date Sun, 16 Jan 2005 03:40:12 +0000
parents 95879cc1ed20 1e7f10c55429
children 3ebd9bdb4fe5
comparison
equal deleted inserted replaced
90071:f6b4d0ebf147 90072:cb67264d6096
1 ;;; rmail.el --- main code of "RMAIL" mail reader for Emacs 1 ;;; rmail.el --- main code of "RMAIL" mail reader for Emacs
2 2
3 ;; Copyright (C) 1985,86,87,88,93,94,95,96,97,98,2000, 01, 2004 3 ;; Copyright (C) 1985,86,87,88,93,94,95,96,97,98,2000,01,2004,2005
4 ;; Free Software Foundation, Inc. 4 ;; Free Software Foundation, Inc.
5 5
6 ;; Maintainer: FSF 6 ;; Maintainer: FSF
7 ;; Keywords: mail 7 ;; Keywords: mail
8 8
89 (defgroup rmail-edit nil 89 (defgroup rmail-edit nil
90 "Rmail editing." 90 "Rmail editing."
91 :prefix "rmail-edit-" 91 :prefix "rmail-edit-"
92 :group 'rmail) 92 :group 'rmail)
93 93
94 (defgroup rmail-obsolete nil
95 "Rmail obsolete customization variables."
96 :group 'rmail)
94 97
95 (defcustom rmail-movemail-program nil 98 (defcustom rmail-movemail-program nil
96 "If non-nil, name of program for fetching new mail." 99 "If non-nil, name of program for fetching new mail."
97 :group 'rmail-retrieve 100 :group 'rmail-retrieve
98 :type '(choice (const nil) string)) 101 :type '(choice (const nil) string))
99 102
100 (defcustom rmail-pop-password nil 103 (defcustom rmail-pop-password nil
101 "*Password to use when reading mail from a POP server, if required." 104 "*Password to use when reading mail from POP server. Please, use rmail-remote-password instead."
102 :type '(choice (string :tag "Password") 105 :type '(choice (string :tag "Password")
103 (const :tag "Not Required" nil)) 106 (const :tag "Not Required" nil))
104 :group 'rmail-retrieve) 107 :group 'rmail-obsolete)
105 108
106 (defcustom rmail-pop-password-required nil 109 (defcustom rmail-pop-password-required nil
107 "*Non-nil if a password is required when reading mail using POP." 110 "*Non-nil if a password is required when reading mail from a POP server. Please, use rmail-remote-password-required instead."
108 :type 'boolean 111 :type 'boolean
109 :group 'rmail-retrieve) 112 :group 'rmail-obsolete)
113
114 (defcustom rmail-remote-password nil
115 "*Password to use when reading mail from a remote server. This setting is ignored for mailboxes whose URL already contains a password."
116 :type '(choice (string :tag "Password")
117 (const :tag "Not Required" nil))
118 :set-after '(rmail-pop-password)
119 :set #'(lambda (symbol value)
120 (set-default symbol
121 (if (and (not value)
122 (boundp 'rmail-pop-password)
123 rmail-pop-password)
124 rmail-pop-password
125 value))
126 (setq rmail-pop-password nil))
127 :group 'rmail-retrieve
128 :version "21.3.50.1")
129
130 (defcustom rmail-remote-password-required nil
131 "*Non-nil if a password is required when reading mail from a remote server."
132 :type 'boolean
133 :set-after '(rmail-pop-password-required)
134 :set #'(lambda (symbol value)
135 (set-default symbol
136 (if (and (not value)
137 (boundp 'rmail-pop-password-required)
138 rmail-pop-password-required)
139 rmail-pop-password-required
140 value))
141 (setq rmail-pop-password-required nil))
142 :group 'rmail-retrieve
143 :version "21.3.50.1")
110 144
111 (defcustom rmail-movemail-flags nil 145 (defcustom rmail-movemail-flags nil
112 "*List of flags to pass to movemail. 146 "*List of flags to pass to movemail.
113 Most commonly used to specify `-g' to enable GSS-API authentication 147 Most commonly used to specify `-g' to enable GSS-API authentication
114 or `-k' to enable Kerberos authentication." 148 or `-k' to enable Kerberos authentication."
115 :type '(repeat string) 149 :type '(repeat string)
116 :group 'rmail-retrieve 150 :group 'rmail-retrieve
117 :version "20.3") 151 :version "20.3")
118 152
119 (defvar rmail-pop-password-error "invalid usercode or password\\| 153 (defvar rmail-remote-password-error "invalid usercode or password\\|
120 unknown user name or bad password" 154 unknown user name or bad password\\|Authentication failed\\|MU_ERR_AUTH_FAILURE"
121 "Regular expression matching incorrect-password POP server error messages. 155 "Regular expression matching incorrect-password POP or IMAP server error
156 messages.
122 If you get an incorrect-password error that this expression does not match, 157 If you get an incorrect-password error that this expression does not match,
123 please report it with \\[report-emacs-bug].") 158 please report it with \\[report-emacs-bug].")
124 159
125 (defvar rmail-encoded-pop-password nil) 160 (defvar rmail-encoded-remote-password nil)
126 161
127 (defcustom rmail-preserve-inbox nil 162 (defcustom rmail-preserve-inbox nil
128 "*Non-nil if incoming mail should be left in the user's inbox, 163 "*Non-nil if incoming mail should be left in the user's inbox,
129 rather than deleted, after it is retrieved." 164 rather than deleted, after it is retrieved."
130 :type 'boolean 165 :type 'boolean
131 :group 'rmail-retrieve) 166 :group 'rmail-retrieve)
167
168 (defcustom rmail-movemail-search-path nil
169 "*List of directories to search for movemail (in addition to `exec-path')."
170 :group 'rmail-retrieve
171 :type '(repeat (directory)))
172
173 (defun rmail-probe (prog)
174 "Determine what flavor of movemail PROG is by executing it with --version
175 command line option and analyzing its output."
176 (with-temp-buffer
177 (let ((tbuf (current-buffer)))
178 (buffer-disable-undo tbuf)
179 (call-process prog nil tbuf nil "--version")
180 (if (not (buffer-modified-p tbuf))
181 ;; Should not happen...
182 nil
183 (goto-char (point-min))
184 (cond
185 ((looking-at ".*movemail: invalid option")
186 'emacs) ;; Possibly...
187 ((looking-at "movemail (GNU Mailutils .*)")
188 'mailutils)
189 (t
190 ;; FIXME:
191 'emacs))))))
192
193 (defun rmail-autodetect ()
194 "Determine and return the flavor of `movemail' program in use. If
195 rmail-movemail-program is set, use it. Otherwise, look for `movemail'
196 in the path constructed by appending rmail-movemail-search-path,
197 exec-path and exec-directory."
198 (if rmail-movemail-program
199 (rmail-probe rmail-movemail-program)
200 (catch 'scan
201 (dolist (dir (append rmail-movemail-search-path exec-path
202 (list exec-directory)))
203 (when (and dir (file-accessible-directory-p dir))
204 (let ((progname (expand-file-name "movemail" dir)))
205 (when (and (not (file-directory-p progname))
206 (file-executable-p progname))
207 (let ((x (rmail-probe progname)))
208 (when x
209 (setq rmail-movemail-program progname)
210 (throw 'scan x))))))))))
211
212 (defvar rmail-movemail-variant-in-use nil
213 "The movemail variant currently in use. Known variants are:
214
215 `emacs' Means any implementation, compatible with the native Emacs one.
216 This is the default;
217 `mailutils' Means GNU mailutils implementation, capable of handling full
218 mail URLs as the source mailbox;")
219
220 ;;;###autoload
221 (defun rmail-movemail-variant-p (&rest variants)
222 "Return t if the current movemail variant is any of VARIANTS.
223 Currently known variants are 'emacs and 'mailutils."
224 (when (not rmail-movemail-variant-in-use)
225 ;; Autodetect
226 (setq rmail-movemail-variant-in-use (rmail-autodetect)))
227 (not (null (member rmail-movemail-variant-in-use variants))))
132 228
133 ;;;###autoload 229 ;;;###autoload
134 (defcustom rmail-dont-reply-to-names nil "\ 230 (defcustom rmail-dont-reply-to-names nil "\
135 *A regexp specifying addresses to prune from a reply message. 231 *A regexp specifying addresses to prune from a reply message.
136 A value of nil means exclude your own email address as an address 232 A value of nil means exclude your own email address as an address
1514 (setq found t)))) 1610 (setq found t))))
1515 found) 1611 found)
1516 ;; Don't leave the buffer screwed up if we get a disk-full error. 1612 ;; Don't leave the buffer screwed up if we get a disk-full error.
1517 (or found (rmail-show-message))))) 1613 (or found (rmail-show-message)))))
1518 1614
1615 (defun rmail-parse-url (file)
1616 "Parse the supplied URL. Return (list MAILBOX-NAME REMOTE PASSWORD GOT-PASSWORD)
1617 WHERE MAILBOX-NAME is the name of the mailbox suitable as argument to the
1618 actual version of `movemail', REMOTE is non-nil if MAILBOX-NAME refers to
1619 a remote mailbox, PASSWORD is the password if it should be
1620 supplied as a separate argument to `movemail' or nil otherwise, GOT-PASSWORD
1621 is non-nil if the user has supplied the password interactively.
1622 "
1623 (if (string-match "^\\([^:]+\\)://\\(\\([^:@]+\\)\\(:\\([^@]+\\)\\)?@\\)?.*" file)
1624 (let (got-password supplied-password
1625 (proto (match-string 1 file))
1626 (user (match-string 3 file))
1627 (pass (match-string 5 file))
1628 (host (substring file (or (match-end 2)
1629 (+ 3 (match-end 1))))))
1630 (if (not pass)
1631 (when rmail-remote-password-required
1632 (setq got-password (not (rmail-have-password)))
1633 (setq supplied-password (rmail-get-remote-password
1634 (string-equal proto "imap")))))
1635
1636 (if (rmail-movemail-variant-p 'emacs)
1637 (if (string-equal proto "pop")
1638 (list (concat "po:" user ":" host)
1639 t
1640 (or pass supplied-password)
1641 got-password)
1642 (error "Emacs movemail does not support %s protocol" proto))
1643 (list file
1644 (or (string-equal proto "pop") (string-equal proto "imap"))
1645 supplied-password
1646 got-password)))
1647 (list file nil nil nil)))
1648
1519 (defun rmail-insert-inbox-text (files renamep) 1649 (defun rmail-insert-inbox-text (files renamep)
1520 ;; Detect a locked file now, so that we avoid moving mail 1650 ;; Detect a locked file now, so that we avoid moving mail
1521 ;; out of the real inbox file. (That could scare people.) 1651 ;; out of the real inbox file. (That could scare people.)
1522 (or (memq (file-locked-p buffer-file-name) '(nil t)) 1652 (or (memq (file-locked-p buffer-file-name) '(nil t))
1523 (error "RMAIL file %s is locked" 1653 (error "RMAIL file %s is locked"
1524 (file-name-nondirectory buffer-file-name))) 1654 (file-name-nondirectory buffer-file-name)))
1525 (let (file tofile delete-files movemail popmail got-password password) 1655 (let (file tofile delete-files movemail popmail got-password password)
1526 (while files 1656 (while files
1527 ;; Handle POP mailbox names specially; don't expand as filenames 1657 ;; Handle remote mailbox names specially; don't expand as filenames
1528 ;; in case the userid contains a directory separator. 1658 ;; in case the userid contains a directory separator.
1529 (setq file (car files)) 1659 (setq file (car files))
1530 (setq popmail (string-match "^po:" file)) 1660 (let ((url-data (rmail-parse-url file)))
1661 (setq file (nth 0 url-data))
1662 (setq popmail (nth 1 url-data))
1663 (setq password (nth 2 url-data))
1664 (setq got-password (nth 3 url-data)))
1665
1531 (if popmail 1666 (if popmail
1532 (setq renamep t) 1667 (setq renamep t)
1533 (setq file (file-truename 1668 (setq file (file-truename
1534 (substitute-in-file-name (expand-file-name file))))) 1669 (substitute-in-file-name (expand-file-name file)))))
1535 (setq tofile (expand-file-name 1670 (setq tofile (expand-file-name
1536 ;; Generate name to move to from inbox name, 1671 ;; Generate name to move to from inbox name,
1537 ;; in case of multiple inboxes that need moving. 1672 ;; in case of multiple inboxes that need moving.
1538 (concat ".newmail-" (file-name-nondirectory file)) 1673 (concat ".newmail-"
1674 (file-name-nondirectory
1675 (if (memq system-type '(windows-nt cygwin))
1676 ;; cannot have "po:" in file name
1677 (substring file 3)
1678 file)))
1539 ;; Use the directory of this rmail file 1679 ;; Use the directory of this rmail file
1540 ;; because it's a nuisance to use the homedir 1680 ;; because it's a nuisance to use the homedir
1541 ;; if that is on a full disk and this rmail 1681 ;; if that is on a full disk and this rmail
1542 ;; file isn't. 1682 ;; file isn't.
1543 (file-name-directory 1683 (file-name-directory
1558 ;; and the actual inbox is /usr/spool/mail/foo/foo. 1698 ;; and the actual inbox is /usr/spool/mail/foo/foo.
1559 (if (file-directory-p file) 1699 (if (file-directory-p file)
1560 (setq file (expand-file-name (user-login-name) 1700 (setq file (expand-file-name (user-login-name)
1561 file))))) 1701 file)))))
1562 (cond (popmail 1702 (cond (popmail
1563 (if rmail-pop-password-required 1703 (message "Getting mail from the remote server ..."))
1564 (progn (setq got-password (not (rmail-have-password)))
1565 (setq password (rmail-get-pop-password))))
1566 (if (memq system-type '(windows-nt cygwin))
1567 ;; cannot have "po:" in file name
1568 (setq tofile
1569 (expand-file-name
1570 (concat ".newmail-pop-"
1571 (file-name-nondirectory (substring file 3)))
1572 (file-name-directory
1573 (expand-file-name buffer-file-name)))))
1574 (message "Getting mail from post office ..."))
1575 ((and (file-exists-p tofile) 1704 ((and (file-exists-p tofile)
1576 (/= 0 (nth 7 (file-attributes tofile)))) 1705 (/= 0 (nth 7 (file-attributes tofile))))
1577 (message "Getting mail from %s..." tofile)) 1706 (message "Getting mail from %s..." tofile))
1578 ((and (file-exists-p file) 1707 ((and (file-exists-p file)
1579 (/= 0 (nth 7 (file-attributes file)))) 1708 (/= 0 (nth 7 (file-attributes file))))
1601 (if (not rmail-preserve-inbox) 1730 (if (not rmail-preserve-inbox)
1602 (condition-case () 1731 (condition-case ()
1603 (write-region (point) (point) file) 1732 (write-region (point) (point) file)
1604 (file-error nil)))) 1733 (file-error nil))))
1605 (t 1734 (t
1606 (let ((errors nil)) 1735 (with-temp-buffer
1607 (unwind-protect 1736 (let ((errors (current-buffer)))
1608 (save-excursion 1737 (buffer-disable-undo errors)
1609 (setq errors (generate-new-buffer " *rmail loss*")) 1738 (let ((args
1610 (buffer-disable-undo errors) 1739 (append
1611 (let ((args 1740 (list (or rmail-movemail-program
1612 (append 1741 (expand-file-name "movemail"
1613 (list (or rmail-movemail-program 1742 exec-directory))
1614 (expand-file-name "movemail" 1743 nil errors nil)
1615 exec-directory)) 1744 (if rmail-preserve-inbox
1616 nil errors nil) 1745 (list "-p")
1617 (if rmail-preserve-inbox 1746 nil)
1618 (list "-p") 1747 (if (rmail-movemail-variant-p 'mailutils)
1619 nil) 1748 (append (list "--emacs") rmail-movemail-flags)
1620 rmail-movemail-flags 1749 rmail-movemail-flags)
1621 (list file tofile) 1750 (list file tofile)
1622 (if password (list password) nil)))) 1751 (if password (list password) nil))))
1623 (apply 'call-process args)) 1752 (apply 'call-process args))
1624 (if (not (buffer-modified-p errors)) 1753 (if (not (buffer-modified-p errors))
1625 ;; No output => movemail won 1754 ;; No output => movemail won
1626 nil 1755 nil
1627 (set-buffer errors) 1756 (set-buffer errors)
1628 (subst-char-in-region (point-min) (point-max) 1757 (subst-char-in-region (point-min) (point-max)
1629 ?\n ?\ ) 1758 ?\n ?\ )
1630 (goto-char (point-max)) 1759 (goto-char (point-max))
1631 (skip-chars-backward " \t") 1760 (skip-chars-backward " \t")
1632 (delete-region (point) (point-max)) 1761 (delete-region (point) (point-max))
1633 (goto-char (point-min)) 1762 (goto-char (point-min))
1634 (if (looking-at "movemail: ") 1763 (if (looking-at "movemail: ")
1635 (delete-region (point-min) (match-end 0))) 1764 (delete-region (point-min) (match-end 0)))
1636 (beep t) 1765 (beep t)
1637 (message "movemail: %s" 1766 ;; If we just read the password, most likely it is
1638 (buffer-substring (point-min) 1767 ;; wrong. Otherwise, see if there is a specific
1639 (point-max))) 1768 ;; reason to think that the problem is a wrong passwd.
1640 ;; If we just read the password, most likely it is 1769 (if (or got-password
1641 ;; wrong. Otherwise, see if there is a specific 1770 (re-search-forward rmail-remote-password-error
1642 ;; reason to think that the problem is a wrong passwd. 1771 nil t))
1643 (if (or got-password 1772 (rmail-set-remote-password nil))
1644 (re-search-forward rmail-pop-password-error 1773
1645 nil t)) 1774 ;; If using Mailutils, remove initial error code
1646 (rmail-set-pop-password nil)) 1775 ;; abbreviation
1647 (sit-for 3) 1776 (when (rmail-movemail-variant-p 'mailutils)
1648 nil)) 1777 (goto-char (point-min))
1649 (if errors (kill-buffer errors)))))) 1778 (when (looking-at "[A-Z][A-Z0-9_]*:")
1779 (delete-region (point-min) (match-end 0))))
1780
1781 (message "movemail: %s"
1782 (buffer-substring (point-min)
1783 (point-max)))
1784
1785 (sit-for 3)
1786 nil)))))
1787
1650 ;; At this point, TOFILE contains the name to read: 1788 ;; At this point, TOFILE contains the name to read:
1651 ;; Either the alternate name (if we renamed) 1789 ;; Either the alternate name (if we renamed)
1652 ;; or the actual inbox (if not renaming). 1790 ;; or the actual inbox (if not renaming).
1653 (if (file-exists-p tofile) 1791 (if (file-exists-p tofile)
1654 (let ((coding-system-for-read 'no-conversion) 1792 (let ((coding-system-for-read 'no-conversion)
3832 ; The password is encoded to prevent it from being easily accessible 3970 ; The password is encoded to prevent it from being easily accessible
3833 ; to "prying eyes." Obviously, this encoding isn't "real security," 3971 ; to "prying eyes." Obviously, this encoding isn't "real security,"
3834 ; nor is it meant to be. 3972 ; nor is it meant to be.
3835 3973
3836 ;;;###autoload 3974 ;;;###autoload
3837 (defun rmail-set-pop-password (password) 3975 (defun rmail-set-remote-password (password)
3838 "Set PASSWORD to be used for retrieving mail from a POP server." 3976 "Set PASSWORD to be used for retrieving mail from a POP or IMAP server."
3839 (interactive "sPassword: ") 3977 (interactive "sPassword: ")
3840 (if password 3978 (if password
3841 (setq rmail-encoded-pop-password 3979 (setq rmail-encoded-remote-password
3842 (rmail-encode-string password (emacs-pid))) 3980 (rmail-encode-string password (emacs-pid)))
3843 (setq rmail-pop-password nil) 3981 (setq rmail-remote-password nil)
3844 (setq rmail-encoded-pop-password nil))) 3982 (setq rmail-encoded-remote-password nil)))
3845 3983
3846 (defun rmail-get-pop-password () 3984 (defun rmail-get-remote-password (imap)
3847 "Get the password for retrieving mail from a POP server. If none 3985 "Get the password for retrieving mail from a POP or IMAP server. If none
3848 has been set, then prompt the user for one." 3986 has been set, then prompt the user for one."
3849 (if (not rmail-encoded-pop-password) 3987 (when (not rmail-encoded-remote-password)
3850 (progn (if (not rmail-pop-password) 3988 (if (not rmail-remote-password)
3851 (setq rmail-pop-password (read-passwd "POP password: "))) 3989 (setq rmail-remote-password
3852 (rmail-set-pop-password rmail-pop-password) 3990 (read-passwd (if imap
3853 (setq rmail-pop-password nil))) 3991 "IMAP password: "
3854 (rmail-encode-string rmail-encoded-pop-password (emacs-pid))) 3992 "POP password: "))))
3993 (rmail-set-remote-password rmail-remote-password)
3994 (setq rmail-remote-password nil))
3995 (rmail-encode-string rmail-encoded-remote-password (emacs-pid)))
3855 3996
3856 (defun rmail-have-password () 3997 (defun rmail-have-password ()
3857 (or rmail-pop-password rmail-encoded-pop-password)) 3998 (or rmail-remote-password rmail-encoded-remote-password))
3858 3999
3859 (defun rmail-encode-string (string mask) 4000 (defun rmail-encode-string (string mask)
3860 "Encode STRING with integer MASK, by taking the exclusive OR of the 4001 "Encode STRING with integer MASK, by taking the exclusive OR of the
3861 lowest byte in the mask with the first character of string, the 4002 lowest byte in the mask with the first character of string, the
3862 second-lowest-byte with the second character of the string, etc., 4003 second-lowest-byte with the second character of the string, etc.,