(eval-when-compile (require 'cl))
(require 'mailheader)
-(require 'rmail)
+(condition-case nil
+ (require 'rmail)
+ (t (message "Ignore any errors about rmail from this file")))
(require 'nnheader)
(require 'timezone)
(require 'easymenu)
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."
+shorten-followup-to existing-newsgroups buffer-file-name unchanged."
:group 'message-news)
(defcustom message-required-news-headers
:type 'sexp)
(defcustom message-ignored-news-headers
- "^NNTP-Posting-Host:\\|^Xref:\\|^Bcc:\\|^Gcc:\\|^Fcc:\\|^Resent-Fcc:"
+ "^NNTP-Posting-Host:\\|^Xref:\\|^[BGF]cc:\\|^Resent-Fcc:"
"*Regexp of headers to be removed unconditionally before posting."
:group 'message-news
:group 'message-headers
:type 'regexp)
-(defcustom message-ignored-mail-headers "^Gcc:\\|^Fcc:\\|^Resent-Fcc:"
+(defcustom message-ignored-mail-headers "^[GF]cc:\\|^Resent-Fcc:"
"*Regexp of headers to be removed unconditionally before mailing."
:group 'message-mail
:group 'message-headers
:type 'regexp)
-(defcustom message-ignored-supersedes-headers "^Path:\\|^Date\\|^NNTP-Posting-Host:\\|^Xref:\\|^Lines:\\|^Received:\\|^X-From-Line:\\|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:"
"*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."
:type 'boolean)
(defcustom 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:"
+ "^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:\\|^Content-Transfer-Encoding:\\|^Content-Type:\\|^Mime-Version:"
"*Regexp matching headers to be included in forwarded messages."
:group 'message-forwarding
:type 'regexp)
(defvar message-postpone-actions nil
"A list of actions to be performed after postponing a message.")
+(define-widget 'message-header-lines 'text
+ "All header lines must be LFD terminated."
+ :valid-regexp "^\\'"
+ :error "All header lines must be newline terminated")
+
(defcustom message-default-headers ""
"*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."
:group 'message-headers
- :type 'string)
+ :type 'message-header-lines)
(defcustom message-default-mail-headers ""
"*A string of header lines to be inserted in outgoing mails."
:group 'message-headers
:group 'message-mail
- :type 'string)
+ :type 'message-header-lines)
(defcustom message-default-news-headers ""
"*A string of header lines to be inserted in outgoing news
articles."
:group 'message-headers
:group 'message-news
- :type 'string)
+ :type 'message-header-lines)
;; Note: could use /usr/ucb/mail instead of sendmail;
;; options -t, and -v if not interactive.
(defface message-header-other-face
'((((class color)
(background dark))
- (:foreground "red4"))
+ (:foreground "#b00000"))
(((class color)
(background light))
(:foreground "steel blue"))
(defface message-separator-face
'((((class color)
(background dark))
- (:foreground "blue4"))
+ (:foreground "blue3"))
(((class color)
(background light))
(:foreground "brown"))
(eval-and-compile
(autoload 'message-setup-toolbar "messagexmas")
+ (autoload 'mh-new-draft-name "mh-comp")
(autoload 'mh-send-letter "mh-comp")
(autoload 'gnus-point-at-eol "gnus-util")
(autoload 'gnus-point-at-bol "gnus-util")
(autoload 'gnus-output-to-mail "gnus-util")
(autoload 'gnus-output-to-rmail "gnus-util")
- (autoload 'mail-abbrev-in-expansion-header-p "mailabbrev"))
+ (autoload 'mail-abbrev-in-expansion-header-p "mailabbrev")
+ (autoload 'nndraft-request-associate-buffer "nndraft")
+ (autoload 'nndraft-request-expire-articles "nndraft"))
\f
"Return non-nil if FORM is funcallable."
(or (and (symbolp form) (fboundp form))
(and (listp form) (eq (car form) 'lambda))
- (compiled-function-p form)))
+ (byte-code-function-p form)))
(defun message-strip-subject-re (subject)
"Remove \"Re:\" from subject lines."
(save-excursion
(save-restriction
(message-narrow-to-headers)
- (message-fetch-field "newsgroups")))))
+ (and (message-fetch-field "newsgroups")
+ (not (message-fetch-field "posted-to")))))))
(defun message-mail-p ()
"Say whether the current buffer contains a mail message."
(define-key message-mode-map "\C-c\C-e" 'message-elide-region)
(define-key message-mode-map "\C-c\C-v" 'message-delete-not-region)
+ (define-key message-mode-map "\M-\r" 'message-newline-and-reformat)
(define-key message-mode-map "\t" 'message-tab))
["Caesar (rot13) Region" message-caesar-region (mark t)]
["Elide Region" message-elide-region (mark t)]
["Delete Outside Region" message-delete-not-region (mark t)]
+ ["Newline and Reformat" message-newline-and-reformat t]
["Rename buffer" message-rename-buffer t]
["Spellcheck" ispell-message t]
"----"
facemenu-remove-face-function t)
(make-local-variable 'paragraph-separate)
(make-local-variable 'paragraph-start)
- (setq paragraph-start (concat (regexp-quote mail-header-separator)
- "$\\|[ \t]*[-_][-_][-_]+$\\|"
- "-- $\\|"
- paragraph-start))
- (setq paragraph-separate (concat (regexp-quote mail-header-separator)
- "$\\|[ \t]*[-_][-_][-_]+$\\|"
- "-- $\\|"
- paragraph-separate))
+ (setq paragraph-start
+ (concat (regexp-quote mail-header-separator)
+ "$\\|[ \t]*[-_][-_][-_]+$\\|"
+ "-- $\\|"
+ ;;!!! Uhm... shurely this can't be right.
+ "[> " (regexp-quote message-yank-prefix) "]+$\\|"
+ paragraph-start))
+ (setq paragraph-separate
+ (concat (regexp-quote mail-header-separator)
+ "$\\|[ \t]*[-_][-_][-_]+$\\|"
+ "-- $\\|"
+ "[> " (regexp-quote message-yank-prefix) "]+$\\|"
+ paragraph-separate))
(make-local-variable 'message-reply-headers)
(setq message-reply-headers nil)
(make-local-variable 'message-newsreader)
(message-goto-signature)
(forward-line -2))
+(defun message-newline-and-reformat ()
+ "Insert four newlines, and then reformat if inside quoted text."
+ (interactive)
+ (let ((point (point))
+ quoted)
+ (save-excursion
+ (beginning-of-line)
+ (setq quoted (looking-at (regexp-quote message-yank-prefix))))
+ (insert "\n\n\n\n")
+ (when quoted
+ (insert message-yank-prefix))
+ (fill-paragraph nil)
+ (goto-char point)
+ (forward-line 2)))
+
(defun message-insert-signature (&optional force)
"Insert a signature. See documentation for the `message-signature' variable."
(interactive (list 0))
(defun message-caesar-buffer-body (&optional rotnum)
"Caesar rotates all letters in the current buffer by 13 places.
-Used to encode/decode possibly offensive messages (commonly in net.jokes).
+Used to encode/decode possiblyun offensive messages (commonly in net.jokes).
With prefix arg, specifies the number of places to rotate each letter forward.
Mail and USENET news headers are not rotated."
(interactive (if current-prefix-arg
the user from the mailer."
(interactive "P")
;; Disabled test.
- (when (if (and nil buffer-file-name)
+ (when (if (and buffer-file-name
+ nil)
(y-or-n-p (format "Send buffer contents as %s message? "
(if (message-mail-p)
(if (message-news-p) "mail and news" "mail")
"news")))
(or (buffer-modified-p)
+ (message-check-element 'unchanged)
(y-or-n-p "No changes in the buffer; really send? ")))
;; Make it possible to undo the coming changes.
(undo-boundary)
(defun message-send-mail-with-mh ()
"Send the prepared message buffer with mh."
(let ((mh-previous-window-config nil)
- (name (make-temp-name
- (concat (file-name-as-directory
- (expand-file-name message-autosave-directory))
- "msg."))))
+ (name (mh-new-draft-name)))
(setq buffer-file-name name)
;; MH wants to generate these headers itself.
(when message-mh-deletable-headers
(defun message-make-organization ()
"Make an Organization header."
(let* ((organization
- (or (getenv "ORGANIZATION")
- (when message-user-organization
+ (when message-user-organization
(if (message-functionp message-user-organization)
(funcall message-user-organization)
- message-user-organization)))))
+ message-user-organization))))
(save-excursion
(message-set-work-buffer)
(cond ((stringp organization)
(string-match "\\." mail-host-address))
mail-host-address)
;; We try `user-mail-address' as a backup.
- ((and (string-match "\\." user-mail)
+ ((and user-mail
+ (string-match "\\." user-mail)
(string-match "@\\(.*\\)\\'" user-mail))
(match-string 1 user-mail))
;; Default to this bogus thing.
headers)
(delete-region (point) (progn (forward-line -1) (point)))
(when message-default-headers
- (insert message-default-headers))
+ (insert message-default-headers)
+ (or (bolp) (insert ?\n)))
(put-text-property
(point)
(progn
(forward-line -1)
(when (message-news-p)
(when message-default-news-headers
- (insert message-default-news-headers))
+ (insert message-default-news-headers)
+ (or (bolp) (insert ?\n)))
(when message-generate-headers-first
(message-generate-headers
(delq 'Lines
(copy-sequence message-required-news-headers))))))
(when (message-mail-p)
(when message-default-mail-headers
- (insert message-default-mail-headers))
+ (insert message-default-mail-headers)
+ (or (bolp) (insert ?\n)))
(when message-generate-headers-first
(message-generate-headers
(delq 'Lines
(unless follow-to
(if (or (not wide)
to-address)
- (setq follow-to (list (cons 'To (or to-address reply-to from))))
+ (progn
+ (setq follow-to (list (cons 'To (or to-address reply-to from))))
+ (when (and wide mct)
+ (push (cons 'Cc mct) follow-to)))
(let (ccalist)
(save-excursion
(message-set-work-buffer)
(cdr local)))))
locals)))
+;;; 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)))