]> code.delx.au - gnu-emacs/blobdiff - lisp/mail/sendmail.el
(mail-alias-file): Add autoload cookie.
[gnu-emacs] / lisp / mail / sendmail.el
index 5eb37c9c32d87f3b56aa92eba050c0823bbc766c..0f2861f8868a4afbd68081c15ff32f2298ce4be9 100644 (file)
@@ -1,6 +1,6 @@
 ;;; sendmail.el --- mail sending commands for Emacs.
 
-;; Copyright (C) 1985, 1986, 1992 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1986, 1992, 1993, 1994 Free Software Foundation, Inc.
 
 ;; Maintainer: FSF
 ;; Keywords: mail
@@ -58,9 +58,11 @@ The headers are be delimited by a line which is `mail-header-separator'.")
 *Name of file to write all outgoing messages in, or nil for none.
 Do not use an rmail file here!  Instead, use its inbox file.")
 
+;;;###autoload
 (defvar mail-default-reply-to nil
   "*Address to insert as default Reply-to field of outgoing messages.")
 
+;;;###autoload
 (defvar mail-alias-file nil
   "*If non-nil, the name of a file to use instead of `/usr/lib/aliases'.
 This file defines aliases to be expanded by the mailer; this is a different
@@ -79,7 +81,7 @@ nil means use indentation.")
 (defvar mail-indentation-spaces 3
   "*Number of spaces to insert at the beginning of each cited line.
 Used by `mail-yank-original' via `mail-yank-cite'.")
-(defvar mail-yank-hooks '(mail-indent-citation)
+(defvar mail-yank-hooks nil
   "Obsolete hook for modifying a citation just inserted in the mail buffer.
 Each hook function can find the citation between (point) and (mark t).
 And each hook function should leave point and mark around the citation
@@ -125,6 +127,26 @@ If t, it means to insert the contents of the file `~/.signature'.")
 It is inserted before you edit the message,
 so you can edit or delete these lines.")
 
+;; Note: could use /usr/ucb/mail instead of sendmail;
+;; options -t, and -v if not interactive.
+(defvar mail-mailer-swallows-blank-line
+  (if (and (string-match "sparc-sun-sunos\\(\\'\\|[^5]\\)" system-configuration)
+          (file-readable-p "/etc/sendmail.cf")
+          (let ((buffer (get-buffer-create " *temp*")))
+            (unwind-protect
+                (save-excursion
+                  (set-buffer buffer)
+                  (insert-file-contents "/etc/sendmail.cf")
+                  (goto-char (point-min))
+                  (let ((case-fold-search nil))
+                    (re-search-forward "^OR\\>" nil t)))
+              (kill-buffer buffer))))
+      '(looking-at "[ \t]\\|[-a-zA-Z]+:"))
+  "Set this non-nil if the system's mailer runs the header and body together.
+\(This problem exists on Sunos 4 when sendmail is run in remote mode.)
+The value should be an expression to test whether the problem will
+actually occur.")
+
 (defvar mail-mode-syntax-table nil
   "Syntax table used while in mail mode.")
 
@@ -133,6 +155,9 @@ so you can edit or delete these lines.")
      (setq mail-mode-syntax-table (copy-syntax-table text-mode-syntax-table))
      (modify-syntax-entry ?% ". " mail-mode-syntax-table)))
 
+(defvar mail-send-hook nil
+  "Normal hook run before sending mail, in Mail mode.")
+
 (defun mail-setup (to subject in-reply-to cc replybuffer actions)
   (if (eq mail-aliases t)
       (progn
@@ -174,7 +199,9 @@ so you can edit or delete these lines.")
     (if to (setq to (point)))
     (cond ((eq mail-signature t)
           (if (file-exists-p "~/.signature")
-              (insert-file-contents "~/.signature")))
+              (progn
+                (insert "\n\n-- \n")
+                (insert-file-contents "~/.signature"))))
          (mail-signature
           (insert mail-signature)))
     (goto-char (point-max))
@@ -192,6 +219,7 @@ C-c C-s  mail-send (send the message)    C-c C-c  mail-send-and-exit
 C-c C-f  move to a header field (and create it if there isn't):
         C-c C-f C-t  move to To:       C-c C-f C-s  move to Subj:
         C-c C-f C-b  move to BCC:      C-c C-f C-c  move to CC:
+        C-c C-f C-f  move to FCC:
 C-c C-t  move to message text.
 C-c C-y  mail-yank-original (insert current message, in Rmail).
 C-c C-q  mail-fill-yanked-message (fill what was yanked).
@@ -302,13 +330,23 @@ Prefix arg means don't delete this window."
             (cdr (assq 'dedicated (frame-parameters)))
             (not (null (delq (selected-frame) (visible-frame-list)))))
        (delete-frame (selected-frame))
-      (if (and (not arg)
-              (not (one-window-p))
-              (save-excursion
-                (set-buffer (window-buffer (next-window (selected-window) 'not)))
-                (eq major-mode 'rmail-mode)))
-         (delete-window)
-       (switch-to-buffer newbuf)))))
+      (let (rmail-flag summary-buffer)
+       (and (not arg)
+            (not (one-window-p))
+            (save-excursion
+              (set-buffer (window-buffer (next-window (selected-window) 'not)))
+              (setq rmail-flag (eq major-mode 'rmail-mode))
+              (setq summary-buffer
+                    (and (boundp 'rmail-summary-buffer)
+                         rmail-summary-buffer
+                         (buffer-name rmail-summary-buffer)
+                         (not (get-buffer-window rmail-summary-buffer))
+                         rmail-summary-buffer))))
+       (if rmail-flag
+           ;; If the Rmail buffer has a summary, show that.
+           (if summary-buffer (switch-to-buffer summary-buffer)
+             (delete-window))
+         (switch-to-buffer newbuf))))))
 
 (defun mail-send ()
   "Send the message in the current buffer.
@@ -322,8 +360,8 @@ the user from the mailer."
        (or (buffer-modified-p)
            (y-or-n-p "Message already sent; resend? ")))
       (progn
-       (message "Sending...")
        (run-hooks 'mail-send-hook)
+       (message "Sending...")
        (funcall send-mail-function)
        ;; Now perform actions on successful sending.
        (while mail-send-actions
@@ -345,6 +383,7 @@ the user from the mailer."
                  0))
        (tembuf (generate-new-buffer " sendmail temp"))
        (case-fold-search nil)
+       resend-to-addresses
        delimline
        (mailbuf (current-buffer)))
     (unwind-protect
@@ -372,26 +411,36 @@ the user from the mailer."
            (replace-match "\n"))
          (let ((case-fold-search t))
            (goto-char (point-min))
-           (if (re-search-forward "^Sender:" delimline t)
-               (error "Sender may not be specified."))
            ;; Find and handle any FCC fields.
            (goto-char (point-min))
            (if (re-search-forward "^FCC:" delimline t)
                (mail-do-fcc delimline))
-           ;; If the From is different than current user, insert Sender.
            (goto-char (point-min))
-           (and (re-search-forward "^From:"  delimline t)
-                (progn
-                  (require 'mail-utils)
-                  (not (string-equal
-                        (mail-strip-quoted-names
-                         (save-restriction
-                           (narrow-to-region (point-min) delimline)
-                           (mail-fetch-field "From")))
-                        (user-login-name))))
-                (progn
-                  (forward-line 1)
-                  (insert "Sender: " (user-login-name) "\n")))
+           (require 'mail-utils)
+           (while (re-search-forward "^Resent-to:" delimline t)
+             (setq resend-to-addresses
+                   (save-restriction
+                     (narrow-to-region (point)
+                                       (save-excursion
+                                         (end-of-line)
+                                         (point)))
+                     (append (mail-parse-comma-list)
+                             resend-to-addresses))))
+;;; Apparently this causes a duplicate Sender.
+;;;        ;; If the From is different than current user, insert Sender.
+;;;        (goto-char (point-min))
+;;;        (and (re-search-forward "^From:"  delimline t)
+;;;             (progn
+;;;               (require 'mail-utils)
+;;;               (not (string-equal
+;;;                     (mail-strip-quoted-names
+;;;                      (save-restriction
+;;;                        (narrow-to-region (point-min) delimline)
+;;;                        (mail-fetch-field "From")))
+;;;                     (user-login-name))))
+;;;             (progn
+;;;               (forward-line 1)
+;;;               (insert "Sender: " (user-login-name) "\n")))
            ;; "S:" is an abbreviation for "Subject:".
            (goto-char (point-min))
            (if (re-search-forward "^S:" delimline t)
@@ -400,6 +449,11 @@ the user from the mailer."
            (goto-char (point-min))
            (if (re-search-forward "^Subject:[ \t]*\n" delimline t)
                (replace-match ""))
+           ;; Insert an extra newline if we need it to work around
+           ;; Sun's bug that swallows newlines.
+           (goto-char (1+ delimline))
+           (if (eval mail-mailer-swallows-blank-line)
+               (newline))
            (if mail-interactive
                (save-excursion
                  (set-buffer errbuf)
@@ -409,8 +463,7 @@ the user from the mailer."
                               (if (boundp 'sendmail-program)
                                   sendmail-program
                                 "/usr/lib/sendmail")
-                              nil errbuf nil
-                              "-oi" "-t")
+                              nil errbuf nil "-oi")
                         ;; Always specify who from,
                         ;; since some systems have broken sendmails.
                         (list "-f" (user-login-name))
@@ -421,7 +474,14 @@ the user from the mailer."
                              (list (concat "-oA" mail-alias-file)))
                         ;; These mean "report errors by mail"
                         ;; and "deliver in background".
-                        (if (null mail-interactive) '("-oem" "-odb"))))
+                        (if (null mail-interactive) '("-oem" "-odb"))
+                        ;; Get the addresses from the message
+                        ;; unless this is a resend.
+                        ;; We must not do that for a resend
+                        ;; because we would find the original addresses.
+                        ;; For a resend, include the specific addresses.
+                        (or resend-to-addresses
+                            '("-t"))))
          (if mail-interactive
              (save-excursion
                (set-buffer errbuf)
@@ -521,10 +581,7 @@ the user from the mailer."
                      (if max (narrow-to-region (point-min) max))))))
            ;; Else append to the file directly.
            (write-region
-            ;; Include a blank line before if file already exists.
-
-            (if (file-exists-p (car fcc-list)) (point-min) (1+ (point-min)))
-            (point-max) (car fcc-list) t)))
+            (1+ (point-min)) (point-max) (car fcc-list) t)))
        (setq fcc-list (cdr fcc-list))))
     (kill-buffer tembuf)))
 
@@ -583,13 +640,13 @@ the user from the mailer."
       (progn (mail-position-on-field "to")
             (insert "\nBCC: "))))
 
-(defun mail-fcc ()
+(defun mail-fcc (folder)
   "Add a new FCC field, with file name completion."
-  (interactive)
+  (interactive "FFolder carbon copy: ")
   (expand-abbrev)
   (or (mail-position-on-field "fcc" t) ;Put new field after exiting FCC.
       (mail-position-on-field "to"))
-  (insert "\nFCC: " (read-file-name "Folder carbon copy: ")))
+  (insert "\nFCC: " folder))
 
 (defun mail-position-on-field (field &optional soft)
   (let (end
@@ -617,7 +674,8 @@ the user from the mailer."
   (search-forward (concat "\n" mail-header-separator "\n")))
 \f
 (defun mail-signature (atpoint)
-  "Sign letter with contents of `mail-signature-file'."
+  "Sign letter with contents of the file `~/.signature'.
+Prefix arg means put contents at point."
   (interactive "P")
   (save-excursion
     (or atpoint
@@ -626,7 +684,7 @@ the user from the mailer."
     (end-of-line)
     (or atpoint
        (delete-region (point) (point-max)))
-    (insert "\n\n")
+    (insert "\n\n-- \n")
     (insert-file-contents (expand-file-name "~/.signature"))))
 
 (defun mail-fill-yanked-message (&optional justifyp)
@@ -669,7 +727,10 @@ and don't delete any header fields."
   (interactive "P")
   (if mail-reply-buffer
       (let ((start (point)))
-       (delete-windows-on mail-reply-buffer)
+       ;; If the original message is in another window in the same frame,
+       ;; delete that window to save screen space.
+       ;; t means don't alter other frames.
+       (delete-windows-on mail-reply-buffer t)
        (insert-buffer mail-reply-buffer)
        (if (consp arg)
            nil
@@ -678,7 +739,9 @@ and don't delete any header fields."
                                           mail-indentation-spaces)))
            (if mail-citation-hook
                (run-hooks 'mail-citation-hook)
-             (run-hooks 'mail-yank-hooks))))
+             (if mail-yank-hooks
+                 (run-hooks 'mail-yank-hooks)
+               (mail-indent-citation)))))
        ;; This is like exchange-point-and-mark, but doesn't activate the mark.
        ;; It is cleaner to avoid activation, even though the command
        ;; loop would deactivate the mark because we inserted text.
@@ -785,9 +848,13 @@ 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))
   (switch-to-buffer "*mail*")
-  (setq default-directory (expand-file-name "~/"))
+  (if (file-exists-p (expand-file-name "~/"))
+      (setq default-directory (expand-file-name "~/")))
   (auto-save-mode auto-save-default)
   (mail-mode)
+  ;; Disconnect the buffer from its visited file
+  ;; (in case the user has actually visited a file *mail*).
+;  (set-visited-file-name nil)
   (let (initialized)
     (and (not noerase)
         (or (not (buffer-modified-p))
@@ -813,7 +880,7 @@ The seventh argument ACTIONS is a list of actions to take
           (let ((buffer-read-only nil))
             (erase-buffer)
             (insert-file-contents file-name nil)))
-         (t (error "mail-recover cancelled.")))))
+         (t (error "mail-recover cancelled")))))
 
 ;;;###autoload
 (defun mail-other-window (&optional noerase to subject in-reply-to cc replybuffer sendactions)
@@ -831,16 +898,11 @@ The seventh argument ACTIONS is a list of actions to take
     (pop-to-buffer "*mail*"))
   (mail noerase to subject in-reply-to cc replybuffer sendactions))
 
-
-;;;###autoload
-(define-key ctl-x-map "m" 'mail)
-
-;;;###autoload
-(define-key ctl-x-4-map "m" 'mail-other-window)
-
-;;;###autoload
-(define-key ctl-x-5-map "m" 'mail-other-frame)
-
+;;; Do not execute these when sendmail.el is loaded,
+;;; only in loaddefs.el.
+;;;###autoload (define-key ctl-x-map "m" 'mail)
+;;;###autoload (define-key ctl-x-4-map "m" 'mail-other-window)
+;;;###autoload (define-key ctl-x-5-map "m" 'mail-other-frame)
 
 ;;; Do not add anything but external entries on this page.