Silence byte compiler.
[gnus] / lisp / message.el
index 5166950..21847ac 100644 (file)
@@ -1,6 +1,6 @@
 ;;; message.el --- composing mail and news messages
 
-;; Copyright (C) 1996-2011 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2013 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: mail, news
@@ -268,7 +268,7 @@ This is a list of regexps and regexp matches."
   :type 'sexp)
 
 (defcustom message-ignored-news-headers
-  "^NNTP-Posting-Host:\\|^Xref:\\|^[BGF]cc:\\|^Resent-Fcc:\\|^X-Draft-From:\\|^X-Gnus-Agent-Meta-Information:"
+  "^NNTP-Posting-Host:\\|^Xref:\\|^[BGF]cc:\\|^Resent-Fcc:\\|^X-Draft-From:\\|^X-Gnus-Agent-Meta-Information:\\|^X-Message-SMTP-Method:"
   "*Regexp of headers to be removed unconditionally before posting."
   :group 'message-news
   :group 'message-headers
@@ -600,8 +600,10 @@ Done before generating the new subject of a forward."
   ;; comes back to you (e.g. a mailing-list to which you subscribe, in which
   ;; case you may be removed from the list on the grounds that mail to you
   ;; bounced with a "mailing loop" error).
-  "^Return-receipt\\|^X-Gnus\\|^Gnus-Warning:\\|^>?From \\|^Delivered-To:"
+  "^Return-receipt\\|^X-Gnus\\|^Gnus-Warning:\\|^>?From \\|^Delivered-To:\
+\\|^X-Content-Length:\\|^X-UIDL:"
   "*All headers that match this regexp will be deleted when resending a message."
+  :version "24.4"
   :group 'message-interface
   :link '(custom-manual "(message)Resending")
   :type '(repeat :value-to-internal (lambda (widget value)
@@ -682,14 +684,16 @@ Done before generating the new subject of a forward."
        (t
         (error "Don't know how to send mail.  Please customize `message-send-mail-function'"))))
 
