$book = '..'?>
include "$book/mh.php"; includeHeader('shafol.html', 'pccewca.html'); ?>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.
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.
To:
it prompts you with To: and leaves the cursor there.
Then:
Reply-to: ehuser@bigmachine.xxx.yyy.zzz
then prompter won't stop or prompt you. It'll leave the
field 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?.
--------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?.
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 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.
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:
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.
%(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.
%<{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.
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.
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 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 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.
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.
includeFooter('$Date: 2006-05-31 15:13:43 -0700 (Wed, 31 May 2006) $',
'OReilly: 1991, 1992, 1995; Jerry: 1996, 1997, 1999, 2000, 2002, 2004');
?>