Draft Message Template Files

[previous] [next] [table of contents] [index]

When you start to compose a mail message with MH, the MH command (comp, repl, etc.) reads a template file for the draft message. Because xmh, exmh and mh-e call MH commands to build their drafts, these same template files also set those message headers.

How the Draft Message is Built

This section explains how commands like comp and forw create a draft message from their template files. Four sections explain how the individual template files are used.

Each mail composition command has its own template file, as shown in the next Table. A file from your MH directory will be used if you've put one there. Otherwise, the system default in the MH library directory is used.

Table: Draft Message Template Filenames

Program        Filename
comp components repl replcomps forw forwcomps forw -digest digestcomps dist distcomps
For instance, the default template file for comp, named components, looks like this (unless someone on your system has changed it):
To:
cc:
Subject:
-------
When you start a mail-composition program like comp, the program reads its template file and builds a draft file. For comp and dist, this is easy -- just copy the template file into the draft file. The forw command copies the template file and the forwarded message(s) into the draft file. The forw -digest and repl commands read formatting rules (mh-format strings) from the template file. For instance, here's a line from the default replcomps file:
%<{subject}Subject: Re: %{subject}\n%>\
That line says, "If the original message had a Subject: field, output Subject: Re: followed by the original subject text and a newline character." (See The replcomps File and MH Format Strings.)

After the MH program has built a draft file, it starts whatnow. Then, whatnow starts your message editor -- by default, it's prompter (it may be different at your site).

Let's look at what prompter does with the draft file. (If you'd like to see some sample draft files while you read this description, look back at the Figures Sending a message. Step 1: Making draft from template and Sending a message. Steps 2-4: Draft message, before and after prompter edits it. For an overview of the whole process of sending messages, see the Section Overview: Sending MH Messages.

  1. When it reads a draft header line which is an empty field -- a line that ends with a colon (:) -- prompter prints that and a space to the screen and leaves the cursor after the space. For example, when prompter reads the line:
    To:
    
    it prompts you with To: and leaves the cursor there. Then:
  2. Each time you press RETURN, prompter reads the next line from the draft file. If the line is an empty field, prompter works like step 1 above. If a line in the draft file already has something after the colon, like this:
    Reply-to: ehuser@bigmachine.xxx.yyy.zzz
    
    then prompter won't stop or prompt you. It'll leave the field in the draft message.
  3. When prompter sees a separator line (a blank line or a line with only dashes) as it's reading the header from the draft file, it assumes that the separator line is the start of the message body. From here, prompter changes its behavior -- instead of looking for header fields and prompting you, it starts processing the message body. One of three things will happen as prompter processes the body:
To add or change the fields in a header, you can edit the header (by starting an editor from the What now? prompt) when you compose the message. Or you can make your own private template files, as the next four sections explain.

The components File

The comp command uses this file. It's a pretty basic file; there's an explanation at How the Draft Message is Built.

My components file (in my MH directory) looks like this:

Reply-to: jpeek@jpeek.com
X-Mailer: MH 6.8.3
To:
cc:
Bcc:
Fcc: outbox
Subject:
-------

The Section Fields You Add to a Header explains Fcc:, Bcc:, Reply-to:, and X-. The X-Mailer: helps me identify messages I've sent with MH and does a little bragging, too. :-)

The replcomps File

The repl command builds the header of your draft reply automatically. The default reply header looks like this (the italicized text comes from those fields of the message you're replying to):
To: Reply-To or From
cc: cc, To, and yourself
Fcc: from -fcc switch, if any
Subject: Re: Subject
In-reply-to: Your message of "Date."
           Message-Id
That's set up in the system replcomps file. You can customize the heading and the way that fields are filled in by making your own replcomps file. To do this well, you'll need to study the Chapter MH Formatting. But you can do a lot by imitating the changes I show you here and by experimenting. Ready? Let's dig in. The next Example is a copy of the default replcomps file in MH 6.8.3. An Example at the end of this section shows a copy of the updated replcomps file.

NOTE for users of the online version of this book: The next example is followed by long explanation. To avoid jumping between the example and its explanation, it's a good idea to open a new browser window to show the example. (Check your browser's menu for a command like New Web Browser or Open in New Window). Then, use the original browser to read the explanation while you view the example in the second browser window.

