]> code.delx.au - gnu-emacs/blobdiff - lisp/mail/sendmail.el
Update copyright year to 2016
[gnu-emacs] / lisp / mail / sendmail.el
index 331754fb1b5305e52dc286af9b4c43f00dba4ec3..5ab5bd9a2cda6ac43e1db985be731c1d949ce680 100644 (file)
@@ -1,9 +1,9 @@
 ;;; sendmail.el --- mail sending commands for Emacs
 
-;; Copyright (C) 1985-1986, 1992-1996, 1998, 2000-2012
-;;   Free Software Foundation, Inc.
+;; Copyright (C) 1985-1986, 1992-1996, 1998, 2000-2016 Free Software
+;; Foundation, Inc.
 
-;; Maintainer: FSF
+;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: mail
 
 ;; This file is part of GNU Emacs.
@@ -58,7 +58,7 @@
 (defcustom mail-from-style 'default
   "Specifies how \"From:\" fields look.
 
-If `nil', they contain just the return address like:
+If nil, they contain just the return address like:
        king@grassland.com
 If `parens', they look like:
        king@grassland.com (Elvis Parsley)
@@ -243,15 +243,14 @@ Used by `mail-yank-original' via `mail-indent-citation'."
   :type 'integer
   :group 'sendmail)
 
-;; FIXME make it really obsolete.
 (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
 text as modified.
-
 This is a normal hook, misnamed for historical reasons.
-It is semi-obsolete and mail agents should no longer use it.")
+It is obsolete and mail agents should no longer use it.")
+(make-obsolete-variable 'mail-yank-hooks 'mail-citation-hook "19.34")
 
 ;;;###autoload
 (defcustom mail-citation-hook nil
@@ -526,31 +525,33 @@ This also saves the value of `send-mail-function' via Customize."
          ;; Query the user.
          (with-temp-buffer
            (rename-buffer "*Emacs Mail Setup Help*" t)
-           (insert "\
+           (insert (substitute-command-keys "\
  Emacs is about to send an email message, but it has not been
  configured for sending email.  To tell Emacs how to send email:
 
- - Type `"
+ - Type `")
                    (propertize "mail client" 'face 'bold)
-                   "' to start your default email client and
-   pass it the message text.\n\n")
+                   (substitute-command-keys "\
+' to start your default email client and
+   pass it the message text.\n\n"))
            (and sendmail-program
                 (executable-find sendmail-program)
-                (insert "\
- - Type `"
+                (insert (substitute-command-keys "\
+ - Type `")
                         (propertize "transport" 'face 'bold)
-                        "' to invoke the system's mail transport agent
-   (the `"
+                        (substitute-command-keys "\
+' to invoke the system's mail transport agent
+   (the `")
                         sendmail-program
-                        "' program).\n\n"))
-           (insert "\
- - Type `"
+                        (substitute-command-keys "' program).\n\n")))
+           (insert (substitute-command-keys "\
+ - Type `")
                    (propertize "smtp" 'face 'bold)
-                   "' to send mail directly to an \"outgoing mail\" server.
+                   (substitute-command-keys "' to send mail directly to an \"outgoing mail\" server.
    (Emacs may prompt you for SMTP settings).
 
  Emacs will record your selection and will use it thereafter.
- To change it later, customize the option `send-mail-function'.\n")
+ To change it later, customize the option `send-mail-function'.\n"))
            (goto-char (point-min))
            (display-buffer (current-buffer))
            (let ((completion-ignore-case t))
@@ -908,6 +909,8 @@ the user from the mailer."
                 (concat "\\(?:[[:space:];,]\\|\\`\\)"
                         (regexp-opt mail-mailing-lists t)
                         "\\(?:[[:space:];,]\\|\\'\\)"))))
+        (mail-combine-fields "To")
+        (mail-combine-fields "CC")
        ;; If there are mailing lists defined
        (when ml
          (save-excursion
@@ -1076,6 +1079,71 @@ This function does not perform RFC2047 encoding."
                 (goto-char fullname-start))))
           (insert ")\n")))))
 
