]> code.delx.au - gnu-emacs/blobdiff - lisp/mail/sendmail.el
(mail-mode): Don't set local-abbrev-table.
[gnu-emacs] / lisp / mail / sendmail.el
index 34e653cc83414b2c539730b8432b42e08053d5c3..7be8c973762c3dcf40d8c2b8566385110a609b2b 100644 (file)
@@ -1,6 +1,6 @@
 ;;; sendmail.el --- mail sending commands for Emacs.  -*- byte-compile-dynamic: t -*-
 
-;; Copyright (C) 1985, 86, 92, 93, 94, 95, 96, 98, 2000, 2001
+;; Copyright (C) 1985, 86, 92, 93, 94, 95, 96, 98, 2000, 2001, 2002
 ;;   Free Software Foundation, Inc.
 
 ;; Maintainer: FSF
@@ -81,8 +81,8 @@ is a privileged operation."
 If this is nil while `mail-specify-envelope-from' is non-nil, the
 content of `user-mail-address' is used."
   :version "21.1"
-  :type '(choice (const :tag "Use `user-mail-address'" nil)
-                string)
+  :type '(choice (string :tag "From-name")
+                (const :tag "Use `user-mail-address'" nil))
   :group 'sendmail)
 
 ;;;###autoload
@@ -257,7 +257,7 @@ If a string, that string is inserted.
   which is the standard way to delimit a signature in a message.)
 Otherwise, it should be an expression; it is evaluated
 and should insert whatever you want to insert."
-  :type '(choice (const "None" nil)
+  :type '(choice (const :tag "None" nil)
                 (const :tag "Use `.signature' file" t)
                 (string :tag "String to insert")
                 (sexp :tag "Expression to evaluate"))
@@ -269,6 +269,14 @@ and should insert whatever you want to insert."
   :type 'file
   :group 'sendmail)
 
