(eval-when-compile
(require 'cl))
(require 'mail-header)
+(require 'nnheader)
+;;;###autoload
(defvar message-fcc-handler-function 'rmail-output
"*A function called to save outgoing articles.
This function will be called with the name of the file to store the
article in. The default function is `rmail-output' which saves in Unix
mailbox format.")
+;;;###autoload
(defvar message-courtesy-message
"The following message is a courtesy copy of an article\nthat has been posted as well.\n\n"
"*This is inserted at the start of a mailed copy of a posted message.
If this variable is nil, no such courtesy message will be added.")
+;;;###autoload
(defvar message-ignored-bounced-headers "^\\(Received\\):"
"*Regexp that matches headers to be removed in resent bounced mail.")
+;;;###autoload
(defvar message-from-style 'angles
"*Specifies how \"From\" headers look.
If `angles', they look like:
Elvis Parsley <king@grassland.com>")
+;;;###autoload
(defvar message-syntax-checks
'(subject-cmsg multiple-headers sendsys message-id from
long-lines control-chars size new-text
If this variable is t, message will check everything it can. If it is
a list, then those elements in that list will be checked.")
+;;;###autoload
(defvar message-required-news-headers
- '(From Date Newsgroups Subject Message-ID Organization Lines
+ '(From Date Newsgroups Subject Message-ID
+ (optional . Organization) Lines
(optional . X-Newsreader))
"*Headers to be generated or prompted for when posting an article.
RFC977 and RFC1036 require From, Date, Newsgroups, Subject,
X-Newsreader are optional. If don't you want message to insert some
header, remove it from this list.")
+;;;###autoload
(defvar message-required-mail-headers
'(From Date To Subject (optional . In-Reply-To) Message-ID Lines
(optional . X-Mailer))
RFC822 required that From, Date, To, Subject and Message-ID be
included. Organization, Lines and X-Mailer are optional.")
+;;;###autoload
(defvar message-deletable-headers '(Message-ID Date)
"*Headers to be deleted if they already exist and were generated by message previously.")
+;;;###autoload
(defvar message-ignored-news-headers
"^NNTP-Posting-Host:\\|^Xref:\\|^Bcc:\\|^Gcc:"
"*Regexp of headers to be removed unconditionally before posting.")
+;;;###autoload
(defvar message-ignored-mail-headers "^Gcc:"
"*Regexp of headers to be removed unconditionally before mailing.")
+;;;###autoload
(defvar message-ignored-supersedes-headers
"^Path:\\|^Date\\|^NNTP-Posting-Host:\\|^Xref:\\|^Lines:\\|^Received:\\|^X-From-Line:\\|Return-Path:"
"*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.")
+;;;###autoload
(defvar message-signature-separator "^-- *$"
"Regexp matching signature separator.")
+;;;###autoload
(defvar message-interactive nil
"Non-nil means when sending a message wait for and display errors.
nil means let mailer mail back a message to report errors.")
(defvar gnus-local-organization)
+;;;###autoload
(defvar message-user-organization
(if (boundp 'gnus-local-organization)
gnus-local-organization t)
"*String to be used as an Organization header.
If t, use `message-user-organization-file'.")
+;;;###autoload
(defvar message-user-organization-file "/usr/lib/news/organization"
"*Local news organization file.")
+;;;###autoload
(defvar message-autosave-directory "~/Mail/drafts/"
"*Directory where message autosaves buffers.
If nil, message won't autosave.")
"------- End of forwarded message -------\n"
"*Delimiter inserted after forwarded messages.")
+;;;###autoload
(defvar message-signature-before-forwarded-message t
"*If non-nil, put the signature before any included forwarded message.")
+;;;###autoload
(defvar message-included-forward-headers
"^From:\\|^Newsgroups:\\|^Subject:\\|^Date:\\|^Followup-To:\\|^Reply-To:\\|^Organization:\\|^Summary:\\|^Keywords:\\|^To:\\|^Cc:\\|^Posted-To:\\|^Mail-Copies-To:\\|^Apparently-To:\\|^Gnus-Warning:\\|^Resent-\\|^Message-ID:\\|^References:"
"*Regexp matching headers to be included in forwarded messages.")
+;;;###autoload
(defvar message-ignored-resent-headers "^Return-receipt"
"*All headers that match this regexp will be deleted when resending a message.")
The headers should be delimited by a line whose contents match the
variable `message-header-separator'.")
+;;;###autoload
(defvar message-send-news-function 'message-send-news
"Function to call to send the current buffer as news.
The headers should be delimited by a line whose contents match the
variable `message-header-separator'.")
+;;;###autoload
(defvar message-reply-to-function nil
"Function that should return a list of headers.")
+;;;###autoload
(defvar message-wide-reply-to-function nil
"Function that should return a list of headers.")
+;;;###autoload
(defvar message-followup-to-function nil
"Function that should return a list of headers.")
+;;;###autoload
(defvar message-use-followup-to 'ask
"*Specifies what to do with Followup-To header.
If nil, ignore the header. If it is t, use its value, but ignore
ignore the \"poster\" value. If it is the symbol `use', always use
the value.")
+;;;###autoload
(defvar message-post-method
(cond ((boundp 'gnus-post-method)
gnus-post-method)
(t '(nnspool "")))
"Method used to post news.")
+;;;###autoload
(defvar message-generate-headers-first nil
"*If non-nil, generate all possible headers before composing.")
"Normal hook, run each time a new outgoing message is initialized.
The function `message-setup' runs this hook.")
-(defvar message-cite-hook nil
- "Hook run when yanking articles.")
-
(defvar message-header-setup-hook nil
"Hook called narrowed to the headers when setting up a message buffer.")
+;;;###autoload
(defvar message-citation-line-function 'message-insert-citation-line
"*Function called to insert the \"Whomever writes:\" line.")
(defvar message-alias-modtime nil
"The modification time of your mail alias file when it was last examined.")
+;;;###autoload
(defvar message-yank-prefix "> "
"*Prefix inserted on the lines of yanked messages.
nil means use indentation.")
"*Number of spaces to insert at the beginning of each cited line.
Used by `message-yank-original' via `message-yank-cite'.")
+;;;###autoload
+(defvar message-cite-function 'message-cite-original
+ "*Function for citing an original message.")
+
+;;;###autoload
(defvar message-indent-citation-function 'message-indent-citation
"*Function for modifying a citation just inserted in the mail buffer.
This can also be a list of functions. Each function can find the
removed from alias expansions."
nil)
+;;;###autoload
(defvar message-signature t
"*String to be inserted at the and the the message buffer.
If t, the `message-signature-file' file will be inserted instead.
If a function, the result from the function will be used instead.
If a form, the result from the form will be used instead.")
+;;;###autoload
(defvar message-signature-file "~/.signature"
"*File containing the text inserted at end of mail buffer.")
"If nil, use the NNTP server name in the Path header.
If stringp, use this; if non-nil, use no host name (user name only).")
-(defvar message-generic-domain nil
- "If nil, the full host name will be the system name prepended to the domain name.
-If this is a string, the full host name will be this string.
-If this is non-nil, non-string, the domain name will be used as the
-full host name.")
-
(defvar message-reply-buffer nil)
(defvar message-reply-headers nil)
(defvar message-newsreader nil)
(defvar message-send-actions nil
"A list of actions to be performed upon successful sending of a message.")
+;;;###autoload
(defvar message-default-headers nil
"*A string containing header lines to be inserted in outgoing messages.
It is inserted before you edit the message, so you can edit or delete
these lines.")
+;;;###autoload
(defvar message-default-mail-headers nil
"*A string of header lines to be inserted in outgoing mails.")
+;;;###autoload
(defvar message-default-news-headers nil
"*A string of header lines to be inserted in outgoing news articles.")
Like Text Mode but with these additional commands:
C-c C-s message-send (send the message) C-c C-c message-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 Subject:
- C-c C-f C-c move to CC: C-c C-f C-b move to BCC:
- C-c C-f C-f move to FCC: C-c C-f C-r move to Reply-To:
- C-c C-f C-u move to Summary: C-c C-f C-n move to Newsgroups:
- C-c C-f C-k move to Kewords: C-c C-f C-d move to Distribution:
- C-c C-f C-o move to Followup-To:
-C-c C-t message-insert-to (add a To: header to a news followup)
-C-c C-n message-insert-newsgroups (add a Newsgroup: header to a news reply)
-C-c C-b message-goto-text (move to beginning of message text).
+ C-c C-f C-t move to To C-c C-f C-s move to Subject
+ C-c C-f C-c move to Cc C-c C-f C-b move to Bcc
+ C-c C-f C-f move to Fcc C-c C-f C-r move to Reply-To
+ C-c C-f C-u move to Summary C-c C-f C-n move to Newsgroups
+ C-c C-f C-k move to Keywords C-c C-f C-d move to Distribution
+ C-c C-f C-o move to Followup-To
+C-c C-t message-insert-to (add a To header to a news followup)
+C-c C-n message-insert-newsgroups (add a Newsgroup header to a news reply)
+C-c C-b message-goto-body (move to beginning of message text).
C-c C-s message-goto-signature (move to the beginning of the signature).
C-c C-w message-insert-signature (insert `message-signature-file' file).
C-c C-y message-yank-original (insert current message, if any).
C-c C-q message-fill-yanked-message (fill what was yanked).
-C-c C-v message-sent-via (add a Sent-via field for each To or CC).
C-c C-r message-ceasar-buffer-body (rot13 the message body)."
(interactive)
(kill-all-local-variables)
;;; Various commands
-(defun message-insert-signature ()
+(defun message-insert-signature (&optional force)
"Insert a signature. See documentation for the `message-signature' variable."
- (interactive)
+ (interactive (list t))
(let* ((signature
- (cond ((message-functionp message-signature)
+ (cond ((and (null message-signature)
+ force)
+ t)
+ ((message-functionp message-signature)
(funcall message-signature))
((listp message-signature)
(eval message-signature))
Just \\[universal-argument] as argument means don't indent, insert no
prefix, and don't delete any headers."
(interactive "P")
- (when message-reply-buffer
- (let ((start (point))
- (functions
- (when message-indent-citation-function
- (if (listp message-indent-citation-function)
- message-indent-citation-function
- (list message-indent-citation-function))))
- (modified (buffer-modified-p)))
- ;; 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.
+ (let ((modified (buffer-modified-p)))
+ (when (and message-reply-buffer
+ message-cite-function)
(delete-windows-on message-reply-buffer t)
(insert-buffer message-reply-buffer)
- (unless (consp arg)
- (goto-char start)
- (let ((message-indentation-spaces
- (if arg (prefix-numeric-value arg)
- message-indentation-spaces)))
- (while functions
- (funcall (pop functions)))))
- (when message-citation-line-function
- (unless (bolp)
- (insert "\n"))
- (funcall message-citation-line-function))
+ (funcall message-cite-function)
;; 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.
(unless (bolp)
(insert ?\n))
(unless modified
- (setq message-checksum (message-checksum)))
- (run-hooks 'message-cite-hook))))
+ (setq message-checksum (message-checksum))))))
+
+(defun message-cite-original ()
+ (let ((start (point))
+ (functions
+ (when message-indent-citation-function
+ (if (listp message-indent-citation-function)
+ message-indent-citation-function
+ (list message-indent-citation-function)))))
+ (unless (consp arg)
+ (goto-char start)
+ (let ((message-indentation-spaces
+ (if arg (prefix-numeric-value arg)
+ message-indentation-spaces)))
+ (while functions
+ (funcall (pop functions)))))
+ (when message-citation-line-function
+ (unless (bolp)
+ (insert "\n"))
+ (funcall message-citation-line-function))))
(defun message-insert-citation-line ()
"Function that inserts a simple citation line."
(save-restriction
(message-narrow-to-headers)
;; Remove some headers.
- (message-remove-header message-ignored-news-headers t))
+ (message-remove-header message-ignored-mail-headers t))
(goto-char (point-max))
;; require one newline at the end.
(or (= (preceding-char) ?\n)
(defun message-make-message-id ()
"Make a unique Message-ID."
- (concat "<" (message-unique-id) "@" (message-make-fqdm) ">"))
+ (concat "<" (message-unique-id)
+ (let ((psubject (save-excursion (mail-fetch-field "subject"))))
+ (if (and message-reply-headers
+ (mail-header-references message-reply-headers)
+ (mail-header-subject message-reply-headers)
+ psubject
+ (mail-header-subject message-reply-headers)
+ (not (string=
+ (message-strip-subject-re
+ (mail-header-subject message-reply-headers))
+ (message-strip-subject-re psubject))))
+ "_-_" ""))
+ "@" (message-make-fqdm) ">"))
(defvar message-unique-id-char nil)
(defun message-make-address ()
"Make the address of the user."
- (concat (user-login-name) "@" (message-make-domain)))
+ (or user-mail-address
+ (concat (user-login-name) "@" (message-make-domain))))
(defun message-make-fqdm ()
"Return user's fully qualified domain name."
(let ((system-name (system-name)))
- (if (string-match "[^.]\\.[^.]" system-name)
- ;; `system-name' returned the right result.
- system-name
- ;; We try `user-mail-address' as a backup.
- (if (string-match "@\\([^ ]+\\)\\($\\| \\)" user-mail-address)
- (match-string 1 user-mail-address)
- (concat system-name ".i-have-a-misconfigured-system-so-shoot-me")))))
+ (cond
+ ((string-match "[^.]\\.[^.]" system-name)
+ ;; `system-name' returned the right result.
+ system-name)
+ ;; We try `user-mail-address' as a backup.
+ ((string-match "@\\(\\W+\\)\\(\\'\\|\\W\\)" user-mail-address)
+ (match-string 1 user-mail-address))
+ (t
+ (concat system-name ".i-have-a-misconfigured-system-so-shoot-me")))))
(defun message-make-host-name ()
"Return the name of the host."
(defun message-make-domain ()
"Return the domain name."
- (let ((fqdm (message-make-fqdm)))
- (if message-generic-domain
- (progn
- (string-match "^[^.]+\\." fqdm)
- (substring fqdm (match-end 0)))
- fqdm)))
+ (or mail-host-address
+ (message-make-fqdm)))
(defun message-generate-headers (headers)
"Prepare article HEADERS.
(get-text-property (1+ (match-beginning 0)) 'message-deletable)
(message-delete-line))
(pop headers)))
- ;; If there are References, and the subject has changed, then
- ;; we have to change the Message-ID. See Son-of-1036.
- (when (and message-reply-headers
- (mail-fetch-field "references"))
- (let ((psubject (mail-fetch-field "subject")))
- (and psubject (mail-header-subject message-reply-headers)
- (string= (message-strip-subject-re
- (mail-header-subject message-reply-headers))
- (message-strip-subject-re
- psubject))
- (progn
- (string-match "@" Message-ID)
- (setq Message-ID
- (concat (substring Message-ID 0 (match-beginning 0))
- "_-_"
- (substring Message-ID (match-beginning 0))))))))
;; Go through all the required headers and see if they are in the
;; articles already. If they are not, or are empty, they are
;; inserted automatically - except for Subject, Newsgroups and
(insert mail-header-separator))
(message-position-point)))
+;;;
+;;; Interactive entry points for new message buffers.
+;;;
+
+;;;###autoload
+(defun message-mail-other-window (&optional to subject)
+ "Like `message-mail' command, but display mail buffer in another window."
+ (interactive)
+ (let ((pop-up-windows t)
+ (special-display-buffer-names nil)
+ (special-display-regexps nil)
+ (same-window-buffer-names nil)
+ (same-window-regexps nil))
+ (message-pop-to-buffer "*mail message*"))
+ (message-setup `((To . ,(or to "")) (Subject . ,(or subject "")))))
+
+;;;###autoload
+(defun message-mail-other-frame (&optional to subject)
+ "Like `message-mail' command, but display mail buffer in another frame."
+ (interactive)
+ (let ((pop-up-frames t)
+ (special-display-buffer-names nil)
+ (special-display-regexps nil)
+ (same-window-buffer-names nil)
+ (same-window-regexps nil))
+ (message-pop-to-buffer "*mail message*"))
+ (message-setup `((To . ,(or to "")) (Subject . ,(or subject "")))))
+
+;;;###autoload
+(defun message-news-other-window (&optional newsgroups subject)
+ "Start editing a news article to be sent."
+ (interactive)
+ (let ((pop-up-windows t)
+ (special-display-buffer-names nil)
+ (special-display-regexps nil)
+ (same-window-buffer-names nil)
+ (same-window-regexps nil))
+ (message-pop-to-buffer "*news message*"))
+ (message-setup `((Newsgroups . ,(or newsgroups ""))
+ (Subject . ,(or subject "")))))
+
+;;;###autoload
+(defun message-news-other-frame (&optional newsgroups subject)
+ "Start editing a news article to be sent."
+ (interactive)
+ (let ((pop-up-frames t)
+ (special-display-buffer-names nil)
+ (special-display-regexps nil)
+ (same-window-buffer-names nil)
+ (same-window-regexps nil))
+ (message-pop-to-buffer "*news message*"))
+ (message-setup `((Newsgroups . ,(or newsgroups ""))
+ (Subject . ,(or subject "")))))
+
(provide 'message)
;;; message.el ends here