Example: Default MH 6.8+ replcomps file

 1> %(lit)%(formataddr %<{reply-to}%?{from}%?{sender}%?{return-path}%>)\
 2> %<(nonnull)%(void(width))%(putaddr To: )\n%>\
 3> %(lit)%(formataddr{to})%(formataddr{cc})%(formataddr(me))\
 4> %<(nonnull)%(void(width))%(putaddr cc: )\n%>\
 5> %<{fcc}Fcc: %{fcc}\n%>\
 6> %<{subject}Subject: Re: %{subject}\n%>\
 7> %<{date}In-reply-to: Your message of "\
 8> %<(nodate{date})%{date}%|%(pretty{date})%>."%<{message-id}
 9>              %{message-id}%>\n%>\
10> --------
Okay. One step at a time. I'll show you the important part of each line and how you might change it. Or, to go to the explanation of a particular line, click on the line number in the example above.
  1. Lines 1-2 build a To: address field for the draft. The format of line 1 changed in MH 6.8. If you're using a version of MH before 6.8, click here to read the pre-6.8 explanation instead!

    This is the format of lines 1-2 in MH 6.8 and later:

    %(lit)%(formataddr %<{reply-to}%?{from}%?{sender}%?{return-path}%>)\
    %<(nonnull)%(void(width))%(putaddr To: )\n%>\
    
    Those lines look for the best address in the original message. The %(lit) erases a storage register that'll hold the address. The %(formataddr ...) formats an address and stores it in the register. The rest of line 1, the argument to formataddr, chooses the address:
    %<{reply-to}%?{from}%?{sender}%?{return-path}%>
    
    It's an if-else if-else test. It means: If none of those tests found the address they needed, we don't have a To: address for the reply.

    Line 2 starts with a test (%<) that runs the (nonnull) function to see whether formataddr saved an address in line 1. If so, %(void(width)) saves the width of the address. (The Section scan Format Strings has more information about the string and numeric registers where those values are saved.) The %(putaddr To: )\n uses a function named putaddr. It gets the address field that was saved in line 1 and prints To: followed by the address and a newline character (\n). We've got the To: address, if any; the %> ends the test.

    The rest of the replcomps file is the same in all recent versions.

  2. Lines 3-4 of the default replcomps file build a cc: address field:
    %(lit)%(formataddr{to})%(formataddr{cc})%(formataddr(me))\
    %<(nonnull)%(void(width))%(putaddr cc: )\n%>\
    
    It's something like the To: field, but it doesn't have the if-else tests. Instead, it grabs all the To: and cc: addresses from the original message. It also includes your address (with formataddr(me)).

    Notice that line 3 has three separate calls to formataddr -- there are no %<if%|else%> tests. That's why it takes all of the addresses from the original message, not just the first one it finds.

    I get mail from hosts that run other operating systems and other mailers. The messages can have header fields, like the ones below, that list addresses where the message was delivered:

    X-Vmsmail-Cc: lonie%ahost@englvax.xyz.edu
    X-To: nelson@mvus.bitnet
    
    Because those addresses aren't in the To: or cc: fields on the message I get, repl won't let me reply there. I usually want my reply to go to those addresses, too. To fix that, I changed line 3 to include those fields and more. My fix made it pretty long, so I also split it onto three lines. In my edited replcomps, the lines are:
    %(lit)%(formataddr{to})%(formataddr{cc})\
    %(formataddr{x-vmsmail-to})%(formataddr{x-vmsmail-cc})\
    %(formataddr{x-to})%(formataddr{x-cc})%(formataddr(me))\
    
    The repl -query switch (Section Selective Replies with -query) helps me wade through this bunch of addresses.
  3. Lines 5-6 of the default replcomps file work about the same way -- they make the Fcc: and Subject: fields:
    %<{fcc}Fcc: %{fcc}\n%>\
    %<{subject}Subject: Re: %{subject}\n%>\
    
    Let's look at line 5. The %< tells repl to test for a -fcc switch ({fcc}) on the command line or in the MH profile -- if there is one, it outputs Fcc: with the folder name (%{fcc}) and a newline (\n) after it.

    I like to be able to add another Fcc: field to my draft because I usually don't remember to use -fcc on the command line; I want to be prompted. So I put another line in my replcomps file, right after line 5:

    Fcc:
    
    When I start repl, it fills in the To:, cc: and the first Fcc: field (if any) automatically, as explained above. Then repl copies the empty Fcc: field into the draft. As prompter reads the draft, it skips right past those complete fields. But prompter stops at this second Fcc: field and prompts for a folder name. If I don't want to send any other Fcc:'s, I just press RETURN; prompter will delete the empty field.

    If the incoming mail doesn't have a subject, the test on line 6 will see that and not add a subject to the reply. I'd like a choice: If there's no subject, I want to be prompted. So I've changed line 6 to this:

    Subject: %<{subject}Re: %{subject}%>\n\
    
    Compare that to the original version and you'll see two changes: First, I moved the Subject: (and a space after it) outside of the control escape. Now replcomps always outputs Subject: -- whether the original message has a subject or not. Second, I always need to have a newline (\n) output at the end of the Subject: field, whether it has a subject or not. So I moved the newline outside the control escape.

    This takes advantage of the way that prompter works; review the Section Editor-next if you need to. If there's a subject, replcomps outputs Subject: Re: original-subject; prompter keeps that line in the draft. Otherwise, prompter prompts me with Subject:; I can either fill in a subject -- or press RETURN and prompter will delete the empty Subject: field.

  4. These three lines of of the default replcomps file make the one In-reply-to: field of the reply header:
    7>  %<{date}In-reply-to: Your message of "\
    8>  %<(nodate{date})%{date}%|%(pretty{date})%>."%<{message-id}
    9>               %{message-id}%>\n%>\
    
    Because there's no newline (\n) until the end of this, repl will format it to fit the header neatly.

    One thing I don't like about this format is that the field says: "In-reply-to: Your message of ...". Sometimes -- like when I'm replying to a list of people -- the word "your" is wrong. I've changed my replcomps so it uses the From: address of the original message, instead of the word "your." For example, when I'm replying to a message like this:

    Date:    Mon, 09 Jan 1995 09:47:42 -0500
    From:    "Keith E Smith" <KES@MVUS.BITNET>
    Sender:  Help Squad <HELPOUT@MVUS.BITNET>
    To:      Jerry Peek <jdpeek@asun.acs.syr.edu>
    Subject: HELP!
    
    the heading of my reply message says:
        ...
    Subject: Re: HELP!
    In-reply-to: Message from  "Keith E Smith" <KES@MVUS.BITNET>
       of "Mon, 09 Jan 1995 09:47:42 -0500."
    
    Here's how I do that -- replace lines 7-9 of the default replcomps with the following:
    In-reply-to: Message from %<{from}%{from}%|%{sender}%>\n\
       of "%<(nodate{date})%{date}%|%(pretty{date})%>."\
    %<{message-id} %{message-id}%>\n\
    
    That format string outputs In-reply-to: Message from, followed by the From: address if there is one -- otherwise, the Sender:. Then it outputs a newline (\n). If it can't parse the date in the message, it prints the Date: field as is; but if it can, it prints a "user-friendly" version of the date. Finally, if there was a Message-Id:, that's printed, too. Notice that even though the second and third lines are separated, that doesn't mean that the draft header will always have two lines. That's because there's no embedded \n here. The leading space before the second line is printed, though. The third line isn't indented because I don't want any space printed before the Message-Id: number.

    This isn't perfect, but it's usually just fine.

  5. Line 10 of the default replcomps file is a row of separator dashes. When prompter sees this, it knows that the rest of the file (if any) is the message body.
