]> code.delx.au - gnu-emacs/blobdiff - lisp/mail/sendmail.el
(mail-alias-file): Add autoload cookie.
[gnu-emacs] / lisp / mail / sendmail.el
index ddb671bf641ca40749279d50092d8dcf0c6f9c72..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
@@ -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,12 +411,21 @@ 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))
+           (goto-char (point-min))
+           (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))
@@ -401,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)
@@ -410,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))
@@ -422,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)
@@ -522,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)))
 
@@ -584,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
@@ -618,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
@@ -627,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)
@@ -670,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
@@ -788,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))
@@ -816,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)