MH & nmh: Email for Users & Programmers

May, 2006

Overview: Sending MH Messages

Each of the four MH programs that are used to compose a mail message -- comp, repl, forw, and dist -- does some things differently from the others. For example, comp composes an original message, and forw forwards existing ones. repl can build its header automatically; you fill in headers for the other three programs. But the programs have a lot in common. They all build a draft file in the same way, they all use prompter (unless you choose another editor), and they all have a What now? prompt. This section is about those similarities.

To create a MIME message, you put special directives in the draft file. Next, you give the draft to mhn (under MH, and nmh before version 1.0) or mhbuild (nmh-1.0 and above); that formats the draft for MIME. Most MIME messages are created with comp, but you can use forw and repl too. too.

Making the Draft from the Template File

Each of the four mail-creating programs has its own template draft file. This file helps to form the draft message. For instance, the default template file for comp is named components. The components file looks like this (unless someone on your system has changed it):

    To:
    cc:
    Subject:
    -------
    
The row of dashes separates the message header from the body. It's automatically replaced with an empty line when you send the message.

When you start comp, it copies components into the draft file. The template file for repl is different -- it's not just copied. Instead, the file, called replcomps, has MH formatting commands that automatically fill in the header of the draft file for you. forw and dist have their own twists, too. The Figure below shows how they all work.

If you want to change the order of the fields -- or add new ones -- in all the messages that you send with an MH command, read the Section Draft Message Template Files.

Figure: Sending a message. Step 1: Making draft from template

sams1mdf.jpg

Editing the Draft with prompter

After the comp, repl, forw, and dist commands make the draft file in their own ways, they all start a program called whatnow. The first thing whatnow does is start an editor. The default editor is named prompter. (The Section Changing Default Editors explains more.)

prompter reads and edits the draft file, line by line. First it handles the header (up to the line of dashes). Next it handles the body. The next Figure has an example.

Figure: Sending a message. Steps 2-4: Draft message, before and after prompter edits it

s2dmbape.jpg

The Header

If the draft file has any empty header fields such as:

    To:
    
prompter prompts you to fill them in. By now you know that if you leave the field empty, prompter just deletes that field from the draft.

Normally, after you fill in a field and press RETURN, prompter reads the next header field and shows it on your screen. But if you type a backslash (\) at the end of a line just before you press RETURN, prompter will keep collecting the same header field. That lets you put long lists of addresses in, say, the cc: field.

    % comp
    To: uunet!somewhere!somebody
    cc: jjensen@bigcorp.se, lvalois@somecorp.fr, myboss,\
      phogan@auscorp.au
    Subject:
    
You must start each of the continuation lines with a space or tab. The sidebar When is a Backslash Not a Backslash? has more about this often-used character.

To add or change the fields in a header, you can either edit the header after prompter is finished or make your own private template files.

The Body

After the row of dashes in the draft file, prompter starts collecting the body of the message from your terminal exactly as you type it. Remember that prompter doesn't wrap lines; you should press RETURN at the end of every line. It reads until you press CTRL-D at the start of a line. (prompter reads what you type until it gets the end-of-input character. There's a chance that your account is set up to use something besides CTRL-D as end-of-input.)

MH 6.7 added a new -doteof switch for prompter. If you set this switch (usually in your MH profile), then prompter will accept a single dot (.) at the start of a line, by itself, as the end of the draft message.