+;;;###autoload
+(defcustom mail-default-directory "~/"
+  "*Directory for mail buffers.
+Value of `default-directory' for mail buffers.
+This directory is used for auto-save files of mail buffers."
+  :type '(directory :tag "Directory")
+  :group 'sendmail)
+
 (defvar mail-reply-action nil)
 (defvar mail-send-actions nil
   "A list of actions to be performed upon successful sending of a message.")
@@ -301,6 +309,16 @@ for the recipient, who may not know how to decode them properly."
   :type '(choice (const t) (const nil) (const query) (const mime))
   :group 'sendmail)
 
+(defcustom mail-use-dsn nil
+  "*Ask MTA for notification of failed, delayed or successful delivery.
+Note that only some MTAs (currently only recent versions of Sendmail)
+support Delivery Status Notification."
+  :group 'sendmail
+  :type '(repeat (radio (const :tag "Failure" failure)
+                       (const :tag "Delay" delay)
+                       (const :tag "Success" success)))
+  :version "21.4")
+
 ;; Note: could use /usr/ucb/mail instead of sendmail;
 ;; options -t, and -v if not interactive.
 (defvar mail-mailer-swallows-blank-line
@@ -455,6 +473,7 @@ actually occur.")
   :type 'hook
   :options '(footnote-mode))
 
+(defvar mail-mode-abbrev-table text-mode-abbrev-table)
 ;;;###autoload
 (define-derived-mode mail-mode text-mode "Mail"
   "Major mode for editing mail to be sent.
@@ -487,7 +506,7 @@ Turning on Mail mode runs the normal hooks `text-mode-hook' and
   (set (make-local-variable 'comment-start) mail-yank-prefix)
   (make-local-variable 'adaptive-fill-regexp)
   (setq adaptive-fill-regexp
-       (concat "[ \t]*[-[:alnum:]]*>+[ \t]*\\|"
+       (concat "[ \t]*[-[:alnum:]]+>+[ \t]*\\|"
                adaptive-fill-regexp))
   (make-local-variable 'adaptive-fill-first-line-regexp)
   (setq adaptive-fill-first-line-regexp
@@ -798,7 +817,11 @@ external program defined by `sendmail-program'."
        (program (if (boundp 'sendmail-program)
                     sendmail-program
                   "/usr/lib/sendmail"))
-       (mail-envelope-from mail-envelope-from))
+       ;; Examine these variables now, so that
+       ;; local binding in the mail buffer will take effect.
+       (envelope-from
+        (and mail-specify-envelope-from
+             (or mail-envelope-from user-mail-address))))
     (unwind-protect
        (save-excursion
          (set-buffer tembuf)
@@ -964,9 +987,8 @@ external program defined by `sendmail-program'."
                      (append (list (point-min) (point-max)
                                    program
                                    nil errbuf nil "-oi")
-                             (and mail-specify-envelope-from
-                                  (list "-f" (or mail-envelope-from
-                                                 user-mail-address)))
+                             (and envelope-from
+                                  (list "-f" envelope-from))
 ;;;                          ;; Don't say "from root" if running under su.
 ;;;                          (and (equal (user-real-login-name) "root")
 ;;;                               (list "-f" (user-login-name)))
@@ -987,6 +1009,9 @@ external program defined by `sendmail-program'."
 ;;;                          (or resend-to-addresses
                                  '("-t")
 ;;;                              )
+                             (if mail-use-dsn
+                                 (list "-N" (mapconcat 'symbol-name
+                                                       mail-use-dsn ",")))
                              )
                      )
                     (exit-value (apply 'call-process-region args)))
@@ -1496,10 +1521,11 @@ The seventh argument ACTIONS is a list of actions to take
 ;;;          (message "Auto save file for draft message exists; consider M-x mail-recover"))
 ;;;          t))
   (pop-to-buffer "*mail*")
-  ;; Put the auto-save file in the home dir
-  ;; to avoid any danger that it can't be written.
-  (if (file-exists-p (expand-file-name "~/"))
-      (setq default-directory (expand-file-name "~/")))
+  ;; Avoid danger that the auto-save file can't be written.
+  (let ((dir (expand-file-name
+             (file-name-as-directory mail-default-directory))))
+    (if (file-exists-p dir)
+       (setq default-directory dir)))
   ;; Only call auto-save-mode if necessary, to avoid changing auto-save file.
   (if (or (and auto-save-default (not buffer-auto-save-file-name))
           (and (not auto-save-default) buffer-auto-save-file-name))
@@ -1532,22 +1558,123 @@ The seventh argument ACTIONS is a list of actions to take
        (message "Auto save file for draft message exists; consider M-x mail-recover"))
     initialized))
 
+(defun mail-recover-1 ()
+  "Pop up a list of auto-saved draft messages so you can recover one of them."
+  (interactive)
+  (let ((file-name (make-auto-save-file-name))
+       (ls-lisp-support-shell-wildcards t)
+       non-random-len wildcard)
+    ;; Remove the random part from the auto-save-file-name, and
+    ;; create a wildcard which matches possible candidates.
+    ;; Note: this knows that make-auto-save-file-name appends
+    ;; "#<RANDOM-STUFF>#" to the buffer name, where RANDOM-STUFF
+    ;; is the result of (make-temp-name "").
+    (setq non-random-len
+         (- (length file-name) (length (make-temp-name "")) 1))
+    (setq wildcard (concat (substring file-name 0 non-random-len) "*"))
+    (if (null (file-expand-wildcards wildcard))
+       (message "There are no auto-saved drafts to recover")
+      ;; Bind dired-trivial-filenames to t because all auto-save file
+      ;; names are normally ``trivial'', so Dired will set point after
+      ;; all the files, at buffer bottom.  We want it on the first
+      ;; file instead.
+      (let ((dired-trivial-filenames t))
+       (dired-other-window wildcard (concat dired-listing-switches "t")))
+      (rename-buffer "*Auto-saved Drafts*" t)
+      (save-excursion
+       (goto-char (point-min))
+       (or (looking-at " Move to the draft file you want to recover,")
+           (let ((inhibit-read-only t))
+             ;; Each line starts with a space so that Font Lock mode
+             ;; won't highlight the first character.
+             (insert "\
+ Move to the draft file you want to recover, then type C-c C-c
+ to recover text of message whose composition was interrupted.
+ To browse text of a draft, type v on the draft file's line.
+
+ You can also delete some of these files;
+ type d on a line to mark that file for deletion.
+
+ List of possible auto-save files for recovery:
+
+"))))
+      (use-local-map
+       (let ((map (make-sparse-keymap)))
+        (set-keymap-parent map (current-local-map))
+        map))
+      (define-key (current-local-map) "v"
+       (lambda ()
+         (interactive)
+         (let ((coding-system-for-read 'emacs-mule-unix))
+           (dired-view-file))))
+      (define-key (current-local-map) "\C-c\C-c"
+       (lambda ()
+         (interactive)
+         (let ((fname (dired-get-filename))
+               ;; Auto-saved files are written in the internal
+               ;; representation, so they should be read accordingly.
+               (coding-system-for-read 'emacs-mule-unix))
+           (switch-to-buffer-other-window "*mail*")
+           (let ((buffer-read-only nil))
+             (erase-buffer)
+             (insert-file-contents fname nil)
+             ;; insert-file-contents will set buffer-file-coding-system
+             ;; to emacs-mule, which is probably not what they want to
+             ;; use for sending the message.  But we don't know what
+             ;; was its value before the buffer was killed or Emacs
+             ;; crashed.  We therefore reset buffer-file-coding-system
+             ;; to the default value, so that either the default does
+             ;; TRT, or the user will get prompted for the right
+             ;; encoding when they send the message.
+             (setq buffer-file-coding-system
+                   default-buffer-file-coding-system))))))))
+
 (defun mail-recover ()
-  "Reread contents of current buffer from its last auto-save file."
+  "Recover interrupted mail composition from auto-save files.
+
+If the mail buffer has a current valid auto-save file,
+the command recovers that file.  Otherwise, it displays a
+buffer showing the existing auto-saved draft messages;
+you can move to one of them and type C-c C-c to recover that one."
   (interactive)
-  (let ((file-name (make-auto-save-file-name)))
-    (cond ((save-window-excursion
-            (if (not (eq system-type 'vax-vms))
-                (with-output-to-temp-buffer "*Directory*"
-                  (buffer-disable-undo standard-output)
-                  (let ((default-directory "/"))
-                    (call-process
-                     "ls" nil standard-output nil "-l" file-name))))
-            (yes-or-no-p (format "Recover auto save file %s? " file-name)))
-          (let ((buffer-read-only nil))
-            (erase-buffer)
-            (insert-file-contents file-name nil)))
-         (t (error "mail-recover cancelled")))))
+  ;; In case they invoke us from some random buffer...
+  (switch-to-buffer "*mail*")
+  ;; If *mail* didn't exist, set its directory, so that auto-saved
+  ;; drafts will be found.
+  (let ((dir (expand-file-name
+             (file-name-as-directory mail-default-directory))))
+    (if (file-exists-p dir)
+       (setq default-directory dir)))
+  (or (eq major-mode 'mail-mode)
+      (mail-mode))
+  (let ((file-name buffer-auto-save-file-name))
+    (cond ((and file-name (file-exists-p file-name))
+          (let ((dispbuf
+                 ;; This used to invoke `ls' via call-process, but
+                 ;; dired-noselect is more portable to systems where
+                 ;; `ls' is not a standard program (it will use
+                 ;; ls-lisp instead).
+                 (dired-noselect file-name
+                                 (concat dired-listing-switches "t"))))
+            (save-selected-window
+              (select-window (display-buffer dispbuf t))
+              (goto-char (point-min))
+              (forward-line 2)
+              (dired-move-to-filename)
+              (setq dispbuf (rename-buffer "*Directory*" t)))
+            (if (not (yes-or-no-p
+                      (format "Recover mail draft from auto save file %s? "
+                              file-name)))
+                (error "mail-recover cancelled")
+              (let ((buffer-read-only nil)
+                    (buffer-coding buffer-file-coding-system)
+                    ;; Auto-save files are written in internal
+                    ;; representation of non-ASCII characters.
+                    (coding-system-for-read 'emacs-mule-unix))
+                (erase-buffer)
+                (insert-file-contents file-name nil)
+                (setq buffer-file-coding-system buffer-coding)))))
+         (t (mail-recover-1)))))
 
 ;;;###autoload
 (defun mail-other-window (&optional noerase to subject in-reply-to cc replybuffer sendactions)