-;; Useful to set in site-init.el
-(defcustom message-send-mail-function
+(defun message-default-send-mail-function ()
   (cond ((eq send-mail-function 'smtpmail-send-it) 'message-smtpmail-send-it)
        ((eq send-mail-function 'feedmail-send-it) 'feedmail-send-it)
        ((eq send-mail-function 'sendmail-query-once) 'sendmail-query-once)
        ((eq send-mail-function 'mailclient-send-it)
         'message-send-mail-with-mailclient)
-       (t (message-send-mail-function)))
+       (t (message-send-mail-function))))
+
+;; Useful to set in site-init.el
+(defcustom message-send-mail-function (message-default-send-mail-function)
   "Function to call to send the current buffer as mail.
 The headers should be delimited by a line whose contents match the
 variable `mail-header-separator'.
@@ -1137,6 +1141,7 @@ probably want to set this variable only for specific groups,
 e.g. using `gnus-posting-styles':
 
   (eval (set (make-local-variable 'message-cite-reply-position) 'above))"
+  :version "24.1"
   :type '(choice (const :tag "Reply inline" 'traditional)
                 (const :tag "Reply above" 'above)
                 (const :tag "Reply below" 'below))
@@ -1373,11 +1378,11 @@ If nil, you might be asked to input the charset."
   :type 'symbol)
 
 (defcustom message-dont-reply-to-names
-  (and (boundp 'rmail-dont-reply-to-names) rmail-dont-reply-to-names)
+  (and (boundp 'mail-dont-reply-to-names) mail-dont-reply-to-names)
   "*Addresses to prune when doing wide replies.
 This can be a regexp or a list of regexps.  Also, a value of nil means
 exclude your own user name only."
-  :version "21.1"
+  :version "24.3"
   :group 'message
   :link '(custom-manual "(message)Wide Reply")
   :type '(choice (const :tag "Yourself" nil)
@@ -1974,10 +1979,13 @@ You must have the \"hashcash\" binary installed, see `hashcash-path'."
 (autoload 'nndraft-request-associate-buffer "nndraft")
 (autoload 'nndraft-request-expire-articles "nndraft")
 (autoload 'nnvirtual-find-group-art "nnvirtual")
-(autoload 'rmail-dont-reply-to "mail-utils")
 (autoload 'rmail-msg-is-pruned "rmail")
 (autoload 'rmail-output "rmailout")
 
+;; Emacs < 24.1 do not have mail-dont-reply-to
+(unless (fboundp 'mail-dont-reply-to)
+  (defalias 'mail-dont-reply-to 'rmail-dont-reply-to))
+
 \f
 
 ;;;
@@ -2644,7 +2652,7 @@ Point is left at the beginning of the narrowed-to region."
   (interactive)
   (let ((start (point)))
     (message-skip-to-next-address)
-    (kill-region start (point))))
+    (kill-region start (if (bolp) (1- (point)) (point)))))
 
 
 (autoload 'Info-goto-node "info")
@@ -3098,94 +3106,100 @@ M-RET    `message-newline-and-reformat' (break the line and reformat)."
 (defun message-goto-to ()
   "Move point to the To header."
   (interactive)
+  (push-mark)
   (message-position-on-field "To"))
 
 (defun message-goto-from ()
   "Move point to the From header."
   (interactive)
+  (push-mark)
   (message-position-on-field "From"))
 
 (defun message-goto-subject ()
   "Move point to the Subject header."
   (interactive)
+  (push-mark)
   (message-position-on-field "Subject"))
 
 (defun message-goto-cc ()
   "Move point to the Cc header."
   (interactive)
+  (push-mark)
   (message-position-on-field "Cc" "To"))
 
 (defun message-goto-bcc ()
   "Move point to the Bcc  header."
   (interactive)
+  (push-mark)
   (message-position-on-field "Bcc" "Cc" "To"))
 
 (defun message-goto-fcc ()
   "Move point to the Fcc header."
   (interactive)
+  (push-mark)
   (message-position-on-field "Fcc" "To" "Newsgroups"))
 
 (defun message-goto-reply-to ()
   "Move point to the Reply-To header."
   (interactive)
+  (push-mark)
   (message-position-on-field "Reply-To" "Subject"))
 
 (defun message-goto-newsgroups ()
   "Move point to the Newsgroups header."
   (interactive)
+  (push-mark)
   (message-position-on-field "Newsgroups"))
 
 (defun message-goto-distribution ()
   "Move point to the Distribution header."
   (interactive)
+  (push-mark)
   (message-position-on-field "Distribution"))
 
 (defun message-goto-followup-to ()
   "Move point to the Followup-To header."
   (interactive)
+  (push-mark)
   (message-position-on-field "Followup-To" "Newsgroups"))
 
 (defun message-goto-mail-followup-to ()
   "Move point to the Mail-Followup-To header."
   (interactive)
+  (push-mark)
   (message-position-on-field "Mail-Followup-To" "To"))
 
 (defun message-goto-keywords ()
   "Move point to the Keywords header."
   (interactive)
+  (push-mark)
   (message-position-on-field "Keywords" "Subject"))
 
 (defun message-goto-summary ()
   "Move point to the Summary header."
   (interactive)
+  (push-mark)
   (message-position-on-field "Summary" "Subject"))
 
-(eval-when-compile
-  (defmacro message-called-interactively-p (kind)
-    (condition-case nil
-       (progn
-         (eval '(called-interactively-p 'any))
-         ;; Emacs >=23.2
-         `(called-interactively-p ,kind))
-      ;; Emacs <23.2
-      (wrong-number-of-arguments '(called-interactively-p))
-      ;; XEmacs
-      (void-function '(interactive-p)))))
-
 (defun message-goto-body ()
   "Move point to the beginning of the message body."
   (interactive)
-  (when (and (message-called-interactively-p 'any)
+  (when (and (gmm-called-interactively-p 'any)
             (looking-at "[ \t]*\n"))
     (expand-abbrev))
+  (push-mark)
   (goto-char (point-min))
   (or (search-forward (concat "\n" mail-header-separator "\n") nil t)
       (search-forward-regexp "[^:]+:\\([^\n]\\|\n[ \t]\\)+\n\n" nil t)))
 
 (defun message-in-body-p ()
   "Return t if point is in the message body."
-  (let ((body (save-excursion (message-goto-body))))
-    (>= (point) body)))
+  (>= (point)
+      (save-excursion
+       (goto-char (point-min))
+       (or (search-forward (concat "\n" mail-header-separator "\n") nil t)
+           (search-forward-regexp "[^:]+:\\([^\n]\\|\n[ \t]\\)+\n\n" nil t))
+       (point))))
 
 (defun message-goto-eoh ()
   "Move point to the end of the headers."
@@ -3198,6 +3212,7 @@ M-RET    `message-newline-and-reformat' (break the line and reformat)."
 If there is no signature in the article, go to the end and
 return nil."
   (interactive)
+  (push-mark)
   (goto-char (point-min))
   (if (re-search-forward message-signature-separator nil t)
       (forward-line 1)
@@ -3315,11 +3330,33 @@ or in the synonym headers, defined by `message-header-synonyms'."
 (defun message-insert-newsgroups ()
   "Insert the Newsgroups header from the article being replied to."
   (interactive)
-  (when (and (message-position-on-field "Newsgroups")
-            (mail-fetch-field "newsgroups")
-            (not (string-match "\\` *\\'" (mail-fetch-field "newsgroups"))))
-    (insert ","))
-  (insert (or (message-fetch-reply-field "newsgroups") "")))
+  (let ((old-newsgroups (mail-fetch-field "newsgroups"))
+       (new-newsgroups (message-fetch-reply-field "newsgroups"))
+       (first t)
+       insert-newsgroups)
+    (message-position-on-field "Newsgroups")
+    (cond
+     ((not new-newsgroups)
+      (error "No Newsgroups to insert"))
+     ((not old-newsgroups)
+      (insert new-newsgroups))
+     (t
+      (setq new-newsgroups (split-string new-newsgroups "[, ]+")
+           old-newsgroups (split-string old-newsgroups "[, ]+"))
+      (dolist (group new-newsgroups)
+       (unless (member group old-newsgroups)
+         (push group insert-newsgroups)))
+      (if (null insert-newsgroups)
+         (error "Newgroup%s already in the header"
+                (if (> (length new-newsgroups) 1)
+                    "s" ""))
+       (when old-newsgroups
+         (setq first nil))
+       (dolist (group insert-newsgroups)
+         (unless first
+           (insert ","))
+         (setq first nil)
+         (insert group)))))))
 
 \f
 
@@ -3821,7 +3858,9 @@ prefix, and don't delete any headers."
   (interactive "P")
   ;; eval the let forms contained in message-cite-style
   (eval
-   `(let ,message-cite-style
+   `(let ,(if (symbolp message-cite-style)
+             (symbol-value message-cite-style)
+           message-cite-style)
       (message--yank-original-internal ',arg))))
 
 (defun message-yank-buffer (buffer)
@@ -3837,7 +3876,7 @@ prefix, and don't delete any headers."
     (save-current-buffer
       (dolist (buffer (buffer-list t))
        (set-buffer buffer)
-       (when (and (eq major-mode 'message-mode)
+       (when (and (derived-mode-p 'message-mode)
                   (null message-sent-message-via))
          (push (buffer-name buffer) buffers))))
     (nreverse buffers)))
@@ -4037,28 +4076,6 @@ This function strips off the signature from the original message."
        (forward-char -1)
        nil))))
 
-(defun message-remove-signature ()
-  "Remove the signature from the text between point and mark.
-The text will also be indented the normal way."
-  (save-excursion
-    (let ((start (point))
-         mark)
-      (if (not (re-search-forward message-signature-separator (mark t) t))
-         ;; No signature here, so we just indent the cited text.
-         (message-indent-citation)
-       ;; Find the last non-empty line.
-       (forward-line -1)
-       (while (looking-at "[ \t]*$")
-         (forward-line -1))
-       (forward-line 1)
-       (setq mark (set-marker (make-marker) (point)))
-       (goto-char start)
-       (message-indent-citation)
-       ;; Enable undoing the deletion.
-       (undo-boundary)
-       (delete-region mark (mark t))
-       (set-marker mark nil)))))
-
 \f
 
 ;;;
@@ -4453,7 +4470,7 @@ This function could be useful in `message-setup-hook'."
        ;; A simple function.
        ((functionp action)
        (funcall action))
-       ;; Something to be evaled.
+       ;; Something to be evalled.
        (t
        (eval action))))))
 
@@ -4520,8 +4537,9 @@ This function could be useful in `message-setup-hook'."
              (end-of-line)
              (insert (format " (%d/%d)" n total))
              (widen)
-              (funcall (or message-send-mail-real-function
-                           message-send-mail-function)))
+             (if message-send-mail-real-function
+                 (funcall message-send-mail-real-function)
+               (message-multi-smtp-send-mail)))
            (setq n (+ n 1))
            (setq p (pop plist))
            (erase-buffer)))
@@ -4675,8 +4693,9 @@ If you always want Gnus to send messages in one piece, set
 ")))
              (progn
                (message "Sending via mail...")
-               (funcall (or message-send-mail-real-function
-                            message-send-mail-function)))
+               (if message-send-mail-real-function
+                   (funcall message-send-mail-real-function)
+                 (message-multi-smtp-send-mail)))
            (message-send-mail-partially))
          (setq options message-options))
       (kill-buffer tembuf))
@@ -4685,6 +4704,28 @@ If you always want Gnus to send messages in one piece, set
     (push 'mail message-sent-message-via)))
 
 (defvar sendmail-program)
+(defvar smtpmail-smtp-user)
+
+(defun message-multi-smtp-send-mail ()
+  "Send the current buffer to `message-send-mail-function'.
+Or, if there's a header that specifies a different method, use
+that instead."
+  (let ((method (message-field-value "X-Message-SMTP-Method")))
+    (if (not method)
+       (funcall message-send-mail-function)
+      (message-remove-header "X-Message-SMTP-Method")
+      (setq method (split-string method))
+      (cond
+       ((equal (car method) "sendmail")
+       (message-send-mail-with-sendmail))
+       ((equal (car method) "smtp")
+       (require 'smtpmail)
+       (let ((smtpmail-smtp-server (nth 1 method))
+             (smtpmail-smtp-service (nth 2 method))
+             (smtpmail-smtp-user (or (nth 3 method) smtpmail-smtp-user)))
+         (message-smtpmail-send-it)))
+       (t
+       (error "Unknown method %s" method))))))
 
 (defun message-send-mail-with-sendmail ()
   "Send off the prepared buffer with sendmail."
@@ -4841,9 +4882,7 @@ Do not use this for anything important, it is cryptographically weak."
   (require 'sha1)
   (let (sha1-maximum-internal-length)
     (sha1 (concat (message-unique-id)
-                 (format "%x%x%x" (random)
-                         (progn (random t) (random))
-                         (random))
+                 (format "%x%x%x" (random) (random) (random))
                  (prin1-to-string (recent-keys))
                  (prin1-to-string (garbage-collect))))))
 
@@ -5546,7 +5585,6 @@ In posting styles use `(\"Expires\" (make-expires-date 30))'."
 ;; You might for example insert a "." somewhere (not next to another dot
 ;; or string boundary), or modify the "fsf" string.
 (defun message-unique-id ()
-  (random t)
   ;; Don't use microseconds from (current-time), they may be unsupported.
   ;; Instead we use this randomly inited counter.
   (setq message-unique-id-char
@@ -5807,12 +5845,6 @@ give as trustworthy answer as possible."
       (concat system-name
              ".i-did-not-set--mail-host-address--so-tickle-me")))))
 
-(defun message-make-host-name ()
-  "Return the name of the host."
-  (let ((fqdn (message-make-fqdn)))
-    (string-match "^[^.]+\\." fqdn)
-    (substring fqdn 0 (1- (match-end 0)))))
-
 (defun message-make-domain ()
   "Return the domain name."
   (or mail-host-address
@@ -6129,20 +6161,13 @@ Headers already prepared in the buffer are not modified."
     (while (and (not (= (point) end))
                (or (not (eq char ?,))
                    quoted))
-      (skip-chars-forward "^,\"" (point-max))
+      (skip-chars-forward "^,\"" end)
       (when (eq (setq char (following-char)) ?\")
        (setq quoted (not quoted)))
       (unless (= (point) end)
        (forward-char 1)))
     (skip-chars-forward " \t\n")))
 
-(defun message-fill-address (header value)
-  (insert (capitalize (symbol-name header))
-         ": "
-         (if (consp value) (car value) value)
-         "\n")
-  (message-fill-field-address))
-
 (defun message-split-line ()
   "Split current line, moving portion beyond point vertically down.
 If the current line has `message-yank-prefix', insert it on the new line."
@@ -6173,17 +6198,22 @@ If the current line has `message-yank-prefix', insert it on the new line."
       (point-max))))
 
 (defun message-fill-field-address ()
-  (while (not (eobp))
-    (message-skip-to-next-address)
-    (let (last)
-      (if (and (> (current-column) 78)
-              last)
-         (progn
-           (save-excursion
-             (goto-char last)
-             (insert "\n\t"))
-           (setq last (1+ (point))))
-       (setq last (1+ (point)))))))
+  (let (end last)
+    (while (not end)
+      (message-skip-to-next-address)
+      (cond ((bolp)
+            (end-of-line 0)
+            (setq end 1))
+           ((eobp)
+            (setq end 0)))
+      (when (and (> (current-column) 78)
+                last)
+       (save-excursion
+         (goto-char last)
+         (delete-char (- (skip-chars-backward " \t")))
+         (insert "\n\t")))
+      (setq last (point)))
+    (forward-line end)))
 
 (defun message-fill-field-general ()
   (let ((begin (point))
@@ -6213,7 +6243,7 @@ If the current line has `message-yank-prefix', insert it on the new line."
 When sending via news, also check that the REFERENCES are less
 than 988 characters long, and if they are not, trim them until
 they are."
-  ;; 21 is the number suggested by USEAGE.
+  ;; 21 is the number suggested by USAGE.
   (let ((maxcount 21)
        (count 0)
        (cut 2)
@@ -6734,11 +6764,16 @@ The function is called with one parameter, a cons cell ..."
                               ", "))
            mct (message-fetch-field "mail-copies-to")
            author (or (message-fetch-field "mail-reply-to")
-                      (message-fetch-field "reply-to")
-                      (message-fetch-field "from")
-                      "")
+                      (message-fetch-field "reply-to"))
            mft (and message-use-mail-followup-to
-                    (message-fetch-field "mail-followup-to"))))
+                    (message-fetch-field "mail-followup-to")))
+      ;; Make sure this message goes to the author if this is a wide
+      ;; reply, since Reply-To address may be a list address a mailing
+      ;; list server added.
+      (when (and wide author)
+       (setq cc (concat author ", " cc)))
+      (when (or wide (not author))
+       (setq author (or (message-fetch-field "from") ""))))
 
     ;; Handle special values of Mail-Copies-To.
     (when mct
@@ -6804,9 +6839,9 @@ want to get rid of this query permanently.")))
       ;; Squeeze whitespace.
       (while (string-match "[ \t][ \t]+" recipients)
        (setq recipients (replace-match " " t t recipients)))
-      ;; Remove addresses that match `rmail-dont-reply-to-names'.
-      (let ((rmail-dont-reply-to-names (message-dont-reply-to-names)))
-       (setq recipients (rmail-dont-reply-to recipients)))
+      ;; Remove addresses that match `mail-dont-reply-to-names'.
+      (let ((mail-dont-reply-to-names (message-dont-reply-to-names)))
+       (setq recipients (mail-dont-reply-to recipients)))
       ;; Perhaps "Mail-Copies-To: never" removed the only address?
       (if (string-equal recipients "")
          (setq recipients author))
@@ -7385,12 +7420,13 @@ Optional DIGEST will use digest to forward."
        (dolist (elem ignored)
          (message-remove-header elem t))))))
 
-(defun message-forward-make-body-mime (forward-buffer)
+(defun message-forward-make-body-mime (forward-buffer &optional beg end)
   (let ((b (point)))
     (insert "\n\n<#part type=message/rfc822 disposition=inline raw=t>\n")
     (save-restriction
       (narrow-to-region (point) (point))
-      (mml-insert-buffer forward-buffer)
+      (insert-buffer-substring forward-buffer beg end)
+      (mml-quote-region (point-min) (point-max))
       (goto-char (point-min))
       (when (looking-at "From ")
        (replace-match "X-From-Line: "))
@@ -7571,7 +7607,7 @@ is for the internal use."
   (message "Resending message to %s..." address)
   (save-excursion
     (let ((cur (current-buffer))
-         beg)
+         gcc beg)
       ;; We first set up a normal mail buffer.
       (unless (message-mail-user-agent)
        (set-buffer (get-buffer-create " *message resend*"))
@@ -7584,6 +7620,8 @@ is for the internal use."
       ;; Insert our usual headers.
       (message-generate-headers '(From Date To Message-ID))
       (message-narrow-to-headers)
+      (when (setq gcc (mail-fetch-field "gcc" nil t))
+       (message-remove-header "gcc"))
       ;; Remove X-Draft-From header etc.
       (message-remove-header message-ignored-mail-headers t)
       ;; Rename them all to "Resent-*".
@@ -7625,6 +7663,10 @@ is for the internal use."
            message-generate-hashcash
            rfc2047-encode-encoded-words)
        (message-send-mail))
+      (when gcc
+       (message-goto-eoh)
+       (insert "Gcc: " gcc "\n"))
+      (run-hooks 'message-sent-hook)
       (kill-buffer (current-buffer)))
     (message "Resending message to %s...done" address)))
 
@@ -7782,7 +7824,7 @@ Setter function for custom variables."
                              'message-tool-bar-retro)
   "Specifies the message mode tool bar.
 
-It can be either a list or a symbol refering to a list.  See
+It can be either a list or a symbol referring to a list.  See
 `gmm-tool-bar-from-list' for the format of the list.  The
 default key map is `message-mode-map'.
 
@@ -8134,7 +8176,7 @@ regexp VARSTR."
   (if (fboundp 'mail-abbrevs-setup)
       (let ((minibuffer-setup-hook 'mail-abbrevs-setup)
            (minibuffer-local-map message-minibuffer-local-map))
-       (flet ((mail-abbrev-in-expansion-header-p nil t))
+       (gmm-flet ((mail-abbrev-in-expansion-header-p nil t))
          (read-from-minibuffer prompt initial-contents)))
     (let ((minibuffer-setup-hook 'mail-abbrev-minibuffer-setup-hook)
          (minibuffer-local-map message-minibuffer-local-map))