# Draft Message Template Files

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 or nmh etcetera 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:
   - If you type something and press RETURN, prompter writes the completed field into the draft message file.
   - If you type something and end the line with a backslash (`\`) just before you press RETURN, prompter keeps reading what you type. This is how you can type fields that are wider than the screen. prompter copies what you type until you end a line with something besides a backslash. To make the message header legal, be sure to start each of the continuation lines with space(s) or a tab.
   - If you don't type anything and just press RETURN, prompter omits that field from the draft message. For instance, if you're at the empty `cc:` field and you just press RETURN, there won't be a `cc:` field in the message you send.
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:
   - The simplest case is when the separator line is the last line in the draft file. (This happens, for instance, when you're using the comp command.) prompter just copies what you type into the draft message body until you type end-of-input (usually, CTRL-D) at the start of a line.
   - The next case is when there's more text after the separator line (for instance, text from comp -use, forw, or repl -filter) and if you have not used the -noprepend switch. In this case, prompter will print on the screen (but not in the draft message):

               --------Enter initial text

     You can type any message that you want prompter to add before the text from the draft file. As always, prompter will read your message until you press CTRL-D at the start of a line. Then, prompter copies in the rest of the draft file and exits. The whatnow program, which started prompter, prints `What now?`.
   - Finally, if you use its -noprepend switch, prompter treats existing text in the draft body differently. First, it rolls the existing text by on your screen. Then, it prompts you on the screen (but not in the draft):

               --------Enter additional text

     You can type a message to go at the end of the existing text. As before, after you press CTRL-D at the start of a line, prompter exits. The whatnow program, which started prompter, prints `What now?`.

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. (You can also get these files from this book's online archive. They're in examples/mh/Mail/replcomps.default and examples/mh/Mail/replcomps.jerry.)

> 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, 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 string register that'll store 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-elseif test. It means:
   - If (`%<`) the original message has a `Reply-to:` field in the header (`{reply-to}`), take that address.
   - Else if (`%?`) the original message has a `From:` field (`{from}`), take that address.
   - If that's not true, test for a `Sender:` field and use it if it exists.
   - Finally, there's one last check for a `Return-Path:` field.
   - A test always ends with `%>`.
   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 not, the test fails and line is skipped; no `To:` field is output. Otherwise, `%(void(width))` saves the width of the address in a numeric register. (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.

   The `(nonnull)` test at the beginning of line 2 causes a problem for repl -query users like me. There are times when I don't want my reply to go to any of the addresses that replcomps chooses for the `To:` field. The `(nonnull)` prevents a `To:` field if there are no addresses. In cases like these, I want to add `To:` addresses by hand. (A message really should have a `To:` field.) So I removed the test. Line 2 of my edited replcomps looks like this:

             %(void(width))%(putaddr To: )

   If there are no addresses, I still get a bare `To:` field. Then prompter will prompt me for addresses. I can just hit RETURN to leave the field blank (and let prompter delete it) in the rare case that I really don't want a `To:`.

   Note that I also removed the `\n` and `\` at the end of the line. These aren't needed on lines that output fields (like this one) which will always be present in the output.

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-elseif 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.

   Messages can have header fields like the ones below that list other addresses where the message was delivered:

             Resent-Cc: lonie@englvax.xyz.edu
             X-To: nelson@mvus.bitnet

   (I've also seen `X-vmsmail-to:` and `X-ccmail-to:`.) 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 have fields like those. 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(me))\
             %(formataddr{resent-to})%(formataddr{resent-cc})\
             %<(nonnull)%(void(width))%(putaddr cc: )\n%>\

   The repl -query switch helps me wade through this bunch of addresses.

   Sometimes I want to send a copy of my reply to addresses that didn't get the original message. That's easy for people who use a text editor (vi, for example) to start their draft messages. But I like to use prompter. So I've added an empty `cc:` field to my edited replcomps:

             cc:

   If I don't have any extra `cc:`s when I'm composing my reply, I just press RETURN; prompter deletes the blank field.
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 option (`{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 an `Fcc:` field in my draft, but I use different folders for different messages. I usually don't remember to use -fcc on the command line; I want to be prompted. So I changed line 5 to always output `Fcc:`. Then it adds the folder from any -fcc option. So, line 7 of my edited replcomps is:

             Fcc: %<{fcc}%{fcc}%>

   Compare that to the original version and you'll see two changes: First, I moved the `Fcc:` (and a space after it) outside of the test. Now replcomps always outputs `Fcc:`. Second, I always need to have a newline output at the end of the `Fcc:` field, whether there was a -fcc option or not. So I removed the `\n` (which outputs a newline) and the `\` continuation (which "eats" a newline at the end of the line).

   This setup takes advantage of the way that prompter works. If there's a `Fcc:` folder defined, replcomps outputs `Fcc:: folder`; prompter keeps that line in the draft. Otherwise, prompter prompts me with `Fcc:`, and I can either fill in a folder -- or press RETURN and the empty `Fcc:` field will be deleted.

   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, in the same way I fixed line 5, I've changed line 6 of my edited replcomps to:

             Subject: %<{subject}Re: %{subject}%>

   Notice that the `Re:` is inside the test. So, if I'm prompted to enter a subject, the subject won't automatically start with `Re:` -- but I can add it if I want to.
4. MH was designed long before message threading became popular. This step explains how to set up replcomps for threading. If you need an overview or details, please read References: Message Threading first.

   The default replcomps file puts the only threading info, the message-id, into the `In-reply-to:` field. It also adds the date and other text. Under a developing Internet draft email standard (draft-ietf-drums-msg-fmt-01), this extra text would be illegal.

   Let's fix this. First, if the new draft standard becomes a standard, any text other than a message-id in the `In-reply-to:` field will be illegal. So, to be safe, let's fill our new `In-reply-to:` field with the message-id of the message we're replying to. Because it's possible that the message you're replying to won't have a `Message-ID:` field, we'll only output the field (and a newline) if there is one. The backslash at the end (`\`) prevents a blank line if there's no `In-reply-to:` field output:

             %<{message-id}In-reply-to: %{message-id}\n%>\

   Next, let's add lines of code that make a new `References:` field. The order of the message-ids in this field is important: they should be listed from oldest to newest. So the field should contain the `References:`, if any, from the message you're replying to -- followed by its `Message-ID:` field. The simplest code would look like this:

             References: %{references} %{message-id}

   but it could leave multiple spaces that make the field sort of ugly. Let's be neat by adding the (trim) function to remove trailing whitespace from each field we copy in. Here are the three new lines for my edited replcomps:

             %<{message-id}References: \
             %<{references}%(void{references})%(trim)%(putstr) %>\
             %(void{message-id})%(trim)%(putstr)\n%>\

   In words, that says: "If the message I'm replying to has a `Message-ID:` field, write the word `References:` into the new draft. If the message has a `References:` field, store its text (`%(void{references})`), remove trailing whitespace (`%(trim)`), and output the trimmed text (`%(putstr)`). Next, do the same thing for the `Message-ID:` field."

   Time to fix lines 7-9 of the default replcomps file. Those three lines make the `In-reply-to:` field for the reply header. We've already made a new `In-reply-to:` field that meets the draft standard, so we'll be moving the text from the old replcomps into a new `Comments:` field. The old lines were:

             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 the original MH 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'll change 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>
             Message-ID: <19950109094744.AA18273@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: <19950109094744.AA18273@MVUS.BITNET>
             Comments: In-reply-to "Keith E Smith" <KES@MVUS.BITNET>
                message dated "Mon, 09 Jan 1995 09:47:42 -0500."

   Here's how I do that -- replace lines 7-9 with the following:

             Comments: In-reply-to \
             %<{from}%(void{from})%?(void{apparently-from})%|%(void{sender})%>\
             %(trim)%(putstr)\n\
                message dated "%<(nodate{date})%{date}%|%(tws{date})%>."

   This outputs `Comments: In-reply-to` followed by the `From:` address if there is one -- otherwise, the `Apparently-From:` or the `Sender:`. Then this code outputs a newline (`\n`), three spaces, and the words message dated. If it can't parse the date in the message, it prints the `Date:` field as is; but if it can, it uses the (tws) function to write the date in an "official" format. The leading space before the third line is output as-is. The third line is indented because it continues the `Comments:` field from the previons line.
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}%>)\
        %(void(width))%(putaddr To: )
        %(lit)%(formataddr{to})%(formataddr{cc})%(formataddr(me))\
        %(formataddr{resent-to})%(formataddr{resent-cc})\
        %<(nonnull)%(void(width))%(putaddr cc: )\n%>\
        cc:
        Fcc: %<{fcc}%{fcc}%>
        Subject: %<{subject}Re: %{subject}%>
        %<{message-id}In-reply-to: %{message-id}\n%>\
        %<{message-id}References: \
        %<{references}%(void{references})%(trim)%(putstr) %>\
        %(void{message-id})%(trim)%(putstr)\n%>\
        Comments: In-reply-to \
        %<{from}%(void{from})%?(void{apparently-from})%|%(void{sender})%>\
        %(trim)%(putstr)\n\
           message dated "%<(nodate{date})%{date}%|%(tws{date})%>."
        --------

## 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 look like the one below. (You can also get this little file from this book's online archive. It's in examples/mh/Mail/distcomps.)

        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.