This document describes the previous attach interface.  The attach
interface has changes for nmh 1.6 and later.  The interface is
documented in send(1), whatnow(1), and mhbuild(1).  No configuration
is required, and the same commands exist in whatnow; the two main
differences are that the header is now named "Attach", and mhbuild takes
care of the actual header processing.

Jon Steinhart's (jon@fourwinds.com) Attachment Handling Mods
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

A bunch of changes have been made to improve the nmh user interface for
handling MIME attachments.  This document provides the background and
implementation details of this so-called attach feature.

The user documentation for the attach feature is in the nmh send(1)
and whatnow(1) man pages.  

Why Did I Do This?
~~~~~~~~~~~~~~~~~~

Although nmh contains the necessary functionality for MIME message handing,
the interface to this functionality is pretty obtuse.  There's no way that
I'm ever going to convince my partner to write mhbuild composition files!
And even though I know how to write them, I often screw up when sending a
message that contains a shell script because I forget that I have to double
any # at the start of a line, which shell scripts have galore.

These changes simplify the task of managing attachments on draft files.
They allow attachments to be added, listed, and deleted.  MIME messages are
automatically created when drafts with attachments are sent.

The Simple Setup
~~~~~~~~~~~~~~~~

Starting with nmh version 1.5, no setup is necessary.

======================================================================
Through nmh 1.4, and optionally with nmh 1.5 and beyond, here's how to
set things up.

This only works if you're using the "standard" interface, i.e.,
whatnow.  Life is more complicated if you run mh-e.

Add the following to your .mh_profile:

	send: -attach Nmh-Attachment
	whatnow: -attach Nmh-Attachment

You may already have send and whatnow lines in your .mh_profile; if
you do, just add the new stuff to the end of the line.  For example,
mine looks like:

	send: -alias aliases -attach Nmh-Attachment
	whatnow: -attach Nmh-Attachment

That's it.  Next time you want to send an attachment, say "attach
filename" at the whatnow prompt and you're done.  You can check your
attachments by saying "alist".
======================================================================

Did I Do This Correctly?
~~~~~~~~~~~~~~~~~~~~~~~~

Hard to say.  Despite lots of time looking at the nmh code, I can't say that
I get the philosophy behind its structure.

I am aware of two deviations from what I saw in the nmh code.

 1.  I commented my changes.

 2.  It's been years since I've used a VT-100, so I don't try to make code
     fit into 80 columns anymore.  Seems silly to me.  (Some of us might
     disagree. :-)

What Did I Do?
~~~~~~~~~~~~~~

I made changes to the following files:

	h/
		prototypes.h
	man/
		anno.man
		send.man
		whatnow.man
	uip/
		Makefile.in
		anno.c
		annosbr.c
		send.c
		sendsbr.c
		viamail.c	(needed change for new sendsbr argument)
		whatnowsbr.c

Attachments are associated with messages using header fields.  For example, a
draft that looks like this

	To: jon
	Subject: test of attachments
	Nmh-Attachment: /export/home/jon/foo
	Nmh-Attachment: /export/home/jon/bar
	Nmh-Attachment: /export/home/jon/test/foo
	--------

has the files "foo", "bar", and foo as attachments.

Although I use the header field name "Nmh-Attachment" to indicate
attachments, the implementation allows any header field name.
(Originally, Jon used X-MH-Attachment.  We have globally changed that
to Nmh-Attachment to prevent contributing to the X- header field
namespace.)

The advantage of using header fields is that the list of attachments
travels with the draft so it remains valid across editing sessions.

Note that the header fields for attachments are removed from the message
before it is sent.

Since I was adding header fields to messages, it seemed sensible to use the
existing anno program to do this for me.  This required several changes to
generalize anno:

 o  I added a -draft option that permits annotations (header fields) to
    be added to the draft instead of a message sequence.

 o  I added a -delete option that allows annotations to be deleted.

 o  I added a -list option that allows annotations to be listed.

 o  I added a -number option that modifies the behavior of -delete and -list.

 o  I added a -append option so that annotations are appended to the headers
    instead of the default prepend.  Without this, attachments come out in
    reverse order.

Using the modified anno, the example above could be created (assuming that the
draft exists) by

	prompt% anno -draft -comp Nmh-Attachment -text /export/home/jon/foo -nodate -append
	prompt% anno -draft -comp Nmh-Attachment -text /export/home/jon/bar -nodate -append
	prompt% anno -draft -comp Nmh-Attachment -text /export/home/jon/test/foo -nodate -append

One can quite easily make an "attach" command using shell scripts,
aliases or functions.  For example, here's a bash function that does
the job:

	function attach() { for i in $*; do anno -append -nodate -draft -comp Nmh-Attachment -text "$i"; done; }

