;;; Code:
-(eval-when-compile (require 'cl))
-(eval-when-compile (require 'smtp))
+(eval-when-compile
+ (require 'cl)
+ (require 'smtp)
+ (defvar gnus-list-identifiers)) ; gnus-sum is required where necessary
(require 'mailheader)
(require 'nnheader)
-(require 'easymenu)
-(if (string-match "XEmacs\\|Lucid" emacs-version)
- (require 'mail-abbrevs)
- (require 'mailabbrev))
+;; This is apparently necessary even though things are autoloaded:
+(if (featurep 'xemacs)
+ (require 'mail-abbrevs))
(require 'mime-edit)
(eval-when-compile (require 'static))
;; Avoid byte-compile warnings.
(eval-when-compile
(require 'mail-parse)
- (require 'mm-bodies)
- (require 'mm-encode)
- (require 'mml)
- )
+ (require 'mml))
(defgroup message '((user-mail-address custom-variable)
(user-full-name custom-variable))
Don't touch this variable unless you really know what you're doing.
Checks include subject-cmsg multiple-headers sendsys message-id from
-long-lines control-chars size new-text redirected-followup signature
-approved sender empty empty-headers message-id from subject
-shorten-followup-to existing-newsgroups buffer-file-name unchanged
-newsgroups."
- :group 'message-news)
+long-lines control-chars size new-text quoting-style
+redirected-followup signature approved sender empty empty-headers
+message-id from subject shorten-followup-to existing-newsgroups
+buffer-file-name unchanged newsgroups."
+ :group 'message-news
+ :type '(repeat sexp))
(defcustom message-required-news-headers
'(From Newsgroups Subject Date Message-ID
:group 'message-headers
:type 'regexp)
-(defcustom message-ignored-supersedes-headers "^Path:\\|^Date\\|^NNTP-Posting-Host:\\|^Xref:\\|^Lines:\\|^Received:\\|^X-From-Line:\\|^X-Trace:\\|^X-Complaints-To:\\|Return-Path:\\|^Supersedes:"
+(defcustom message-ignored-supersedes-headers "^Path:\\|^Date\\|^NNTP-Posting-Host:\\|^Xref:\\|^Lines:\\|^Received:\\|^X-From-Line:\\|^X-Trace:\\|^X-Complaints-To:\\|Return-Path:\\|^Supersedes:\\|^NNTP-Posting-Date:\\|^X-Trace:\\|^X-Complaints-To:"
"*Header lines matching this regexp will be deleted before posting.
It's best to delete old Path and Date headers before posting to avoid
any confusion."
:group 'message-interface
:type 'regexp)
-(defcustom message-forward-ignored-headers "Content-Transfer-Encoding"
+(defcustom message-forward-ignored-headers "^Content-Transfer-Encoding:\\|^X-Gnus"
"*All headers that match this regexp will be deleted when forwarding a message."
:group 'message-forwarding
:type '(choice (const :tag "None" nil)
:group 'message-insertion
:type 'regexp)
+(defcustom message-cite-prefix-regexp
+ ;; ?-, ?_ or ?. MUST NOT be in syntax entry w.
+ "[ \t]*\\(\\(\\w\\|[-_.]\\)+>+[ \t]*\\|[]>»|:}+][ \t]*\\)+"
+ "*Regexp matching the longest possible citation prefix on a line."
+ :group 'message-insertion
+ :type 'regexp)
+
(defcustom message-cancel-message "I am canceling my own article.\n"
"Message to be inserted in the cancel message."
:group 'message-interface
(defvar message-user-agent nil
"String of the form of PRODUCT/VERSION. Used for User-Agent header field.")
-;; Ignore errors in case this is used in Emacs 19.
-;; Don't use ignore-errors because this is copied into loaddefs.el.
+(static-when (boundp 'MULE)
+ (require 'reporter));; `define-mail-user-agent' is here.
+
;;;###autoload
-(ignore-errors
- (define-mail-user-agent 'message-user-agent
- 'message-mail 'message-send-and-exit
- 'message-kill-buffer 'message-send-hook))
+(define-mail-user-agent 'message-user-agent
+ 'message-mail 'message-send-and-exit
+ 'message-kill-buffer 'message-send-hook)
(defvar message-mh-deletable-headers '(Message-ID Date Lines Sender)
"If non-nil, delete the deletable headers before feeding to mh.")
:type '(choice (const :tag "unique" unique)
(const :tag "unsent" unsent)))
-(defcustom message-default-charset nil
+(defcustom message-default-charset
+ (and (featurep 'xemacs) (not (featurep 'mule)) 'iso-8859-1)
"Default charset used in non-MULE XEmacsen."
:group 'message
:type 'symbol)
-(defcustom message-dont-reply-to-names rmail-dont-reply-to-names
+(defcustom message-dont-reply-to-names
+ (and (boundp 'rmail-dont-reply-to-names) rmail-dont-reply-to-names)
"*A regexp specifying names to prune when doing wide replies.
A value of nil means exclude your own name only."
:group 'message
(setq message-font-lock-last-position nil)))
(defvar message-font-lock-keywords-1
- (let ((content "[ \t]*\\(.+\\(\n[ \t].*\\)*\\)"))
+ (let ((content "[ \t]*\\(.+\\(\n[ \t].*\\)*\\)\n?"))
`((,(concat "^\\([Tt]o:\\)" content)
(1 'message-header-name-face)
(2 'message-header-to-face nil t))
(defvar message-font-lock-keywords-2
(append message-font-lock-keywords-1
- '((message-font-lock-cited-text-matcher
+ `((message-font-lock-cited-text-matcher
(1 'message-cited-text-face)
(2 'message-cited-text-face))
- ("<#/?\\(multipart\\|part\\|external\\).*>"
+ (,(concat "^\\(" message-cite-prefix-regexp "\\).*")
+ (0 'message-cited-text-face))
+ ("<#/?\\(multipart\\|part\\|external\\|mml\\).*>"
(0 'message-mml-face)))))
(defvar message-font-lock-keywords message-font-lock-keywords-2
(defcustom message-send-mail-partially-limit 1000000
"The limitation of messages sent as message/partial.
-The lower bound of message size in characters, beyond which the message
+The lower bound of message size in characters, beyond which the message
should be sent in several parts. If it is nil, the size is unlimited."
:group 'message-buffers
:type '(choice (const :tag "unlimited" nil)
(integer 1000000)))
+(defcustom message-alternative-emails nil
+ "A regexp to match the alternative email addresses.
+The first matched address (not primary one) is used in the From field."
+ :group 'message-headers
+ :type '(choice (const :tag "Always use primary" nil)
+ regexp))
+
;;; Internal variables.
+(defvar message-sending-message "Sending...")
(defvar message-buffer-list nil)
(defvar message-this-is-news nil)
(defvar message-this-is-mail nil)
(User-Agent))
"Alist used for formatting headers.")
+(defvar message-options nil
+ "Some saved answers when sending message.")
+
(eval-and-compile
(autoload 'message-setup-toolbar "messagexmas")
(autoload 'mh-new-draft-name "mh-comp")
(autoload 'gnus-request-post "gnus-int")
(autoload 'gnus-copy-article-buffer "gnus-msg")
(autoload 'gnus-alive-p "gnus-util")
- (autoload 'gnus-list-identifiers "gnus-sum")
+ (autoload 'gnus-group-name-charset "gnus-group")
(autoload 'rmail-output "rmail")
(autoload 'mu-cite-original "mu-cite"))
`(delete-region (progn (beginning-of-line) (point))
(progn (forward-line ,(or n 1)) (point))))
+(defun message-unquote-tokens (elems)
+ "Remove double quotes (\") from strings in list."
+ (mapcar (lambda (item)
+ (while (string-match "^\\(.*\\)\"\\(.*\\)$" item)
+ (setq item (concat (match-string 1 item)
+ (match-string 2 item))))
+ item)
+ elems))
+
(defun message-tokenize-header (header &optional separator)
"Split HEADER into a list of header elements.
-\",\" is used as the separator."
+SEPARATOR is a string of characters to be used as separators. \",\"
+is used by default."
(if (not header)
nil
(let ((regexp (format "[%s]+" (or separator ",")))
((and (eq (char-after) ?\))
(not quoted))
(setq paren nil))))
- (nreverse elems)))))
+ (nreverse elems)))))
(defun message-mail-file-mbox-p (file)
"Say whether FILE looks like a Unix mbox file."
(when value
(while (string-match "\n[\t ]+" value)
(setq value (replace-match " " t t value)))
- ;; We remove all text props.
- (format "%s" value))))
+ (set-text-properties 0 (length value) nil value)
+ value)))
(defun message-narrow-to-field ()
"Narrow the buffer to the header on the current line."
(defun message-strip-list-identifiers (subject)
"Remove list identifiers in `gnus-list-identifiers'."
+ (require 'gnus-sum) ; for gnus-list-identifiers
(let ((regexp (if (stringp gnus-list-identifiers)
gnus-list-identifiers
(mapconcat 'identity gnus-list-identifiers " *\\|"))))
- (if (string-match (concat "\\(\\(\\(Re: +\\)?\\(" regexp
+ (if (string-match (concat "\\(\\(\\(Re: +\\)?\\(" regexp
" *\\)\\)+\\(Re: +\\)?\\)") subject)
(concat (substring subject 0 (match-beginning 1))
(or (match-string 3 subject)
(error "Face %s not configured for %s mode" face mode-name)))
"")
facemenu-remove-face-function t)
- (make-local-variable 'paragraph-separate)
- (make-local-variable 'paragraph-start)
- ;; `-- ' precedes the signature. `-----' appears at the start of the
- ;; lines that delimit forwarded messages.
- ;; Lines containing just >= 3 dashes, perhaps after whitespace,
- ;; are also sometimes used and should be separators.
- (setq paragraph-start
- (concat (regexp-quote mail-header-separator)
- "$\\|[ \t]*[a-z0-9A-Z]*>+[ \t]*$\\|[ \t]*$\\|"
- "-- $\\|---+$\\|"
- page-delimiter
- ;;!!! Uhm... shurely this can't be right?
- "[> " (regexp-quote message-yank-prefix) "]+$"))
- (setq paragraph-separate paragraph-start)
(make-local-variable 'message-reply-headers)
(setq message-reply-headers nil)
(make-local-variable 'message-user-agent)
(make-local-variable 'message-parameter-alist)
(setq message-parameter-alist
(copy-sequence message-startup-parameter-alist))
+ (message-setup-fill-variables)
;;(when (fboundp 'mail-hist-define-keys)
;; (mail-hist-define-keys))
- (when (string-match "XEmacs\\|Lucid" emacs-version)
- (message-setup-toolbar))
+ (if (featurep 'xemacs)
+ (message-setup-toolbar)
+ (set (make-local-variable 'font-lock-defaults)
+ '((message-font-lock-keywords
+ message-font-lock-keywords-1
+ message-font-lock-keywords-2)
+ nil nil nil nil
+ (font-lock-mark-block-function . mark-paragraph))))
+ (set (make-local-variable 'message-font-lock-last-position) nil)
(easy-menu-add message-mode-menu message-mode-map)
(easy-menu-add message-mode-field-menu message-mode-map)
;; Allow mail alias things.
(mail-abbrevs-setup)
(mail-aliases-setup)))
(message-set-auto-save-file-name)
- (unless (string-match "XEmacs" emacs-version)
- (set (make-local-variable 'font-lock-defaults)
- '((message-font-lock-keywords
- message-font-lock-keywords-1
- message-font-lock-keywords-2)
- nil nil nil nil
- (font-lock-mark-block-function . mark-paragraph))))
- (set (make-local-variable 'message-font-lock-last-position) nil)
+ (make-local-variable 'indent-tabs-mode) ;Turn off tabs for indentation.
+ (setq indent-tabs-mode nil)
+ (run-hooks 'text-mode-hook 'message-mode-hook))
+
+(defun message-setup-fill-variables ()
+ "Setup message fill variables."
+ (make-local-variable 'paragraph-separate)
+ (make-local-variable 'paragraph-start)
(make-local-variable 'adaptive-fill-regexp)
- (setq adaptive-fill-regexp
- (concat "[ \t]*[-a-z0-9A-Z]*\\(>[ \t]*\\)+[ \t]*\\|"
- adaptive-fill-regexp))
(unless (boundp 'adaptive-fill-first-line-regexp)
(setq adaptive-fill-first-line-regexp nil))
(make-local-variable 'adaptive-fill-first-line-regexp)
- (setq adaptive-fill-first-line-regexp
- (concat "[ \t]*[-a-z0-9A-Z]*\\(>[ \t]*\\)+[ \t]*\\|"
- adaptive-fill-first-line-regexp))
(make-local-variable 'auto-fill-inhibit-regexp)
- (setq auto-fill-inhibit-regexp "^[A-Z][^: \n\t]+:")
- (make-local-variable 'indent-tabs-mode) ;Turn off tabs for indentation.
- (setq indent-tabs-mode nil)
- (run-hooks 'text-mode-hook 'message-mode-hook))
+ (let ((quote-prefix-regexp
+ (concat
+ "[ \t]*" ; possible initial space
+ "\\(\\(" (regexp-quote message-yank-prefix) "\\|" ; user's prefix
+ "\\(\\w\\|[-_.]\\)+>\\|" ; supercite-style prefix
+ "[|:>]" ; standard prefix
+ "\\)[ \t]*\\)+"))) ; possible space after each prefix
+ (setq paragraph-start
+ (concat
+ (regexp-quote mail-header-separator) "$\\|"
+ "[ \t]*$\\|" ; blank lines
+ "-- $\\|" ; signature delimiter
+ "---+$\\|" ; delimiters for forwarded messages
+ page-delimiter "$\\|" ; spoiler warnings
+ ".*wrote:$\\|" ; attribution lines
+ quote-prefix-regexp "$")) ; empty lines in quoted text
+ (setq paragraph-separate paragraph-start)
+ (setq adaptive-fill-regexp
+ (concat quote-prefix-regexp "\\|" adaptive-fill-regexp))
+ (setq adaptive-fill-first-line-regexp
+ (concat quote-prefix-regexp "\\|"
+ adaptive-fill-first-line-regexp))
+ (setq auto-fill-inhibit-regexp "^[A-Z][^: \n\t]+:")))
\f
(mail-fetch-field "to")
(not (string-match "\\` *\\'" (mail-fetch-field "to"))))
(insert ", "))
- (insert (or (message-fetch-reply-field "reply-to")
+ (insert (or (message-fetch-reply-field "mail-reply-to")
+ (message-fetch-reply-field "reply-to")
(message-fetch-reply-field "from") "")))
(defun message-widen-reply ()
(defun message-newline-and-reformat ()
"Insert four newlines, and then reformat if inside quoted text."
(interactive)
- (let ((prefix "[]>»|:}+ \t]*")
- (supercite-thing "[-._a-zA-Z0-9]*[>]+[ \t]*")
- quoted point)
+ (let (quoted point)
(unless (bolp)
(save-excursion
(beginning-of-line)
- (when (looking-at (concat prefix
- supercite-thing))
+ (when (looking-at message-cite-prefix-regexp)
(setq quoted (match-string 0))))
(insert "\n"))
(setq point (point))
(let ((inhibit-read-only t))
(put-text-property (point-min) (point-max) 'read-only nil))
(run-hooks 'message-send-hook)
- (message "Sending...")
+ (message-fix-before-sending)
+ (message message-sending-message)
(let ((message-encoding-buffer
(message-generate-new-buffer-clone-locals " message encoding"))
(message-edit-buffer (current-buffer))
(message-mime-mode mime-edit-mode-flag)
(alist message-send-method-alist)
(success t)
- elem sent)
+ elem sent
+ (message-options message-options))
+ (message-options-set-recipient)
(save-excursion
(set-buffer message-encoding-buffer)
(erase-buffer)
(insert-buffer message-edit-buffer)
(funcall message-encode-function)
- (message-fix-before-sending)
(while (and success
(setq elem (pop alist)))
- (when (or (not (funcall (cadr elem)))
- (and (or (not (memq (car elem)
- message-sent-message-via))
- (y-or-n-p
- (format
- "Already sent message via %s; resend? "
- (car elem))))
- (setq success (funcall (caddr elem) arg))))
- (setq sent t))))
+ (when (funcall (cadr elem))
+ (when (and (or (not (memq (car elem)
+ message-sent-message-via))
+ (y-or-n-p
+ (format
+ "Already sent message via %s; resend? "
+ (car elem))))
+ (setq success (funcall (caddr elem) arg)))
+ (setq sent t)))))
(unless (or sent (not success))
(error "No methods specified to send by"))
(prog1
(save-excursion
(run-hooks 'message-sent-hook))
(message "Sending...done")
- ;; Mark the buffer as unmodified and delete autosave.
+ ;; Mark the buffer as unmodified and delete auto-save.
(set-buffer-modified-p nil)
(delete-auto-save-file-if-necessary t)
(message-disassociate-draft)
(put 'message-check 'lisp-indent-function 1)
(put 'message-check 'edebug-form-spec '(form body))
+;; This function will be used by MIME-Edit when inserting invisible parts.
+(defun message-invisible-region (start end)
+ (if (featurep 'xemacs)
+ (if (save-excursion
+ (goto-char start)
+ (eq (following-char) ?\n))
+ (setq start (1+ start)))
+ (if (save-excursion
+ (goto-char (1- end))
+ (eq (following-char) ?\n))
+ (setq end (1- end))))
+ (put-text-property start end 'invisible t)
+ (if (eq 'message-mode major-mode)
+ (put-text-property start end 'message-invisible t)))
+
+(eval-after-load "invisible"
+ '(defalias 'invisible-region 'message-invisible-region))
+
(defun message-fix-before-sending ()
"Do various things to make the message nice before sending it."
;; Make sure there's a newline at the end of the message.
+ (widen)
(goto-char (point-max))
(unless (bolp)
(insert "\n"))
- ;; Delete all invisible text.
+ ;; Expose all invisible text with the property `message-invisible'.
+ ;; We should believe that the things might be created by MIME-Edit.
+ (let (start)
+ (while (setq start (text-property-any (point-min) (point-max)
+ 'message-invisible t))
+ (remove-text-properties start
+ (or (text-property-not-all start (point-max)
+ 'message-invisible t)
+ (point-max))
+ '(invisible nil message-invisible nil))))
+ ;; Expose all invisible text.
(message-check 'invisible-text
(when (text-property-any (point-min) (point-max) 'invisible t)
(put-text-property (point-min) (point-max) 'invisible nil)
(defun message-send-mail-partially ()
"Sendmail as message/partial."
+ ;; replace the header delimiter with a blank line
+ (goto-char (point-min))
+ (re-search-forward
+ (concat "^" (regexp-quote mail-header-separator) "\n"))
+ (replace-match "\n")
+ (run-hooks 'message-send-mail-hook)
(let ((p (goto-char (point-min)))
(tembuf (message-generate-new-buffer-clone-locals " message temp"))
(curbuf (current-buffer))
;; require one newline at the end.
(or (= (preceding-char) ?\n)
(insert ?\n))
- (when (and news
+ (when
+ (save-restriction
+ (message-narrow-to-headers)
+ (and news
(or (message-fetch-field "cc")
- (message-fetch-field "to")))
+ (message-fetch-field "to"))
+ (let ((ct (mime-read-Content-Type)))
+ (and (eq 'text (cdr (assq 'type ct)))
+ (eq 'plain (cdr (assq 'subtype ct)))))))
(message-insert-courtesy-copy))
(setq failure (message-maybe-split-and-send-mail)))
(kill-buffer tembuf))
(message-check 'signature
(goto-char (point-max))
(if (> (count-lines (point) (point-max)) 5)
- (y-or-n-p
- (format
- "Your .sig is %d lines; it should be max 4. Really post? "
- (1- (count-lines (point) (point-max)))))
- t))))
+ (y-or-n-p
+ (format
+ "Your .sig is %d lines; it should be max 4. Really post? "
+ (1- (count-lines (point) (point-max)))))
+ t))
+ ;; Ensure that text follows last quoted portion.
+ (message-check 'quoting-style
+ (goto-char (point-max))
+ (let ((no-problem t))
+ (when (search-backward-regexp "^>[^\n]*\n>" nil t)
+ (setq no-problem nil)
+ (while (not (eobp))
+ (when (and (not (eolp)) (looking-at "[^> \t]"))
+ (setq no-problem t))
+ (forward-line)))
+ (if no-problem
+ t
+ (y-or-n-p "Your text should follow quoted text. Really post? "))))))
(defun message-check-mail-syntax ()
"Check the syntax of the message."
(message-insert-signature)
(save-restriction
(message-narrow-to-headers)
+ (if message-alternative-emails
+ (message-use-alternative-email-as-from))
(run-hooks 'message-header-setup-hook))
(set-buffer-modified-p nil)
(setq buffer-undo-list nil)
(Subject . ,(or subject ""))))))
(defun message-get-reply-headers (wide &optional to-address)
- (let (follow-to mct never-mct from to cc reply-to mft)
+ (let (follow-to mct never-mct from to cc reply-to mrt mft)
;; Find all relevant headers we need.
(setq from (message-fetch-field "from")
to (message-fetch-field "to")
cc (message-fetch-field "cc")
mct (when message-use-mail-copies-to
(message-fetch-field "mail-copies-to"))
- reply-to (when message-use-mail-reply-to
- (or (message-fetch-field "mail-reply-to")
- (message-fetch-field "reply-to")))
- mft (when (and (not to-address)
- (not reply-to)
+ reply-to (message-fetch-field "reply-to")
+ mrt (when message-use-mail-reply-to
+ (message-fetch-field "mail-reply-to"))
+ mft (when (and (not (or to-address mrt reply-to))
message-use-mail-followup-to)
(message-fetch-field "mail-followup-to")))
`Mail-Copies-To: always'
sends a copy of your response to the author.")))
- (setq mct (or reply-to from)))
+ (setq mct (or mrt reply-to from)))
((and (eq message-use-mail-copies-to 'ask)
(not
(message-y-or-n-p
(if (or (not wide)
to-address)
(progn
- (setq follow-to (list (cons 'To (or to-address reply-to mft from))))
+ (setq follow-to (list (cons 'To
+ (or to-address mrt reply-to mft from))))
(when (and wide mct)
(push (cons 'Cc mct) follow-to)))
(let (ccalist)
(save-excursion
(message-set-work-buffer)
- (unless never-mct
- (insert (or reply-to from "")))
- (insert (if mft (concat (if (bolp) "" ", ") mft "") ""))
- (insert (if to (concat (if (bolp) "" ", ") to "") ""))
- (insert (if mct (concat (if (bolp) "" ", ") mct) ""))
- (insert (if cc (concat (if (bolp) "" ", ") cc) ""))
+ (if (and mft
+ message-use-followup-to
+ (or (not (eq message-use-followup-to 'ask))
+ (message-y-or-n-p "Obey Mail-Followup-To? " t "\
+You should normally obey the Mail-Followup-To: header. In this
+article, it has the value of
+
+" mft "
+
+which directs your response to " (if (string-match "," mft)
+ "the specified addresses"
+ "that address only") ".
+
+If a message is posted to several mailing lists, Mail-Followup-To is
+often used to direct the following discussion to one list only,
+because discussions that are spread over several lists tend to be
+fragmented and very difficult to follow.
+
+Also, some source/announcement lists are not indented for discussion;
+responses here are directed to other addresses.")))
+ (insert mft)
+ (unless never-mct
+ (insert (or mrt reply-to from "")))
+ (insert (if to (concat (if (bolp) "" ", ") to "") ""))
+ (insert (if mct (concat (if (bolp) "" ", ") mct) ""))
+ (insert (if cc (concat (if (bolp) "" ", ") cc) "")))
(goto-char (point-min))
(while (re-search-forward "[ \t]+" nil t)
(replace-match " " t t))
(goto-char (point-min))
;; Perhaps "Mail-Copies-To: never" removed the only address?
(when (eobp)
- (insert (or reply-to from "")))
+ (insert (or mrt reply-to from "")))
(setq ccalist
(mapcar
(lambda (addr)
(defun message-reply (&optional to-address wide)
"Start editing a reply to the article in the current buffer."
(interactive)
+ (require 'gnus-sum) ; for gnus-list-identifiers
(let ((cur (current-buffer))
from subject date
references message-id follow-to
"Follow up to the message in the current buffer.
If TO-NEWSGROUPS, use that as the new Newsgroups line."
(interactive)
+ (require 'gnus-sum) ; for gnus-list-identifiers
(let ((cur (current-buffer))
- from subject date mct
+ from subject date reply-to mrt mct mft
references message-id follow-to
(inhibit-point-motion-hooks t)
(message-this-is-news t)
- followup-to distribution newsgroups gnus-warning posted-to mft mrt)
+ followup-to distribution newsgroups gnus-warning posted-to)
(save-restriction
(message-narrow-to-head)
(when (message-functionp message-followup-to-function)
(setq follow-to
(funcall message-followup-to-function)))
(setq from (message-fetch-field "from")
- date (message-fetch-field "date" t)
+ date (message-fetch-field "date")
subject (or (message-fetch-field "subject") "none")
references (message-fetch-field "references")
message-id (message-fetch-field "message-id" t)
- followup-to (when message-use-followup-to
- (message-fetch-field "followup-to"))
- distribution (message-fetch-field "distribution")
+ followup-to (message-fetch-field "followup-to")
newsgroups (message-fetch-field "newsgroups")
posted-to (message-fetch-field "posted-to")
+ reply-to (message-fetch-field "reply-to")
+ mrt (when message-use-mail-reply-to
+ (message-fetch-field "mail-reply-to"))
+ distribution (message-fetch-field "distribution")
mct (when message-use-mail-copies-to
(message-fetch-field "mail-copies-to"))
mft (when message-use-mail-followup-to
- (message-fetch-field "mail-followup-to"))
- mrt (when message-use-mail-reply-to
- (or (message-fetch-field "mail-reply-to")
- (message-fetch-field "reply-to")))
- gnus-warning (message-fetch-field "gnus-warning"))
- (when (and gnus-warning (string-match "<[^>]+>" gnus-warning))
+ (message-fetch-field "mail-followup-to")))
+ (when (and (setq gnus-warning (message-fetch-field "gnus-warning"))
+ (string-match "<[^>]+>" gnus-warning))
(setq message-id (match-string 0 gnus-warning)))
;; Remove bogus distribution.
(when (and (stringp distribution)
`Mail-Copies-To: always'
sends a copy of your response to the author.")))
- (setq mct (or mrt from)))
+ (setq mct (or mrt reply-to from)))
((and (eq message-use-mail-copies-to 'ask)
(not
(message-y-or-n-p
(followup-to
(cond
((equal (downcase followup-to) "poster")
- (if (or (eq message-use-followup-to 'use)
+ (if (or (and followup-to (eq message-use-followup-to 'use))
(message-y-or-n-p "Obey Followup-To: poster? " t "\
You should normally obey the Followup-To: header.
does not read the newsgroup, so he wouldn't see any replies sent to it."))
(setq message-this-is-news nil
distribution nil
- follow-to (list (cons 'To (or mrt from ""))))
+ follow-to (list (cons 'To (or mrt reply-to from ""))))
(setq follow-to (list (cons 'Newsgroups newsgroups)))))
(t
(if (or (equal followup-to newsgroups)
- (not (eq message-use-followup-to 'ask))
+ (not (and followup-to (eq message-use-followup-to 'ask)))
(message-y-or-n-p
(concat "Obey Followup-To: " followup-to "? ") t "\
You should normally obey the Followup-To: header.
(message-pop-to-buffer (message-buffer-name "followup" from newsgroups))
- (setq message-reply-headers
- (make-full-mail-header-from-decoded-header
- 0 subject from date message-id references 0 0 ""))
-
(message-setup
`((Subject . ,subject)
,@follow-to
,@(if (or references message-id)
`((References . ,(concat (or references "") (and references " ")
(or message-id ""))))))
- cur)))
+ cur)
+
+ (setq message-reply-headers
+ (make-full-mail-header-from-decoded-header
+ 0 subject from date message-id references 0 0 ""))))
;;;###autoload
(defun message-cancel-news (&optional arg)
(setq buf (set-buffer (get-buffer-create " *message cancel*"))))
(erase-buffer)
(insert "Newsgroups: " newsgroups "\n"
- "From: " (message-make-from) "\n"
+ "From: " from "\n"
"Subject: cmsg cancel " message-id "\n"
"Control: cancel " message-id "\n"
(if distribution
"Return a Subject header suitable for the message in the current buffer."
(save-excursion
(save-restriction
- (current-buffer)
(message-narrow-to-head)
(let ((funcs message-make-forward-subject-function)
(subject (message-fetch-field "Subject")))
(defalias 'message-exchange-point-and-mark 'exchange-point-and-mark)
;; Support for toolbar
-(when (string-match "XEmacs\\|Lucid" emacs-version)
+(when (featurep 'xemacs)
(require 'messagexmas))
;;; Group name completion.
;;; Miscellaneous functions
;; stolen (and renamed) from nnheader.el
-(defun message-replace-chars-in-string (string from to)
- "Replace characters in STRING from FROM to TO."
- (let ((string (substring string 0)) ;Copy string.
- (len (length string))
- (idx 0))
- ;; Replace all occurrences of FROM with TO.
- (while (< idx len)
- (when (= (aref string idx) from)
- (aset string idx to))
- (setq idx (1+ idx)))
- string))
+(static-if (fboundp 'subst-char-in-string)
+ (defsubst message-replace-chars-in-string (string from to)
+ (subst-char-in-string from to string))
+ (defun message-replace-chars-in-string (string from to)
+ "Replace characters in STRING from FROM to TO."
+ (let ((string (substring string 0)) ;Copy string.
+ (len (length string))
+ (idx 0))
+ ;; Replace all occurrences of FROM with TO.
+ (while (< idx len)
+ (when (= (aref string idx) from)
+ (aset string idx to))
+ (setq idx (1+ idx)))
+ string)))
;;;
;;; MIME functions
(let ((minibuffer-setup-hook 'mail-abbrev-minibuffer-setup-hook))
(read-string prompt))))
-(defvar message-save-buffer " *encoding")
+(defun message-use-alternative-email-as-from ()
+ (require 'mail-utils)
+ (let* ((fields '("To" "Cc"))
+ (emails
+ (split-string
+ (mail-strip-quoted-names
+ (mapconcat 'message-fetch-reply-field fields ","))
+ "[ \f\t\n\r\v,]+"))
+ email)
+ (while emails
+ (if (string-match message-alternative-emails (car emails))
+ (setq email (car emails)
+ emails nil))
+ (pop emails))
+ (unless (or (not email) (equal email user-mail-address))
+ (goto-char (point-max))
+ (insert "From: " email "\n"))))
+
+(defun message-options-get (symbol)
+ (cdr (assq symbol message-options)))
+
+(defun message-options-set (symbol value)
+ (let ((the-cons (assq symbol message-options)))
+ (if the-cons
+ (if value
+ (setcdr the-cons value)
+ (setq message-options (delq the-cons message-options)))
+ (and value
+ (push (cons symbol value) message-options))))
+ value)
+
+(defun message-options-set-recipient ()
+ (save-restriction
+ (message-narrow-to-headers-or-head)
+ (message-options-set 'message-sender
+ (mail-strip-quoted-names
+ (message-fetch-field "from")))
+ (message-options-set 'message-recipients
+ (mail-strip-quoted-names
+ (message-fetch-field "to")))))
+
(defun message-save-drafts ()
+ "Postponing the message."
(interactive)
- (if (not (get-buffer message-save-buffer))
- (get-buffer-create message-save-buffer))
- (let ((filename buffer-file-name)
- (buffer (current-buffer))
- (reply-headers message-reply-headers))
- (set-buffer message-save-buffer)
- (erase-buffer)
- (insert-buffer buffer)
- (setq message-reply-headers reply-headers)
- (message-generate-headers '((optional . In-Reply-To)))
- (mime-edit-translate-buffer)
- (write-region (point-min) (point-max) filename)
- (set-buffer buffer)
- (set-buffer-modified-p nil)))
+ (message "Saving %s..." buffer-file-name)
+ (let ((reply-headers message-reply-headers)
+ (msg (buffer-substring-no-properties (point-min) (point-max))))
+ (with-temp-file buffer-file-name
+ (insert msg)
+ (setq message-reply-headers reply-headers)
+ (message-generate-headers '((optional . In-Reply-To)))
+ (mime-edit-translate-buffer))
+ (set-buffer-modified-p nil))
+ (message "Saving %s...done" buffer-file-name))
(provide 'message)