You can do a lot more customizing. See the Chapter MH Formatting and read your mh-format(5) manual page.

The Example below shows the updated replcomps file. (Here's one last chance to see the original replcomps file.)

Example: Updated MH replcomps file

%(lit)%(formataddr %<{reply-to}%|%<{from}%|%<{sender}%|%<{return-path}%>%>%>%>)\
%<(nonnull)%(void(width))%(putaddr To: )\n%>\
%(lit)%(formataddr{to})%(formataddr{cc})\
%(formataddr{x-vmsmail-to})%(formataddr{x-vmsmail-cc})\
%(formataddr{x-to})%(formataddr{x-cc})%(formataddr(me))\
%<(nonnull)%(void(width))%(putaddr cc: )\n%>\
%<{fcc}Fcc: %{fcc}\n%>\
Fcc:
Subject: %<{subject}Re: %{subject}%>\n\
In-reply-to: Message from %<{from}%{from}%|%{sender}%>\n\
   of "%<(nodate{date})%{date}%|%(pretty{date})%>."\
%<{message-id} %{message-id}%>\n\
--------

The forwcomps File

The forwcomps file for the forw command looks like the components file. I won't explain it here.

In fact, I don't even have a forwcomps file. I use my components file for forw, as well as for comp, by adding this entry to my MH profile:

forw: -form components
I could have done the same thing by using the UNIX ln command to make a link called forwcomps to my components file. If you want a separate forwcomps file, though, be my guest. Just look at Section The components File.

The digestcomps File

The default digestcomps file, in the Example below, is an MH format file. But, unlike replcomps, digestcomps is straightforward:

Example: Default MH digestcomps file

1> From:     %{digest}-Request
2> To:   %{digest} Distribution: dist-%{digest};
3> Subject:  %{digest} Digest V%(cur) #%(msg)
4> Reply-To: %{digest}
5> --------
6> %{digest} Digest    %(weekday{date}), %2(mday{date}) %(month{date}) 19%02(year{date})
7>         Volume %(cur) : Issue %(msg)
8> 
9> Today's Topics:
The header From: field doesn't have @hostname; the mail transport system should add that when it sends the message. (As the Section Signature and From: explains, you can change this field: add a hostname, for instance.) The escape %{digest} contains the digest name, like octopus-eaters. The volume number goes into %(cur); the issue number is in %(msg). The other escapes include the date; the Table MH-format Function Escapes (2 of 3) lists them.

The distcomps File

Don't put anything in the distcomps file except the header fields and a row of dashes. That's because dist distributes messages as is. If you want to add text along with the message body, use the forw command instead.

You can add extra fields to the message header, though. For instance, your distcomps could be:

Resent-To:
Resent-cc:
Resent-Bcc:
Resent-Fcc:
Resent-Comments:
Resent-Comments:
-------
The field names that end in To:, cc:, Bcc:, and Fcc: work just like the corresponding fields in, say, components. The Resent-Comments: fields give you a place to type a one- or two-line message. (Resent-Comments: isn't mentioned explicitly in the RFC 822 mail guidelines, though it's apparently not illegal. Some people say that it violates the idea of redistributing messages exactly as they were. I think it's really handy.) I have two Resent-Comments fields in case I want to write more than one line of comments. Of course, you can leave any of these empty when you dist your message; prompter will delete the fields you leave empty.

[Table of Contents] [Index] [Previous: Sharing Other Users' Folders] [Next: Periodic Cleanup, Checking, etc. with cron and at]


Last change $Date: 1996/06/06 15:09:39 $

This file is from the third edition of the book MH & xmh: Email for Users & Programmers, ISBN 1-56592-093-7, by Jerry Peek. Copyright © 1991, 1992, 1995 by O'Reilly & Associates, Inc. This file is freely-available; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation. For more information, see the file copying.htm.

Suggestions are welcome: Jerry Peek <jpeek@jpeek.com>