The following examples show the different ways in which attachments can be
listed.

	prompt% anno -list -draft -comp Nmh-Attachment
	foo
	bar
	foo

	prompt% anno -list -draft -comp Nmh-Attachment -text /
	/export/home/jon/foo
	/export/home/jon/bar
	/export/home/jon/test/foo

	prompt% anno -list -draft -comp Nmh-Attachment -number
	1	foo
	2	bar
	3	foo

	prompt% anno -list -draft -comp Nmh-Attachment -text / -number
	1	/export/home/jon/foo
	2	/export/home/jon/bar
	3	/export/home/jon/test/foo

	prompt%

Why all these listing options?

I feel that the listing as produced by the first example is what most people
would want most of the time.

The listing as produced by the second example seemed necessary for situations
where there were several attachments with the same file name in different
directories.

I included the numbering option so that attachments could be deleted by number
which might be easier in situations where there were several attachments with
the same file name in different directories, as in the above example.

Attachments are deleted using the -delete option.

	prompt% anno -delete -draft -comp Nmh-Attachment -text foo

deletes the first attachment since the foo matches the basename of the
attachment name.

	prompt% anno -delete -draft -comp Nmh-Attachment -text /export/home/jon/test/foo

deletes the third attachment since the text is a full path name and matches.

	prompt% anno -delete -draft -comp Nmh-Attachment -number 2

deletes the second attachment.

The attachment annotations are converted to a MIME message by send.  I'm not
completely sure that this is the right place to do it, as opposed to doing
it in post, but both would work.  It seemed to me to make more sense to do
it in send so that all of the various post options would apply to the MIME
message instead of the original draft file.

I added an -attach option to send that specifies the header field name used
for attachments.  Send performs the following additional steps if this option
is set:

 o  It scans the header of the draft for attachments.  Normal behavior applies
    if none exist.

 o  A temporary mhbuild composition file is created if there are attachments.

 o  All non-attachment headers are copied from the draft file to the
    composition file.

 o  The body of the draft is copied to a temporary body file if it contains at
    least one non-whitespace character.  A mhbuild directive for this file is
    appended to the composition file.  Note that this eliminates the problem
    of lines beginning with the # character in the message body.

 o  A mhbuild directive is appended to the composition file for each attachment
    header.

 o  mhbuild is run on the composition file, converting it to a MIME message.

 o  The converted composition file is substituted for the original draft file
    and run through the rest of send.

 o  The original draft file is renamed instead of the converted composition
    file.  This preserves the original message instead of the composition file
    which is really what a user would want.

 o  The ,file.orig file created by mhbuild is removed as it's a nuisance.

The mhbuild directives appended to the composition file are constructed as
follows:

 o  The content-type a file with a dot-suffix is obtained from the list of
    mhshow-suffix- entries in the profile.

 o  A file with no dot-suffix or no entry in the profile is assigned a
    content-type of application/octet-stream if it contains any non-ASCII
    characters.

 o  A file with no dot-suffix or no entry in the profile is assigned a
    content-type of text/plain if it contains only ASCII characters.

 o  The directive is of the form:

	#content-type; name="basename"; x-unix-mode=mode [ description ] filename

    The content type is derived as discussed above.  The basename is the
    last component of the pathname given in the body of the attachment header
    field.  The mode is file permissions.  The description is obtained by
    running the file command on the attachment file.  The filename is the
    field body from the attachment header field.

I added an -attach option to whatnow that specifies the header field
name for attachments.

I added to the commands available at the whatnow prompt to provide an
interface to the attachment mechanism.

I'm not completely happy with some of these additions because they
duplicate shell functionality.  I'm not sure that there's a good way
around it other than to not use whatnow.

The first three additions (the ones I'm not happy with) are cd, ls,
and pwd.  These do the same thing as their system counterparts.  As a
matter of fact, these are implemented by running the commands in a
subshell.  I did this because I wanted proper interpretation of
shell-specific things like ~ and wildcard expansion.

The next command is attach.  This takes a list of files and adds them
to the draft as attachments using the same code as the modified anno.
The list of files is run through ls using the user's shell, so
wildcard expansion and all that works.

The alist command lists the attachments on the current draft using
listing function that I added to anno.  It takes two optional options,
-l for a long listing meaning full path names, and -n for a numbered
listing.

The detach command removes attachments from the current draft, again
using the modified anno.  The arguments are interpreted as numbers if
the -n option is used, otherwise they're interpreted as file names.
File names are shoveled through ls using the user's shell in the
directory containing the file for wildcard expansion and such.  File
names are matched against the last pathname component unless they
begin with a / in which case they're matched against the entire name.

What's Left To Do?
~~~~~~~~~~~~~~~~~~

Nothing on this stuff.  When I get time I'd like to improve the interface
for reading messages with attachments.  It's my opinion that, because of the
command line nature of nmh, it makes the most sense to treat attachments as
separate messages.  In other words one should be able to read the next
attachment using next, and the previous one using prev.  One should be able
to show and scan attachments.  This would probably involve a major change
in the message numbering scheme to allow something like 123.4 to indicate
attachment 4 on message 123.

	Jon Steinhart
