(flyspell-process-localwords): Be case-sensitive.
[bpt/emacs.git] / lisp / mh-e / mh-comp.el
CommitLineData
dda00b2c 1;;; mh-comp.el --- MH-E functions for composing and sending messages
c26cf6c8 2
e495eaec 3;; Copyright (C) 1993, 1995, 1997,
af435184 4;; 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
7382bcae 5
a1b4049d 6;; Author: Bill Wohler <wohler@newt.com>
6e65a812 7;; Maintainer: Bill Wohler <wohler@newt.com>
7382bcae 8;; Keywords: mail
a1b4049d 9;; See: mh-e.el
c26cf6c8 10
60370d40 11;; This file is part of GNU Emacs.
c26cf6c8 12
9b7bc076 13;; GNU Emacs is free software; you can redistribute it and/or modify
c26cf6c8
RS
14;; it under the terms of the GNU General Public License as published by
15;; the Free Software Foundation; either version 2, or (at your option)
16;; any later version.
17
9b7bc076 18;; GNU Emacs is distributed in the hope that it will be useful,
c26cf6c8
RS
19;; but WITHOUT ANY WARRANTY; without even the implied warranty of
20;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21;; GNU General Public License for more details.
22
23;; You should have received a copy of the GNU General Public License
b578f267 24;; along with GNU Emacs; see the file COPYING. If not, write to the
3a35cf56
LK
25;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
26;; Boston, MA 02110-1301, USA.
c26cf6c8
RS
27
28;;; Commentary:
29
dda00b2c
BW
30;; This file includes the functions in the MH-Folder maps that get us
31;; into MH-Letter mode, as well the functions in the MH-Letter mode
32;; that are used to send the mail. Other that those, functions that
33;; are needed in mh-letter.el should be found there.
c26cf6c8 34
847b8219
KH
35;;; Change Log:
36
c26cf6c8
RS
37;;; Code:
38
7094eefe 39(require 'mh-e)
dda00b2c
BW
40(require 'mh-gnus) ;needed because mh-gnus.el not compiled
41(require 'mh-scan)
7094eefe 42
dda00b2c 43(require 'sendmail)
bdcfe844 44
dda00b2c
BW
45(autoload 'easy-menu-add "easymenu")
46(autoload 'mml-insert-tag "mml")
c26cf6c8 47
cee9f5c6
BW
48\f
49
dda00b2c 50;;; Site Customization
847b8219
KH
51
52(defvar mh-send-prog "send"
53 "Name of the MH send program.
54Some sites need to change this because of a name conflict.")
55
a1b4049d
BW
56(defvar mh-redist-background nil
57 "If non-nil redist will be done in background like send.
2dcf34f9
BW
58This allows transaction log to be visible if -watch, -verbose or
59-snoop are used.")
847b8219 60
cee9f5c6
BW
61\f
62
dda00b2c 63;;; Variables
c26cf6c8 64
c26cf6c8
RS
65(defvar mh-comp-formfile "components"
66 "Name of file to be used as a skeleton for composing messages.
2dcf34f9
BW
67
68Default is \"components\".
69
70If not an absolute file name, the file is searched for first in the
71user's MH directory, then in the system MH lib directory.")
c26cf6c8 72
847b8219
KH
73(defvar mh-repl-formfile "replcomps"
74 "Name of file to be used as a skeleton for replying to messages.
2dcf34f9
BW
75
76Default is \"replcomps\".
77
78If not an absolute file name, the file is searched for first in the
79user's MH directory, then in the system MH lib directory.")
847b8219 80
c3d6278e 81(defvar mh-repl-group-formfile "replgroupcomps"
bdcfe844 82 "Name of file to be used as a skeleton for replying to messages.
2dcf34f9 83
f0d73c14 84Default is \"replgroupcomps\".
2dcf34f9
BW
85
86This file is used to form replies to the sender and all recipients of
87a message. Only used if `(mh-variant-p 'nmh)' is non-nil.
88If not an absolute file name, the file is searched for first in the
89user's MH directory, then in the system MH lib directory.")
a1b4049d 90
c26cf6c8 91(defvar mh-rejected-letter-start
bdcfe844 92 (format "^%s$"
c3d9274a
BW
93 (regexp-opt
94 '("Content-Type: message/rfc822" ;MIME MDN
f0d73c14 95 "------ This is a copy of the message, including all the headers. ------";from exim
dda00b2c 96 "--- Below this line is a copy of the message."; from qmail
c3d9274a
BW
97 " ----- Unsent message follows -----" ;from sendmail V5
98 " --------Unsent Message below:" ; from sendmail at BU
99 " ----- Original message follows -----" ;from sendmail V8
100 "------- Unsent Draft" ;from MH itself
101 "---------- Original Message ----------" ;from zmailer
102 " --- The unsent message follows ---" ;from AIX mail system
103 " Your message follows:" ;from MMDF-II
104 "Content-Description: Returned Content" ;1993 KJ sendmail
105 ))))
c26cf6c8
RS
106
107(defvar mh-new-draft-cleaned-headers
847b8219 108 "^Date:\\|^Received:\\|^Message-Id:\\|^From:\\|^Sender:\\|^Errors-To:\\|^Delivery-Date:\\|^Return-Path:"
5a4aad03
BW
109 "Regexp of header lines to remove before offering a message as a new draft\\<mh-folder-mode-map>.
110Used by the \\[mh-edit-again] and \\[mh-extract-rejected-mail] commands.")
c26cf6c8 111
c26cf6c8 112(defvar mh-letter-mode-syntax-table nil
bdcfe844 113 "Syntax table used by MH-E while in MH-Letter mode.")
c26cf6c8
RS
114
115(if mh-letter-mode-syntax-table
116 ()
c3d9274a
BW
117 (setq mh-letter-mode-syntax-table
118 (make-syntax-table text-mode-syntax-table))
119 (modify-syntax-entry ?% "." mh-letter-mode-syntax-table))
c26cf6c8 120
bdcfe844
BW
121(defvar mh-send-args nil
122 "Extra args to pass to \"send\" command.")
123
124(defvar mh-annotate-char nil
125 "Character to use to annotate `mh-sent-from-msg'.")
126
127(defvar mh-annotate-field nil
128 "Field name for message annotation.")
c26cf6c8 129
a66894d8 130(defvar mh-insert-auto-fields-done-local nil
f0d73c14 131 "Buffer-local variable set when `mh-insert-auto-fields' called successfully.")
a66894d8
BW
132(make-variable-buffer-local 'mh-insert-auto-fields-done-local)
133
dda00b2c
BW
134\f
135
136;;; MH-E Entry Points
137
c26cf6c8
RS
138;;;###autoload
139(defun mh-smail ()
b2064e08 140 "Compose a message with the MH mail system.
f0d73c14 141See `mh-send' for more details on composing mail."
c26cf6c8
RS
142 (interactive)
143 (mh-find-path)
144 (call-interactively 'mh-send))
145
b2064e08
BW
146;;;###autoload
147(defun mh-smail-other-window ()
148 "Compose a message with the MH mail system in other window.
149See `mh-send' for more details on composing mail."
150 (interactive)
151 (mh-find-path)
152 (call-interactively 'mh-send-other-window))
153
dda00b2c
BW
154(defun mh-send-other-window (to cc subject)
155 "Compose a message in another window.
156
157See `mh-send' for more information and a description of how the
158TO, CC, and SUBJECT arguments are used."
159 (interactive (list
160 (mh-interactive-read-address "To: ")
161 (mh-interactive-read-address "Cc: ")
162 (mh-interactive-read-string "Subject: ")))
163 (let ((pop-up-windows t))
164 (mh-send-sub to cc subject (current-window-configuration))))
165
c3d9274a 166(defvar mh-error-if-no-draft nil) ;raise error over using old draft
283b03f4 167
283b03f4 168;;;###autoload
c3d6278e 169(defun mh-smail-batch (&optional to subject other-headers &rest ignored)
b2064e08
BW
170 "Compose a message with the MH mail system.
171
2dcf34f9
BW
172This function does not prompt the user for any header fields, and
173thus is suitable for use by programs that want to create a mail
174buffer. Users should use \\[mh-smail] to compose mail.
f0d73c14 175
2dcf34f9 176Optional arguments for setting certain fields include TO,
0d887b77
BW
177SUBJECT, and OTHER-HEADERS. Additional arguments are IGNORED.
178
179This function remains for Emacs 21 compatibility. New
180applications should use `mh-user-agent-compose'."
283b03f4
KH
181 (mh-find-path)
182 (let ((mh-error-if-no-draft t))
016fbe59 183 (mh-send (or to "") "" (or subject ""))))
283b03f4 184
0d887b77
BW
185;;;###autoload
186(define-mail-user-agent 'mh-e-user-agent
187 'mh-user-agent-compose 'mh-send-letter 'mh-fully-kill-draft
188 'mh-before-send-letter-hook)
189
a1b4049d
BW
190;;;###autoload
191(defun mh-user-agent-compose (&optional to subject other-headers continue
c3d9274a
BW
192 switch-function yank-action
193 send-actions)
a1b4049d 194 "Set up mail composition draft with the MH mail system.
0d887b77
BW
195This is the `mail-user-agent' entry point to MH-E. This function
196conforms to the contract specified by `define-mail-user-agent'
197which means that this function should accept the same arguments
198as `compose-mail'.
a1b4049d
BW
199
200The optional arguments TO and SUBJECT specify recipients and the
201initial Subject field, respectively.
202
2dcf34f9
BW
203OTHER-HEADERS is an alist specifying additional header fields.
204Elements look like (HEADER . VALUE) where both HEADER and VALUE
205are strings.
a1b4049d 206
2dcf34f9
BW
207CONTINUE, SWITCH-FUNCTION, YANK-ACTION and SEND-ACTIONS are
208ignored."
a1b4049d
BW
209 (mh-find-path)
210 (let ((mh-error-if-no-draft t))
211 (mh-send to "" subject)
212 (while other-headers
213 (mh-insert-fields (concat (car (car other-headers)) ":")
c3d9274a 214 (cdr (car other-headers)))
a1b4049d 215 (setq other-headers (cdr other-headers)))))
283b03f4 216
dda00b2c
BW
217;; Shush compiler.
218(eval-when-compile (mh-do-in-xemacs (defvar sendmail-coding-system)))
219
220;;;###autoload
221(defun mh-send-letter (&optional arg)
222 "Save draft and send message.
223
224When you are all through editing a message, you send it with this
225command. You can give a prefix argument ARG to monitor the first stage
226of the delivery\; this output can be found in a buffer called \"*MH-E
227Mail Delivery*\".
228
229The hook `mh-before-send-letter-hook' is run at the beginning of
230this command. For example, if you want to check your spelling in
231your message before sending, add the function `ispell-message'.
232
233In case the MH \"send\" program is installed under a different name,
234use `mh-send-prog' to tell MH-E the name."
235 (interactive "P")
236 (run-hooks 'mh-before-send-letter-hook)
237 (if (and (mh-insert-auto-fields t)
238 mh-auto-fields-prompt-flag
239 (goto-char (point-min)))
240 (if (not (y-or-n-p "Auto fields inserted, send? "))
241 (error "Send aborted")))
242 (cond ((mh-mh-directive-present-p)
243 (mh-mh-to-mime))
244 ((or (mh-mml-tag-present-p) (not (mh-ascii-buffer-p)))
245 (mh-mml-to-mime)))
246 (save-buffer)
247 (message "Sending...")
248 (let ((draft-buffer (current-buffer))
249 (file-name buffer-file-name)
250 (config mh-previous-window-config)
251 (coding-system-for-write
252 (if (and (local-variable-p 'buffer-file-coding-system
253 (current-buffer)) ;XEmacs needs two args
254 ;; We're not sure why, but buffer-file-coding-system
255 ;; tends to get set to undecided-unix.
256 (not (memq buffer-file-coding-system
257 '(undecided undecided-unix undecided-dos))))
258 buffer-file-coding-system
259 (or (and (boundp 'sendmail-coding-system) sendmail-coding-system)
260 (and (boundp 'default-buffer-file-coding-system )
261 default-buffer-file-coding-system)
262 'iso-latin-1))))
263 ;; Adding a Message-ID field looks good, makes it easier to search for
264 ;; message in your +outbox, and best of all doesn't break threading for
265 ;; the recipient if you reply to a message in your +outbox.
266 (setq mh-send-args (concat "-msgid " mh-send-args))
267 ;; The default BCC encapsulation will make a MIME message unreadable.
268 ;; With nmh use the -mime arg to prevent this.
269 (if (and (mh-variant-p 'nmh)
270 (mh-goto-header-field "Bcc:")
271 (mh-goto-header-field "Content-Type:"))
272 (setq mh-send-args (concat "-mime " mh-send-args)))
273 (cond (arg
274 (pop-to-buffer mh-mail-delivery-buffer)
275 (erase-buffer)
276 (mh-exec-cmd-output mh-send-prog t "-watch" "-nopush"
277 "-nodraftfolder" mh-send-args file-name)
278 (goto-char (point-max)) ; show the interesting part
279 (recenter -1)
280 (set-buffer draft-buffer)) ; for annotation below
281 (t
282 (mh-exec-cmd-daemon mh-send-prog nil "-nodraftfolder" "-noverbose"
283 mh-send-args file-name)))
284 (if mh-annotate-char
285 (mh-annotate-msg mh-sent-from-msg
286 mh-sent-from-folder
287 mh-annotate-char
288 "-component" mh-annotate-field
289 "-text" (format "\"%s %s\""
290 (mh-get-header-field "To:")
291 (mh-get-header-field "Cc:"))))
292
293 (cond ((or (not arg)
294 (y-or-n-p "Kill draft buffer? "))
295 (kill-buffer draft-buffer)
296 (if config
297 (set-window-configuration config))))
298 (if arg
299 (message "Sending...done")
300 (message "Sending...backgrounded"))))
301
302;;;###autoload
303(defun mh-fully-kill-draft ()
304 "Quit editing and delete draft message.
305
306If for some reason you are not happy with the draft, you can use
307this command to kill the draft buffer and delete the draft
308message. Use the command \\[kill-buffer] if you don't want to
309delete the draft message."
310 (interactive)
311 (if (y-or-n-p "Kill draft message? ")
312 (let ((config mh-previous-window-config))
313 (if (file-exists-p buffer-file-name)
314 (delete-file buffer-file-name))
315 (set-buffer-modified-p nil)
316 (kill-buffer (buffer-name))
317 (message "")
318 (if config
319 (set-window-configuration config)))
320 (error "Message not killed")))
321
322\f
323
324;;; MH-Folder Commands
325
326;; Alphabetical.
327
c3d9274a 328;;;###mh-autoload
b2064e08
BW
329(defun mh-edit-again (message)
330 "Edit a MESSAGE to send it again.
331
2dcf34f9
BW
332If you don't complete a draft for one reason or another, and if
333the draft buffer is no longer available, you can pick your draft
334up again with this command. If you don't use a draft folder, your
335last \"draft\" file will be used. If you use draft folders,
336you'll need to visit the draft folder with \"\\[mh-visit-folder]
337drafts <RET>\", use \\[mh-next-undeleted-msg] to move to the
338appropriate message, and then use \\[mh-edit-again] to prepare
339the message for editing.
b2064e08 340
2dcf34f9
BW
341This command can also be used to take messages that were sent to
342you and to send them to more people.
b2064e08 343
2dcf34f9
BW
344Don't use this command to re-edit a message from a Mailer-Daemon
345who complained that your mail wasn't posted for some reason or
346another (see `mh-extract-rejected-mail').
b2064e08
BW
347
348The default message is the current message.
f0d73c14
BW
349
350See also `mh-send'."
c26cf6c8
RS
351 (interactive (list (mh-get-msg-num t)))
352 (let* ((from-folder mh-current-folder)
c3d9274a
BW
353 (config (current-window-configuration))
354 (draft
355 (cond ((and mh-draft-folder (equal from-folder mh-draft-folder))
b2064e08
BW
356 (pop-to-buffer (find-file-noselect (mh-msg-filename message))
357 t)
358 (rename-buffer (format "draft-%d" message))
bdcfe844
BW
359 ;; Make buffer writable...
360 (setq buffer-read-only nil)
361 ;; If buffer was being used to display the message reinsert
362 ;; from file...
363 (when (eq major-mode 'mh-show-mode)
364 (erase-buffer)
365 (insert-file-contents buffer-file-name))
c3d9274a
BW
366 (buffer-name))
367 (t
b2064e08 368 (mh-read-draft "clean-up" (mh-msg-filename message) nil)))))
c26cf6c8 369 (mh-clean-msg-header (point-min) mh-new-draft-cleaned-headers nil)
a1b4049d 370 (mh-insert-header-separator)
c26cf6c8 371 (goto-char (point-min))
283b03f4 372 (save-buffer)
c26cf6c8 373 (mh-compose-and-send-mail draft "" from-folder nil nil nil nil nil nil
c3d9274a 374 config)
a66894d8
BW
375 (mh-letter-mode-message)
376 (mh-letter-adjust-point)))
c26cf6c8 377
c3d9274a 378;;;###mh-autoload
b2064e08
BW
379(defun mh-extract-rejected-mail (message)
380 "Edit a MESSAGE that was returned by the mail system.
381
2dcf34f9
BW
382This command prepares the message for editing by removing the
383Mailer-Daemon envelope and unneeded header fields. Fix whatever
384addressing problem you had, and send the message again with
385\\[mh-send-letter].
b2064e08
BW
386
387The default message is the current message.
f0d73c14
BW
388
389See also `mh-send'."
c26cf6c8
RS
390 (interactive (list (mh-get-msg-num t)))
391 (let ((from-folder mh-current-folder)
c3d9274a 392 (config (current-window-configuration))
b2064e08 393 (draft (mh-read-draft "extraction" (mh-msg-filename message) nil)))
c26cf6c8
RS
394 (goto-char (point-min))
395 (cond ((re-search-forward mh-rejected-letter-start nil t)
c3d9274a
BW
396 (skip-chars-forward " \t\n")
397 (delete-region (point-min) (point))
398 (mh-clean-msg-header (point-min) mh-new-draft-cleaned-headers nil))
399 (t
f0d73c14 400 (message "Does not appear to be a rejected letter")))
a1b4049d 401 (mh-insert-header-separator)
c26cf6c8 402 (goto-char (point-min))
283b03f4 403 (save-buffer)
b2064e08 404 (mh-compose-and-send-mail draft "" from-folder message
c3d9274a
BW
405 (mh-get-header-field "To:")
406 (mh-get-header-field "From:")
407 (mh-get-header-field "Cc:")
408 nil nil config)
bdcfe844 409 (mh-letter-mode-message)))
c26cf6c8 410
c3d9274a 411;;;###mh-autoload
a66894d8 412(defun mh-forward (to cc &optional range)
2be362c2 413 "Forward message.
a66894d8 414
2dcf34f9
BW
415You are prompted for the TO and CC recipients. You are given a
416draft to edit that looks like it would if you had run the MH
417command \"forw\". You can then add some text.
bdcfe844 418
2dcf34f9
BW
419You can forward several messages by using a RANGE. All of the
420messages in the range are inserted into your draft. Check the
421documentation of `mh-interactive-range' to see how RANGE is read
422in interactive use.
b2064e08 423
d1699462
BW
424The hook `mh-forward-hook' is called on the draft.
425
426See also `mh-compose-forward-as-mime-flag',
427`mh-forward-subject-format', and `mh-send'."
a66894d8
BW
428 (interactive (list (mh-interactive-read-address "To: ")
429 (mh-interactive-read-address "Cc: ")
430 (mh-interactive-range "Forward")))
c26cf6c8 431 (let* ((folder mh-current-folder)
a66894d8 432 (msgs (mh-range-to-msg-list range))
c3d9274a
BW
433 (config (current-window-configuration))
434 (fwd-msg-file (mh-msg-filename (car msgs) folder))
435 ;; forw always leaves file in "draft" since it doesn't have -draft
436 (draft-name (expand-file-name "draft" mh-user-path))
437 (draft (cond ((or (not (file-exists-p draft-name))
00b6a079 438 (y-or-n-p "The file draft exists; discard it? "))
f0d73c14
BW
439 (mh-exec-cmd "forw" "-build"
440 (if (and (mh-variant-p 'nmh)
441 mh-compose-forward-as-mime-flag)
442 "-mime")
924df208
BW
443 mh-current-folder
444 (mh-coalesce-msg-list msgs))
c3d9274a
BW
445 (prog1
446 (mh-read-draft "" draft-name t)
447 (mh-insert-fields "To:" to "Cc:" cc)
448 (save-buffer)))
449 (t
450 (mh-read-draft "" draft-name nil)))))
847b8219 451 (let (orig-from
c3d9274a 452 orig-subject)
41b9a988 453 (save-excursion
c3d9274a
BW
454 (set-buffer (get-buffer-create mh-temp-buffer))
455 (erase-buffer)
456 (insert-file-contents fwd-msg-file)
457 (setq orig-from (mh-get-header-field "From:"))
458 (setq orig-subject (mh-get-header-field "Subject:")))
c26cf6c8 459 (let ((forw-subject
924df208 460 (mh-forwarded-letter-subject orig-from orig-subject)))
c3d9274a
BW
461 (mh-insert-fields "Subject:" forw-subject)
462 (goto-char (point-min))
0c47b17c
BW
463 ;; If using MML, translate MH-style directive
464 (if (equal mh-compose-insertion 'mml)
c3d9274a 465 (save-excursion
a66894d8 466 (goto-char (mh-mail-header-end))
c3d9274a
BW
467 (while
468 (re-search-forward
469 "^#forw \\[\\([^]]+\\)\\] \\(+\\S-+\\) \\(.*\\)$"
470 (point-max) t)
471 (let ((description (if (equal (match-string 1)
472 "forwarded messages")
473 "forwarded message %d"
474 (match-string 1)))
475 (msgs (split-string (match-string 3)))
476 (i 0))
477 (beginning-of-line)
478 (delete-region (point) (progn (forward-line 1) (point)))
479 (dolist (msg msgs)
480 (setq i (1+ i))
481 (mh-mml-forward-message (format description i)
482 folder msg))))))
483 ;; Postition just before forwarded message
484 (if (re-search-forward "^------- Forwarded Message" nil t)
485 (forward-line -1)
a66894d8 486 (goto-char (mh-mail-header-end))
c3d9274a
BW
487 (forward-line 1))
488 (delete-other-windows)
489 (mh-add-msgs-to-seq msgs 'forwarded t)
924df208 490 (mh-compose-and-send-mail draft "" folder msgs
c3d9274a
BW
491 to forw-subject cc
492 mh-note-forw "Forwarded:"
493 config)
a66894d8 494 (mh-letter-mode-message)
f0d73c14
BW
495 (mh-letter-adjust-point)
496 (run-hooks 'mh-forward-hook)))))
c26cf6c8
RS
497
498(defun mh-forwarded-letter-subject (from subject)
bdcfe844
BW
499 "Return a Subject suitable for a forwarded message.
500Original message has headers FROM and SUBJECT."
c26cf6c8 501 (let ((addr-start (string-match "<" from))
c3d9274a 502 (comment (string-match "(" from)))
c26cf6c8 503 (cond ((and addr-start (> addr-start 0))
c3d9274a
BW
504 ;; Full Name <luser@host>
505 (setq from (substring from 0 (1- addr-start))))
506 (comment
507 ;; luser@host (Full Name)
508 (setq from (substring from (1+ comment) (1- (length from)))))))
c26cf6c8
RS
509 (format mh-forward-subject-format from subject))
510
b2064e08
BW
511;;;###mh-autoload
512(defun mh-redistribute (to cc &optional message)
513 "Redistribute a message.
847b8219 514
2dcf34f9
BW
515This command is similar in function to forwarding mail, but it
516does not allow you to edit the message, nor does it add your name
517to the \"From\" header field. It appears to the recipient as if
518the message had come from the original sender. When you run this
519command, you are prompted for the TO and CC recipients. The
520default MESSAGE is the current message.
c26cf6c8 521
af435184 522Also investigate the command \\[mh-edit-again] for another way to
2dcf34f9 523redistribute messages.
b2064e08
BW
524
525See also `mh-redist-full-contents-flag'."
c26cf6c8 526 (interactive (list (mh-read-address "Redist-To: ")
c3d9274a
BW
527 (mh-read-address "Redist-Cc: ")
528 (mh-get-msg-num t)))
b2064e08
BW
529 (or message
530 (setq message (mh-get-msg-num t)))
c26cf6c8
RS
531 (save-window-excursion
532 (let ((folder mh-current-folder)
c3d9274a 533 (draft (mh-read-draft "redistribution"
b2064e08
BW
534 (if mh-redist-full-contents-flag
535 (mh-msg-filename message)
c3d9274a
BW
536 nil)
537 nil)))
c26cf6c8
RS
538 (mh-goto-header-end 0)
539 (insert "Resent-To: " to "\n")
540 (if (not (equal cc "")) (insert "Resent-cc: " cc "\n"))
924df208
BW
541 (mh-clean-msg-header
542 (point-min)
543 "^Message-Id:\\|^Received:\\|^Return-Path:\\|^Sender:\\|^Date:\\|^From:"
544 nil)
c26cf6c8
RS
545 (save-buffer)
546 (message "Redistributing...")
924df208
BW
547 (let ((env "mhdist=1"))
548 ;; Setup environment...
b2064e08
BW
549 (setq env (concat env " mhaltmsg="
550 (if mh-redist-full-contents-flag
551 buffer-file-name
552 (mh-msg-filename message folder))))
553 (unless mh-redist-full-contents-flag
924df208
BW
554 (setq env (concat env " mhannotate=1")))
555 ;; Redistribute...
556 (if mh-redist-background
557 (mh-exec-cmd-env-daemon env mh-send-prog nil buffer-file-name)
558 (mh-exec-cmd-error env mh-send-prog "-push" buffer-file-name))
559 ;; Annotate...
b2064e08 560 (mh-annotate-msg message folder mh-note-dist
924df208
BW
561 "-component" "Resent:"
562 "-text" (format "\"%s %s\"" to cc)))
c26cf6c8
RS
563 (kill-buffer draft)
564 (message "Redistributing...done"))))
565
c3d9274a 566;;;###mh-autoload
bdcfe844 567(defun mh-reply (message &optional reply-to includep)
b2064e08 568 "Reply to a MESSAGE.
f0d73c14 569
2dcf34f9
BW
570When you reply to a message, you are first prompted with \"Reply
571to whom?\" (unless the optional argument REPLY-TO is provided).
572You have several choices here.
b2064e08
BW
573
574 Response Reply Goes To
575
2dcf34f9
BW
576 from The person who sent the message. This is the
577 default, so <RET> is sufficient.
b2064e08
BW
578
579 to Replies to the sender, plus all recipients in the
580 \"To:\" header field.
581
582 all
583 cc Forms a reply to the sender, plus all recipients.
584
2dcf34f9
BW
585Depending on your answer, \"repl\" is given a different argument
586to form your reply. Specifically, a choice of \"from\" or none at
587all runs \"repl -nocc all\", and a choice of \"to\" runs \"repl
588-cc to\". Finally, either \"cc\" or \"all\" runs \"repl -cc all
589-nocc me\".
b2064e08 590
2dcf34f9
BW
591Two windows are then created. One window contains the message to
592which you are replying in an MH-Show buffer. Your draft, in
4023e353 593MH-Letter mode (see `mh-letter-mode'), is in the other window.
b2064e08 594
2dcf34f9
BW
595If you supply a prefix argument INCLUDEP, the message you are
596replying to is inserted in your reply after having first been run
597through \"mhl\" with the format file \"mhl.reply\".
b2064e08 598
2dcf34f9
BW
599Alternatively, you can customize the option `mh-yank-behavior'
600and choose one of its \"Automatically\" variants to do the same
601thing. If you do so, the prefix argument has no effect.
b2064e08 602
2dcf34f9
BW
603Another way to include the message automatically in your draft is
604to use \"repl: -filter repl.filter\" in your MH profile.
b2064e08 605
2dcf34f9
BW
606If you wish to customize the header or other parts of the reply
607draft, please see \"repl\" and \"mh-format\".
b2064e08 608
2dcf34f9
BW
609See also `mh-reply-show-message-flag',
610`mh-reply-default-reply-to', and `mh-send'."
bdcfe844
BW
611 (interactive (list
612 (mh-get-msg-num t)
613 (let ((minibuffer-help-form
614 "from => Sender only\nto => Sender and primary recipients\ncc or all => Sender and all recipients"))
615 (or mh-reply-default-reply-to
078cb314 616 (completing-read "Reply to whom (default from): "
bdcfe844
BW
617 '(("from") ("to") ("cc") ("all"))
618 nil
619 t)))
620 current-prefix-arg))
621 (let* ((folder mh-current-folder)
622 (show-buffer mh-show-buffer)
623 (config (current-window-configuration))
624 (group-reply (or (equal reply-to "cc") (equal reply-to "all")))
f0d73c14 625 (form-file (cond ((and (mh-variant-p 'nmh 'mu-mh) group-reply
bdcfe844
BW
626 (stringp mh-repl-group-formfile))
627 mh-repl-group-formfile)
628 ((stringp mh-repl-formfile) mh-repl-formfile)
629 (t nil))))
630 (message "Composing a reply...")
631 (mh-exec-cmd "repl" "-build" "-noquery" "-nodraftfolder"
632 (if form-file
633 (list "-form" form-file))
634 mh-current-folder message
635 (cond ((or (equal reply-to "from") (equal reply-to ""))
636 '("-nocc" "all"))
637 ((equal reply-to "to")
638 '("-cc" "to"))
f0d73c14 639 (group-reply (if (mh-variant-p 'nmh 'mu-mh)
bdcfe844
BW
640 '("-group" "-nocc" "me")
641 '("-cc" "all" "-nocc" "me"))))
0c47b17c
BW
642 (cond ((or (eq mh-yank-behavior 'autosupercite)
643 (eq mh-yank-behavior 'autoattrib))
c3d9274a
BW
644 '("-noformat"))
645 (includep '("-filter" "mhl.reply"))
646 (t '())))
bdcfe844
BW
647 (let ((draft (mh-read-draft "reply"
648 (expand-file-name "reply" mh-user-path)
649 t)))
650 (delete-other-windows)
651 (save-buffer)
a1506d29 652
bdcfe844
BW
653 (let ((to (mh-get-header-field "To:"))
654 (subject (mh-get-header-field "Subject:"))
655 (cc (mh-get-header-field "Cc:")))
656 (goto-char (point-min))
657 (mh-goto-header-end 1)
658 (or includep
659 (not mh-reply-show-message-flag)
660 (mh-in-show-buffer (show-buffer)
661 (mh-display-msg message folder)))
662 (mh-add-msgs-to-seq message 'answered t)
663 (message "Composing a reply...done")
664 (mh-compose-and-send-mail draft "" folder message to subject cc
665 mh-note-repl "Replied:" config))
0c47b17c
BW
666 (when (and (or (eq 'autosupercite mh-yank-behavior)
667 (eq 'autoattrib mh-yank-behavior))
bdcfe844
BW
668 (eq (mh-show-buffer-message-number) mh-sent-from-msg))
669 (undo-boundary)
670 (mh-yank-cur-msg))
671 (mh-letter-mode-message))))
c26cf6c8 672
c3d9274a 673;;;###mh-autoload
c26cf6c8 674(defun mh-send (to cc subject)
b2064e08
BW
675 "Compose a message.
676
2dcf34f9
BW
677Your letter appears in an Emacs buffer whose mode is
678MH-Letter (see `mh-letter-mode').
b2064e08 679
2dcf34f9
BW
680The arguments TO, CC, and SUBJECT can be used to prefill the
681draft fields or suppress the prompts if `mh-compose-prompt-flag'
682is on. They are also passed to the function set in the option
683`mh-compose-letter-function'.
b2064e08
BW
684
685See also `mh-insert-x-mailer-flag' and `mh-letter-mode-hook'.
686
2dcf34f9
BW
687Outside of an MH-Folder buffer (`mh-folder-mode'), you must call
688either \\[mh-smail] or \\[mh-smail-other-window] to compose a new
689message."
c26cf6c8 690 (interactive (list
a66894d8
BW
691 (mh-interactive-read-address "To: ")
692 (mh-interactive-read-address "Cc: ")
693 (mh-interactive-read-string "Subject: ")))
c26cf6c8
RS
694 (let ((config (current-window-configuration)))
695 (delete-other-windows)
696 (mh-send-sub to cc subject config)))
697
dda00b2c
BW
698\f
699
700;;; Support Routines
701
702(defun mh-interactive-read-address (prompt)
703 "Read an address.
704If `mh-compose-prompt-flag' is non-nil, then read an address with
705PROMPT.
706Otherwise return the empty string."
707 (if mh-compose-prompt-flag (mh-read-address prompt) ""))
708
709(defun mh-interactive-read-string (prompt)
710 "Read a string.
711If `mh-compose-prompt-flag' is non-nil, then read a string with
712PROMPT.
713Otherwise return the empty string."
714 (if mh-compose-prompt-flag (read-string prompt) ""))
715
c3d9274a 716;;;###mh-autoload
dda00b2c
BW
717(defun mh-show-buffer-message-number (&optional buffer)
718 "Message number of displayed message in corresponding show buffer.
b2064e08 719
dda00b2c
BW
720Return nil if show buffer not displayed.
721If in `mh-letter-mode', don't display the message number being replied
722to, but rather the message number of the show buffer associated with
723our originating folder buffer.
724Optional argument BUFFER can be used to specify the buffer."
725 (save-excursion
726 (if buffer
727 (set-buffer buffer))
728 (cond ((eq major-mode 'mh-show-mode)
729 (let ((number-start (mh-search-from-end ?/ buffer-file-name)))
730 (string-to-number (substring buffer-file-name
731 (1+ number-start)))))
732 ((and (eq major-mode 'mh-folder-mode)
733 mh-show-buffer
734 (get-buffer mh-show-buffer))
735 (mh-show-buffer-message-number mh-show-buffer))
736 ((and (eq major-mode 'mh-letter-mode)
737 mh-sent-from-folder
738 (get-buffer mh-sent-from-folder))
739 (mh-show-buffer-message-number mh-sent-from-folder))
740 (t
741 nil))))
c26cf6c8 742
c26cf6c8 743(defun mh-send-sub (to cc subject config)
bdcfe844
BW
744 "Do the real work of composing and sending a letter.
745Expects the TO, CC, and SUBJECT fields as arguments.
746CONFIG is the window configuration before sending mail."
c26cf6c8 747 (let ((folder mh-current-folder)
c3d9274a 748 (msg-num (mh-get-msg-num nil)))
c26cf6c8
RS
749 (message "Composing a message...")
750 (let ((draft (mh-read-draft
c3d9274a
BW
751 "message"
752 (let (components)
753 (cond
754 ((file-exists-p
755 (setq components
756 (expand-file-name mh-comp-formfile mh-user-path)))
757 components)
758 ((file-exists-p
759 (setq components
760 (expand-file-name mh-comp-formfile mh-lib)))
761 components)
c3d9274a 762 (t
05227fbe
BW
763 (error "Can't find %s in %s or %s"
764 mh-comp-formfile mh-user-path mh-lib))))
c3d9274a 765 nil)))
c26cf6c8
RS
766 (mh-insert-fields "To:" to "Subject:" subject "Cc:" cc)
767 (goto-char (point-max))
c26cf6c8 768 (mh-compose-and-send-mail draft "" folder msg-num
c3d9274a
BW
769 to subject cc
770 nil nil config)
a66894d8
BW
771 (mh-letter-mode-message)
772 (mh-letter-adjust-point))))
c26cf6c8
RS
773
774(defun mh-read-draft (use initial-contents delete-contents-file)
bdcfe844 775 "Read draft file into a draft buffer and make that buffer the current one.
2dcf34f9
BW
776
777USE is a message used for prompting about the intended use of the
778message.
bdcfe844 779INITIAL-CONTENTS is filename that is read into an empty buffer, or nil
2dcf34f9 780if buffer should not be modified. Delete the initial-contents file if
bdcfe844
BW
781DELETE-CONTENTS-FILE flag is set.
782Returns the draft folder's name.
2dcf34f9
BW
783If the draft folder facility is enabled in ~/.mh_profile, a new buffer
784is used each time and saved in the draft folder. The draft file can
785then be reused."
c26cf6c8 786 (cond (mh-draft-folder
c3d9274a
BW
787 (let ((orig-default-dir default-directory)
788 (draft-file-name (mh-new-draft-name)))
789 (pop-to-buffer (generate-new-buffer
790 (format "draft-%s"
791 (file-name-nondirectory draft-file-name))))
792 (condition-case ()
793 (insert-file-contents draft-file-name t)
794 (file-error))
795 (setq default-directory orig-default-dir)))
796 (t
797 (let ((draft-name (expand-file-name "draft" mh-user-path)))
798 (pop-to-buffer "draft") ; Create if necessary
799 (if (buffer-modified-p)
800 (if (y-or-n-p "Draft has been modified; kill anyway? ")
801 (set-buffer-modified-p nil)
802 (error "Draft preserved")))
803 (setq buffer-file-name draft-name)
804 (clear-visited-file-modtime)
805 (unlock-buffer)
806 (cond ((and (file-exists-p draft-name)
807 (not (equal draft-name initial-contents)))
808 (insert-file-contents draft-name)
809 (delete-file draft-name))))))
c26cf6c8 810 (cond ((and initial-contents
c3d9274a
BW
811 (or (zerop (buffer-size))
812 (if (y-or-n-p
813 (format "A draft exists. Use for %s? " use))
814 (if mh-error-if-no-draft
815 (error "A prior draft exists"))
816 t)))
817 (erase-buffer)
818 (insert-file-contents initial-contents)
819 (if delete-contents-file (delete-file initial-contents))))
c26cf6c8
RS
820 (auto-save-mode 1)
821 (if mh-draft-folder
c3d9274a 822 (save-buffer)) ; Do not reuse draft name
c26cf6c8
RS
823 (buffer-name))
824
c26cf6c8 825(defun mh-new-draft-name ()
bdcfe844 826 "Return the pathname of folder for draft messages."
c26cf6c8
RS
827 (save-excursion
828 (mh-exec-cmd-quiet t "mhpath" mh-draft-folder "new")
829 (buffer-substring (point-min) (1- (point-max)))))
830
c26cf6c8 831(defun mh-insert-fields (&rest name-values)
bdcfe844
BW
832 "Insert the NAME-VALUES pairs in the current buffer.
833If the field exists, append the value to it.
834Do not insert any pairs whose value is the empty string."
c26cf6c8
RS
835 (let ((case-fold-search t))
836 (while name-values
837 (let ((field-name (car name-values))
c3d9274a 838 (value (car (cdr name-values))))
f0d73c14
BW
839 (if (not (string-match "^.*:$" field-name))
840 (setq field-name (concat field-name ":")))
a2c30782
BW
841 (cond ((or (null value)
842 (equal value ""))
c3d9274a
BW
843 nil)
844 ((mh-position-on-field field-name)
845 (insert " " (or value "")))
846 (t
847 (insert field-name " " value "\n")))
848 (setq name-values (cdr (cdr name-values)))))))
c26cf6c8 849
dda00b2c
BW
850(defun mh-compose-and-send-mail (draft send-args
851 sent-from-folder sent-from-msg
852 to subject cc
853 annotate-char annotate-field
854 config)
855 "Edit and compose a draft message in buffer DRAFT and send or save it.
856SEND-ARGS is the argument passed to the send command.
857SENT-FROM-FOLDER is buffer containing scan listing of current folder,
858or nil if none exists.
859SENT-FROM-MSG is the message number or sequence name or nil.
860The TO, SUBJECT, and CC fields are passed to the
861`mh-compose-letter-function'.
862If ANNOTATE-CHAR is non-null, it is used to notate the scan listing of
863the message. In that case, the ANNOTATE-FIELD is used to build a
864string for `mh-annotate-msg'.
865CONFIG is the window configuration to restore after sending the
866letter."
867 (pop-to-buffer draft)
868 (mh-letter-mode)
847b8219 869
dda00b2c
BW
870 ;; Insert identity.
871 (mh-insert-identity mh-identity-default t)
872 (mh-identity-make-menu)
873 (mh-identity-add-menu)
c26cf6c8 874
dda00b2c
BW
875 ;; Insert extra fields.
876 (mh-insert-x-mailer)
877 (mh-insert-x-face)
c26cf6c8 878
dda00b2c 879 (mh-letter-hide-all-skipped-fields)
924df208 880
dda00b2c
BW
881 (setq mh-sent-from-folder sent-from-folder)
882 (setq mh-sent-from-msg sent-from-msg)
883 (setq mh-send-args send-args)
884 (setq mh-annotate-char annotate-char)
885 (setq mh-annotate-field annotate-field)
886 (setq mh-previous-window-config config)
887 (setq mode-line-buffer-identification (list " {%b}"))
888 (mh-logo-display)
889 (mh-make-local-hook 'kill-buffer-hook)
890 (add-hook 'kill-buffer-hook 'mh-tidy-draft-buffer nil t)
891 (if (and (boundp 'mh-compose-letter-function)
892 mh-compose-letter-function)
893 ;; run-hooks will not pass arguments.
894 (let ((value mh-compose-letter-function))
895 (if (and (listp value) (not (eq (car value) 'lambda)))
896 (while value
897 (funcall (car value) to subject cc)
898 (setq value (cdr value)))
899 (funcall mh-compose-letter-function to subject cc)))))
bdcfe844 900
a1b4049d 901(defun mh-insert-x-mailer ()
bdcfe844
BW
902 "Append an X-Mailer field to the header.
903The versions of MH-E, Emacs, and MH are shown."
a1b4049d 904 ;; Lazily initialize mh-x-mailer-string.
a66894d8 905 (when (and mh-insert-x-mailer-flag (null mh-x-mailer-string))
f0d73c14
BW
906 (setq mh-x-mailer-string
907 (format "MH-E %s; %s; %sEmacs %s"
908 mh-version mh-variant-in-use
909 (if mh-xemacs-flag "X" "GNU ")
910 (cond ((not mh-xemacs-flag) emacs-version)
911 ((string-match "[0-9.]*\\( +\([ a-z]+[0-9]+\)\\)?"
912 emacs-version)
913 (match-string 0 emacs-version))
914 (t (format "%s.%s" emacs-major-version
915 emacs-minor-version))))))
a1b4049d
BW
916 ;; Insert X-Mailer, but only if it doesn't already exist.
917 (save-excursion
a66894d8
BW
918 (when (and mh-insert-x-mailer-flag
919 (null (mh-goto-header-field "X-Mailer")))
c3d9274a 920 (mh-insert-fields "X-Mailer:" mh-x-mailer-string))))
a1b4049d 921
dda00b2c
BW
922(defun mh-insert-x-face ()
923 "Append X-Face, Face or X-Image-URL field to header.
924If the field already exists, this function does nothing."
925 (when (and (file-exists-p mh-x-face-file)
926 (file-readable-p mh-x-face-file))
927 (save-excursion
928 (unless (or (mh-position-on-field "X-Face")
929 (mh-position-on-field "Face")
930 (mh-position-on-field "X-Image-URL"))
931 (save-excursion
932 (goto-char (+ (point) (cadr (insert-file-contents mh-x-face-file))))
933 (if (not (looking-at "^"))
934 (insert "\n")))
935 (unless (looking-at "\\(X-Face\\|Face\\|X-Image-URL\\): ")
936 (insert "X-Face: "))))))
937
dda00b2c
BW
938(defun mh-tidy-draft-buffer ()
939 "Run when a draft buffer is destroyed."
940 (let ((buffer (get-buffer mh-recipients-buffer)))
941 (if buffer
942 (kill-buffer buffer))))
943
944(defun mh-letter-mode-message ()
945 "Display a help message for users of `mh-letter-mode'.
946This should be the last function called when composing the draft."
947 (message "%s" (substitute-command-keys
948 (concat "Type \\[mh-send-letter] to send message, "
949 "\\[mh-help] for help"))))
950
951(defun mh-letter-adjust-point ()
952 "Move cursor to first header field if are using the no prompt mode."
953 (unless mh-compose-prompt-flag
954 (goto-char (point-max))
955 (mh-letter-next-header-field)))
956
957(defun mh-annotate-msg (msg buffer note &rest args)
958 "Mark MSG in BUFFER with character NOTE and annotate message with ARGS.
959MSG can be a message number, a list of message numbers, or a
960sequence."
961 (apply 'mh-exec-cmd "anno" buffer
962 (if (listp msg) (append msg args) (cons msg args)))
963 (save-excursion
964 (cond ((get-buffer buffer) ; Buffer may be deleted
965 (set-buffer buffer)
966 (mh-iterate-on-range nil msg
967 (mh-notate nil note
968 (+ mh-cmd-note mh-scan-field-destination-offset)))))))
969
dda00b2c
BW
970(defun mh-insert-header-separator ()
971 "Insert `mh-mail-header-separator', if absent."
972 (save-excursion
973 (goto-char (point-min))
974 (rfc822-goto-eoh)
975 (if (looking-at "$")
976 (insert mh-mail-header-separator))))
bdcfe844 977
a66894d8
BW
978;;;###mh-autoload
979(defun mh-insert-auto-fields (&optional non-interactive)
3b463df0 980 "Insert custom fields if recipient is found in `mh-auto-fields-list'.
a66894d8 981
af435184
BW
982Sets buffer-local `mh-insert-auto-fields-done-local' if header
983fields were added. If NON-INTERACTIVE is non-nil, perform actions
984quietly and only if `mh-insert-auto-fields-done-local' is nil.
2dcf34f9
BW
985
986An `identity' entry is skipped if one was already entered
987manually.
f0d73c14
BW
988
989Return t if fields added; otherwise return nil."
a66894d8 990 (interactive)
f0d73c14
BW
991 (when (or (not non-interactive)
992 (not mh-insert-auto-fields-done-local))
a66894d8 993 (save-excursion
f0d73c14
BW
994 (when (and (or (mh-goto-header-field "To:")
995 (mh-goto-header-field "cc:")))
996 (let ((list mh-auto-fields-list)
997 (fields-inserted nil))
a66894d8
BW
998 (while list
999 (let ((regexp (nth 0 (car list)))
1000 (entries (nth 1 (car list))))
1001 (when (mh-regexp-in-field-p regexp "To:" "cc:")
1002 (setq mh-insert-auto-fields-done-local t)
f0d73c14 1003 (setq fields-inserted t)
a66894d8 1004 (if (not non-interactive)
f0d73c14 1005 (message "Fields for %s added" regexp))
a66894d8
BW
1006 (let ((entry-list entries))
1007 (while entry-list
1008 (let ((field (caar entry-list))
1009 (value (cdar entry-list)))
1010 (cond
f0d73c14 1011 ((equal ":identity" field)
dda00b2c
BW
1012 (when
1013 ;;(and (not mh-identity-local)
a05fcb7d 1014 ;; Bug 1204506. But do we need to be able
dda00b2c
BW
1015 ;; to set an identity manually that won't be
1016 ;; overridden by mh-insert-auto-fields?
1017 (assoc value mh-identity-list)
1018 ;;)
a66894d8
BW
1019 (mh-insert-identity value)))
1020 (t
1021 (mh-modify-header-field field value
1022 (equal field "From")))))
1023 (setq entry-list (cdr entry-list))))))
f0d73c14
BW
1024 (setq list (cdr list)))
1025 fields-inserted)))))
924df208
BW
1026
1027(defun mh-modify-header-field (field value &optional overwrite-flag)
1028 "To header FIELD add VALUE.
2dcf34f9
BW
1029If OVERWRITE-FLAG is non-nil then the old value, if present, is
1030discarded."
a66894d8
BW
1031 (cond ((and overwrite-flag
1032 (mh-goto-header-field (concat field ":")))
1033 (insert " " value)
d5dc8c56 1034 (delete-region (point) (mh-line-end-position)))
a66894d8
BW
1035 ((and (not overwrite-flag)
1036 (mh-regexp-in-field-p (concat "\\b" value "\\b") field))
1037 ;; Already there, do nothing.
1038 )
1039 ((and (not overwrite-flag)
1040 (mh-goto-header-field (concat field ":")))
1041 (insert " " value ","))
1042 (t
1043 (mh-goto-header-end 0)
1044 (insert field ": " value "\n"))))
1045
dda00b2c
BW
1046(defun mh-regexp-in-field-p (regexp &rest fields)
1047 "Non-nil means REGEXP was found in FIELDS."
1048 (save-excursion
1049 (let ((search-result nil)
1050 (field))
1051 (while fields
1052 (setq field (car fields))
1053 (if (and (mh-goto-header-field field)
1054 (re-search-forward
1055 regexp (save-excursion (mh-header-field-end)(point)) t))
1056 (setq fields nil
1057 search-result t)
1058 (setq fields (cdr fields))))
1059 search-result)))
f0d73c14
BW
1060
1061(defun mh-ascii-buffer-p ()
1062 "Check if current buffer is entirely composed of ASCII.
2dcf34f9
BW
1063The function doesn't work for XEmacs since `find-charset-region'
1064doesn't exist there."
f0d73c14
BW
1065 (loop for charset in (mh-funcall-if-exists
1066 find-charset-region (point-min) (point-max))
1067 unless (eq charset 'ascii) return nil
1068 finally return t))
c26cf6c8 1069
bdcfe844
BW
1070(provide 'mh-comp)
1071
cee9f5c6
BW
1072;; Local Variables:
1073;; indent-tabs-mode: nil
1074;; sentence-end-double-space: nil
1075;; End:
60370d40 1076
cee9f5c6 1077;; arch-tag: 62865511-e610-4923-b0b5-f45a8ab70a34
60370d40 1078;;; mh-comp.el ends here