Next, if there was text in the message body when you started prompter (you're forwarding a message, re-editing an existing draft, and so on), prompter will scroll that text across your screen. With big messages or slow terminals, this can take time. If you don't want to see the included text, add the -rapid switch to the prompter: entry in your MH profile. (If you have -rapid set and you want to see the included text, just type list at a What now? prompt.)

If your message had included text, there's one more pair of switches you might want to know about: -prepend and -noprepend. Because most users like to "set and forget" about these, the explanation is in the Section How the Draft Message is Built.

What now? -- and the whatnow Program

After you end the body of the message by typing (usually) CTRL-D, prompter quits and the draft message is handled by the whatnow program. It gives you a list of choices for your draft message. To see the list, just press RETURN at the What now? prompt. That list covers only the most common things you can do at the What now? prompt. Most commands accept other switches to change their operation. For instance, send -width 60 tells send to fold header address fields that are more than 60 characters wide. Or list afile will display the file named afile in your current directory and then give you another What now? prompt. For a quick list of switches, you can add -help to most commands, as in the following example:

    What now? send -help
    syntax: send [file] [switches]
      switches are:
            ...
    What now?
    
Here's more information about each choice, with abbreviations in parentheses:

list (or the letter l)

Shows the draft message you just typed. To do this, it calls the lproc: program listed in your MH profile -- by default, it's a program like more(1) or less(1). On most systems this shows the draft screen by screen -- to see the next screen, press either the space bar or RETURN (depending on the program that list uses).

If your system is set up for MIME and you've created the MIME message with edit mhn or mime (see below), list may be configured in two ways:

When list is done, you'll get another What now? prompt.

display (or d)

Works only with the repl and dist programs. It shows the message that you're replying to or distributing; otherwise display is just like list.

edit (or e)

Uses the default editor (usually prompter, or whatever editor you were using) to edit the draft. When you leave the editor, you'll get another What now? prompt.

You can set a different default editor in your MH profile. See the Section Editor-next. (Another kind of default editor for MIME messages is the automhnproc or buildmimeproc.)

edit editor (or e editor)

Edits the draft with the editor named editor (example: edit vi). When you leave the editor, you'll get another What now? prompt. Then you can use yet another editor program or any of the other whatnow commands.

After you enter the directives for a MIME message, you'll type edit mhn or mime to create the draft -- unless you have automatic MIME draft processing, that is. The Section Sending MIME Mail has an example.

The "editor" program doesn't really have to be an editor. Any UNIX program that accepts a filename argument will work -- including shell programs that you write. For example, you can type edit append filename to append a file to your draft. The command edit original runs a shell script named original to undo the effects of MIME formatting.

As long as the "editor" program doesn't modify the draft file, you can use the edit command to do anything else you can do with a standard UNIX program and a file. For example, the UNIX spell program reads a file and outputs the words it doesn't recognize. Then grep can show words in context if you don't recognize them. Here's an example where spell finds the possible misspelling pre and I use grep to find it:

    % comp
       ...
    What now? e spell
    FTP.SPC.EDU
    Fcc
    Tue
    inbox
    pre

    What now? e grep pre
    project.  I was hoping to have a reviewed, pre-production draft ready

    What now?
    
To fix any misspellings, I'd use a command like e vi. Or, if your system has ispell, it can do the checks and changes interactively. Here are some other "editors" you can use at the What now? prompt:
edit head
Runs head(1) to read the first ten lines of your draft. That usually shows the header pretty well.
edit wc
Counts the number of lines, words, and characters in your draft (including the header).
edit lpr
(or edit lp, depending on your print command) sends the draft to the printer.

mime (nmh only)

As you saw above, you can build a MIME draft by typing edit mhn. That works in both MH and nmh. In nmh, though, you can also type just mime. That runs mhn -build (before nmh-0.21) or mhbuild (nmh-0.21+) -- or, if you have one, runs your buildmimeproc.

If you don't want to know all the details at this point, try typing mime. If it works, great! Otherwise, type edit mhn.

quit (or q)

Leaves the draft message file where it is and takes you back to the shell prompt (%). You use this if you want to do something else and come back to your draft message later. To find out how, see the Section Working with Draft Messages.

quit -delete (or q -d) (nmh: delete)

Deletes the draft message you've been working on and takes you to a shell prompt. Use this if you decide not to send the message. The dash (-) in -delete isn't required, but that's undocumented and may be changed. In nmh version 0.27 and above, you can simply type delete -- and you can abbreviate that to de.

The Section Deleted Draft Messages explains what happens when the draft is deleted -- and how to change your mind after you delete a draft.

refile +folder (or r +folder)

Moves the draft message into the folder you name. The draft won't be sent. You'll get another shell prompt. See the Section Folders.

refile -link +folder (or r -l +folder)

Links a copy of the draft message into the folder you name, but leaves the draft there to be sent. Now, no matter what command you type at the next What now? prompt, a copy of the draft will stay in the folder named folder. You'll get another shell prompt. The Section Moving and Linking Messages: refile has more information.

whom (or w)

Lists the addresses that the message will go to. This is useful with aliases (Section MH Aliases). When whom is done, you'll get another What now? prompt.

whom -check (or w -check)

Lists the addresses that the message will go to and tells you if the address looks "deliverable." (On some versions of MH, whom -check just prints the cryptic error whom: Only one message at a time!... even when there is only one message. Plain whom, without the -check switch, doesn't have the problem.)

Unfortunately, this doesn't mean that the mail will really get there. Depending on how the message is sent, an Address OK message from whom means something like "the remote hostname looks okay" or "the network is available."

Many electronic mail systems still can't tell you whether your mail addresses are correct -- you have to wait to see if the message is returned to you. This may or may not be the situation on your host. But whom -check will try to tell you if addresses are "deliverable" and show you something about them.

Although you can use whom from a shell prompt (like %), you'll usually use it at the What now? prompt. Here's an example, with the middle left out:

    % comp
    To: gurus
        ...
    What now? whom -check
    danro... deliverable
    rada... deliverable
    rbwilbur@mysun.xyz.edu... deliverable
    "| /usr/local/lib/mh/slocal -user ahof"... deliverable
    
Here, whom shows that the gurus mail alias has four members. The first two of them look like addresses on the local computer. The third has mail forwarded to another computer, and the fourth has mail forwarded to a mail-handling program (slocal -- see the Chapter Processing New Mail Automatically.

My computer uses the sendmail transfer agent, so whom calls sendmail to check the addresses. If your computer uses a different transfer agent, your whom output may look different. Again, whom can't guarantee that your message will get through. But you can be fairly sure that if whom tells you there's a problem, you should check into it. Be sure your addresses are written correctly -- if that doesn't help, ask an expert who knows your computer's transfer agent.

send (or s)

Sends the message as shown in the next Figure Sending a message. Steps 5-6: After composing the draft. Depending on how your system's transfer agent is set up and where your message is going, the message may not be delivered for a few minutes, or even a couple of days. All "send" really means is "deliver the message to the transfer agent." The rest is up to that transfer agent. (send actually gives the message to the MH program called post, which in turn gives it to the transfer agent.)

Figure: Sending a message. Steps 5-6: After composing the draft

s56afcot.jpg

If the message was sent (to the transfer agent!) successfully, you'll get another shell prompt. If there were problems, you may see the error on your screen or you may get a mail message that explains what went wrong. Again, it all depends on your system's setup. If you send MIME messages, an automatic MIME processing program can run automatically, when you type send, to process the message with mhn or mhbuild (or something else you choose). You can add a sendproc processing program that does any handling you want before the message is given to MH for delivery. One handy sendproc shell program is mysend.

MH versions with MIME support have a -split switch that automatically splits the message into pieces. This helps to be sure that the message gets through gateways and systems with message size limits. If your message is just plain text, the recipient shouldn't need a MIME mail reader to reassemble the split message: removing all but the first header, then concatenating the message bodies, will give back the original message. See the Section Partial Messages.

send -watch -verbose (or s -wa -v)

Gives you an idea of what's happening as MH delivers your message to the transfer agent. (The undocumented -snoop switch on some versions of MH gives more information.) How much you see depends on several things. If your system is set up to do it, you'll see the SMTP transaction that delivers your message across the network to the remote machine. The section Message Transfer; Sighted and Blind Recipients has an example.

push (or p)

Runs send with its -push switch, which sends your message "in the background." In other words, you'll get another shell prompt right away. The only exception is when you have automatic MIME processing: mhn or mhbuild will be run before you get another shell prompt; that can take time, prompt you for input, or even give another What now? prompt if there are errors to fix. (The -split switch for the send command also works with push. You won't see the progress messages as the parts are sent.)

Using push has good and bad points. You can do something else while MH sends the message; that can be good, especially on a slow system or when it takes time to deliver the message.

But the draft file will stay there until it's been processed. That can be bad:

The Figure Sending a message. Steps 5-6: After composing the draft is a diagram that shows what send (and send -push) do with the finished draft.

Message Transfer; Sighted and Blind Recipients

This section explains more about message delivery, including ways that you can hide the actual recipients' addresses when a message is delivered.

To understand how email is delivered over the Internet (and on many internal networks, too), you need to understand the difference between the addresses in the message header and the addresses in the message envelope. When a message is delivered by SMTP (the Internet mail transfer standard), the addresses in the message header are ignored. SMTP uses the addresses in the message envelope instead. This means that the addresses in the message header can be completely different than the actual addresses (the envelope addresses) where the message is delivered.

How are addresses transferred from the message header (where you put them when you compose the draft) into the envelope? MH does that itself: MH reads the header, parses the addresses, and hands them to the message transfer system. In many cases, depending on how it's configured, MH "speaks" SMTP, to the transfer system, over a network. You can see this happening, depending on your configuration, by using the (mostly-undocumented) send switches -watch -verbose -snoop. I can't cover all the details of SMTP here; if you're interested, see a good book about the Internet. Quickly, though, these switches show the SMTP "conversation" between MH and the relay host where MH sends its outgoing messages. There's an example below.

To get started, let's look at a little-known way of addressing email called a group (or a distribution list). It's defined in RFC 822, and MH supports it. To address mail to a group (at a header field -- To:, cc:, etc.), you type the group name, a colon (:), the addresses, and end the line with a semicolon (;). MH removes those addresses from the header and puts them in the message envelope (only). When recipients get the message, that group line in the message header will have only the group name.

In the example below, a client is sending mail to jpeek@jpeek.com. Jerry's address is in the To: field, so every recipient will see it. The cc: field has a group with addresses of the company's execs, secret addresses which Jerry shouldn't be able to contact.

In the dialog below, MH is running on the host foo.snerdly.com, talking to the mail relay host smtp.snerdly.com. Joe, the person sending the message, asks MH to show the delivery process:

    % comp
    To: Jerry Peek <jpeek@jpeek.com>
    cc: Executive team: bob@snerdly.com, joan@snerdly.com ;
    Subject: Your contract
    --------
    Jerry,

        ....

    What now? s -wa -v -snoop
     -- Posting for All Recipients --
    <= 220 smtp.snerdly.com SMTP/smap Ready.
    => HELO foo.snerdly.com
    <= 250 Greetings, foo.snerdly.com. Pleased to meet you.
    => MAIL FROM:<joe@foo.snerdly.com>
    <= 250 <joe@foo.snerdly.com>... Sender Ok
      -- Network Recipients --
      jpeek at jpeek.com: => RCPT TO:<jpeek@jpeek.com>
    <= 250 <jpeek@jpeek.com> OK
    address ok
      bob at snerdly.com: => RCPT TO:<bob@snerdly.com>
    <= 250 <bob@snerdly.com> OK
    address ok
      joan at snerdly.com: => RCPT TO:<joan@snerdly.com>
    <= 250 <joan@snerdly.com> OK
    address ok
    => DATA
    <= 354 Enter mail, end with "." on a line by itself
    => .
    <= 250 Mail accepted
    => QUIT
    <= 221 Closing connection
     -- Recipient Copies Posted --
    Message Processed
    
You can see that the message is being delivered to three addresses. But look at the message, below, that MH sends (and Jerry and the group recipients get). Notice that the group addresses don't appear because MH removed them:
    To: Jerry Peek <jpeek@jpeek.com>
    cc: Executive team: ;
    Subject: Your contract
    Date: Thu, 15 May 1997 20:12:39 -0700
    From: Joe Doakes <joe@foo.snerdly.com>

    Jerry,

    ....
    
You should be careful with "blind recipients" (like the executives above) whose addresses aren't shown in the delivered message header. In some cases, the recipient's MTA may copy those addresses from the message envelope to a special Apparently-to: header field. This usually happens only when a recipient's host is running the sendmail MTA and the message doesn't have a To: address field. That problem almost never happens with group lists because there is a To: field (although it may have only a group name, that's enough to stop the Apparently-to: field from being added). That problem is more common in blind copies, though.

A blind address is similar to a group address in that MH removes the address from the header before sending the message. But a blind address is typed in a special header field, bcc: ("blind copy") or dcc: ("distribution copy"). MH doesn't just hide the address; it removes the complete bcc: and dcc: fields from the message header. If the message doesn't have any remaining address fields, the recipient's MTA may add an Apparently-to: field. Here's a link to an example of this.

Add Text to Drafts: mysend

The Section Automatic Signature on End of Messages shows how to edit your draft template files to add a standard signature to the end of many (but not all) of your messages. Another Section has the append shell script, an editor you run from the What Now? prompt to add files to the end of a draft before you send it. This section shows a third way: a shell script that edits your draft message when you execute:

    What now? send
    
(It also works when you use push.) The script is written to append a copy of the file .signature from your home directory, with a line of two dashes before it. That's easy to change by editing the script.

By default, the script does not add your signature unless you type:

    What now? send -signature
    
(Abbreviate that -sig if you'd like.) You can change a shell variable to make the opposite the default: a signature unless you type -nosig. No matter what, the script won't add a signature if the draft you're composing is from the dist command.

Any other arguments you type at What now? are passed to the standard MH send command. mysend runs it after editing the draft.

Of course, mysend can do more to a draft than add a signature. Whatever you do, remember that the script processes all of your mail; make sure the script is reliable and does what you want. A test mail setup is a good place for debugging a script this important.

To install the script, add this entry to your MH profile:

    sendproc: /xxx/yyy/mysend
    
where /xxx/yyy is the location of mysend on the filesystem.
NOTE: This script doesn't work with the dist command on some versions of MH (Version 6.7.2, at least). Those versions won't tell the post command to allow a message to be redistributed. The bug only happens when you add your own sendproc program; it had nothing to do with this mysend script. As a result, errors like these occur during the dist command:
      What now? send post: illegal header line --
      Resent-To: post: illegal header line -- Resent-cc:
      
If you use dist and your MH version has that bug, you should also use the mydist script in the Section Explanation of mysend.

Sending PGP Messages

MH 6.8.4 comes with shell scripts that give rudimentary support for PGP (Pretty Good Privacy). The pgped script adds PGP information after you've run mhn on the draft. To run it by hand, you do these three commands:

    What now? e mhn

    What now? e pgped
       or...  e pgped -sign

    What now? send
    
The script for reading PGP is pgpshow.

Other schemes for using PGP with MH have been discussed on the comp.mail.mh newsgroup. There's also good PGP support in exmh.