+(defun mail-combine-fields (field)
+  "Offer to combine all FIELD fields in buffer into one FIELD field.
+If this finds multiple FIELD fields, it asks the user whether
+to combine them into one, and does so if the user says y."
+  (let ((search-pattern (format "^%s[ \t]*:" field))
+        first-to-end
+        query-asked
+        query-answer
+        (old-point (point))
+        (old-max (point-max)))
+    (save-excursion
+      (save-restriction
+        (goto-char (point-min))
+        (narrow-to-region (point-min) (mail-header-end))
+        ;; Find the first FIELD field and record where it ends.
+        (when (re-search-forward search-pattern nil t)
+          (forward-line 1)
+          (re-search-forward "^[^ \t]" nil t)
+          (beginning-of-line)
+          (setq first-to-end (point-marker))
+          (set-marker-insertion-type first-to-end t)
+          ;; Find each following FIELD field
+          ;; and combine it with the first FIELD field.
+          (while (re-search-forward search-pattern nil t)
+            ;; For the second FIELD field, ask user to
+            ;; approve combining them.
+            ;; But if the user refuse to combine them, signal error.
+            (unless query-asked
+              (save-restriction
+                ;; This is just so the screen doesn't change.
+                (narrow-to-region (point-min) old-max)
+                (goto-char old-point)
+                (setq query-asked t)
+                (if (y-or-n-p (format "Message contains multiple %s fields.  Combine? " field))
+                    (setq query-answer t))))
+            (when query-answer
+              (let ((this-to-start (line-beginning-position))
+                    this-to-end
+                    this-to)
+                (forward-line 1)
+                (re-search-forward "^[^ \t]" nil t)
+                (beginning-of-line)
+                (setq this-to-end (point))
+                ;; Get the text of this FIELD field.
+                (setq this-to (buffer-substring this-to-start this-to-end))
+                ;; Delete it.
+                (delete-region this-to-start this-to-end)
+                (save-excursion
+                  ;; Put a comma after the first FIELD field.
+                  (goto-char first-to-end)
+                  (forward-char -1)
+                  (insert ",")
+                  ;; Copy this one after it.
+                  (goto-char first-to-end)
+                  (save-excursion
+                    (insert this-to))
+                  ;; Replace the FIELD: with spaces.
+                  (looking-at search-pattern)
+                  ;; Try to preserve alignment of contents of the field
+                  (let ((prefix-length (length (match-string 0))))
+                    (replace-match " ")
+                    (dotimes (i (1- prefix-length))
+                      (insert " ")))))))
+          (set-marker first-to-end nil))))))
+
 (defun mail-encode-header (beg end)
   "Encode the mail header between BEG and END according to RFC2047.
 Return non-nil if and only if some part of the header is encoded."
@@ -1115,6 +1183,7 @@ external program defined by `sendmail-program'."
   (let ((errbuf (if mail-interactive
                    (generate-new-buffer " sendmail errors")
                  0))
+        (error nil)
        (tembuf (generate-new-buffer " sendmail temp"))
        (multibyte enable-multibyte-characters)
        (case-fold-search nil)
@@ -1279,10 +1348,13 @@ external program defined by `sendmail-program'."
                     (exit-value (apply 'call-process-region args)))
                (cond ((or (null exit-value) (eq 0 exit-value)))
                      ((numberp exit-value)
+                       (setq error t)
                       (error "Sending...failed with exit value %d" exit-value))
                      ((stringp exit-value)
+                       (setq error t)
                       (error "Sending...terminated by signal: %s" exit-value))
                      (t
+                       (setq error t)
                       (error "SENDMAIL-SEND-IT -- fall through: %S" exit-value))))
            (or fcc-was-found
                (error "No recipients")))
@@ -1291,12 +1363,15 @@ external program defined by `sendmail-program'."
                (goto-char (point-min))
                (while (re-search-forward "\n\n* *" nil t)
                  (replace-match "; "))
-               (if (not (zerop (buffer-size)))
-                   (error "Sending...failed to %s"
-                          (buffer-substring (point-min) (point-max)))))))
+               (unless (zerop (buffer-size))
+                  (setq error t)
+                  (error "Sending...failed to %s"
+                         (buffer-substring (point-min) (point-max)))))))
       (kill-buffer tembuf)
-      (if (bufferp errbuf)
-         (kill-buffer errbuf)))))
+      (when (buffer-live-p errbuf)
+        (if error
+            (switch-to-buffer-other-window errbuf)
+          (kill-buffer errbuf))))))
 
 (autoload 'rmail-output-to-rmail-buffer "rmailout")
 
@@ -1494,6 +1569,10 @@ just append to the file, in Babyl format if necessary."
            (insert "\nMail-Followup-To: "))))
 
 (defun mail-position-on-field (field &optional soft)
+  "Move to the end of the contents of header field FIELD.
+If there is no such header, insert one, unless SOFT is non-nil.
+If there are multiple FIELD fields, this goes to the first.
+Returns non-nil if FIELD was originally present."
   (let (end
        (case-fold-search t))
     (setq end (mail-header-end))
@@ -1968,7 +2047,7 @@ you can move to one of them and type C-c C-c to recover that one."
             (if (not (yes-or-no-p
                       (format "Recover mail draft from auto save file %s? "
                               file-name)))
-                (error "mail-recover cancelled")
+                (error "mail-recover canceled")
               (let ((buffer-read-only nil)
                     (buffer-coding buffer-file-coding-system)
                     ;; Auto-save files are written in internal
@@ -1999,7 +2078,6 @@ you can move to one of them and type C-c C-c to recover that one."
 
 ;; Local Variables:
 ;; byte-compile-dynamic: t
-;; coding: utf-8
 ;; End:
 
 ;;; sendmail.el ends here