Updated docs/README-ATTACHMENTS, mainly to reflect that no setup is
[mmh] / docs / README-ATTACHMENTS
1 Jon Steinhart's (jon@fourwinds.com) Attachment Handling Mods
2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3
4 A bunch of changes have been made to improve the nmh user interface for
5 handling MIME attachments.  This document provides the background and
6 implementation details of this so-called attach feature.
7
8 The user documentation for the attach feature is in the nmh send(1)
9 and whatnow(1) man pages.  
10
11 Why Did I Do This?
12 ~~~~~~~~~~~~~~~~~~
13
14 Although nmh contains the necessary functionality for MIME message handing,
15 the interface to this functionality is pretty obtuse.  There's no way that
16 I'm ever going to convince my partner to write mhbuild composition files!
17 And even though I know how to write them, I often screw up when sending a
18 message that contains a shell script because I forget that I have to double
19 any # at the start of a line, which shell scripts have galore.
20
21 These changes simplify the task of managing attachments on draft files.
22 They allow attachments to be added, listed, and deleted.  MIME messages are
23 automatically created when drafts with attachments are sent.
24
25 The Simple Setup
26 ~~~~~~~~~~~~~~~~
27
28 Starting with nmh version 1.5, no setup is necessary.
29
30 ======================================================================
31 Through nmh 1.4, and optionally with nmh 1.5 and beyond, here's how to
32 set things up.
33
34 This only works if you're using the "standard" interface, i.e.,
35 whatnow.  Life is more complicated if you run mh-e.
36
37 Add the following to your .mh_profile:
38
39         send: -attach Nmh-Attachment
40         whatnow: -attach Nmh-Attachment
41
42 You may already have send and whatnow lines in your .mh_profile; if
43 you do, just add the new stuff to the end of the line.  For example,
44 mine looks like:
45
46         send: -alias aliases -attach Nmh-Attachment
47         whatnow: -attach Nmh-Attachment
48
49 That's it.  Next time you want to send an attachment, say "attach
50 filename" at the whatnow prompt and you're done.  You can check your
51 attachments by saying "alist".
52 ======================================================================
53
54 Did I Do This Correctly?
55 ~~~~~~~~~~~~~~~~~~~~~~~~
56
57 Hard to say.  Despite lots of time looking at the nmh code, I can't say that
58 I get the philosophy behind its structure.
59
60 I am aware of two deviations from what I saw in the nmh code.
61
62  1.  I commented my changes.
63
64  2.  It's been years since I've used a VT-100, so I don't try to make code
65      fit into 80 columns anymore.  Seems silly to me.  (Some of us might
66      disagree. :-)
67
68 What Did I Do?
69 ~~~~~~~~~~~~~~
70
71 I made changes to the following files:
72
73         h/
74                 prototypes.h
75         man/
76                 anno.man
77                 send.man
78                 whatnow.man
79         uip/
80                 Makefile.in
81                 anno.c
82                 annosbr.c
83                 send.c
84                 sendsbr.c
85                 viamail.c       (needed change for new sendsbr argument)
86                 whatnowsbr.c
87
88 Attachments are associated with messages using header fields.  For example, a
89 draft that looks like this
90
91         To: jon
92         Subject: test of attachments
93         Nmh-Attachment: /export/home/jon/foo
94         Nmh-Attachment: /export/home/jon/bar
95         Nmh-Attachment: /export/home/jon/test/foo
96         --------
97
98 has the files "foo", "bar", and foo as attachments.
99
100 Although I use the header field name "Nmh-Attachment" to indicate
101 attachments, the implementation allows any header field name.
102 (Originally, Jon used X-MH-Attachment.  We have globally changed that
103 to Nmh-Attachment to prevent contributing to the X- header field
104 namespace.)
105
106 The advantage of using header fields is that the list of attachments
107 travels with the draft so it remains valid across editing sessions.
108
109 Note that the header fields for attachments are removed from the message
110 before it is sent.
111
112 Since I was adding header fields to messages, it seemed sensible to use the
113 existing anno program to do this for me.  This required several changes to
114 generalize anno:
115
116  o  I added a -draft option that permits annotations (header fields) to
117     be added to the draft instead of a message sequence.
118
119  o  I added a -delete option that allows annotations to be deleted.
120
121  o  I added a -list option that allows annotations to be listed.
122
123  o  I added a -number option that modifies the behavior of -delete and -list.
124
125  o  I added a -append option so that annotations are appended to the headers
126     instead of the default prepend.  Without this, attachments come out in
127     reverse order.
128
129 Using the modified anno, the example above could be created (assuming that the
130 draft exists) by
131
132         prompt% anno -draft -comp Nmh-Attachment -text /export/home/jon/foo -nodate -append
133         prompt% anno -draft -comp Nmh-Attachment -text /export/home/jon/bar -nodate -append
134         prompt% anno -draft -comp Nmh-Attachment -text /export/home/jon/test/foo -nodate -append
135
136 One can quite easily make an "attach" command using shell scripts,
137 aliases or functions.  For example, here's a bash function that does
138 the job:
139
140         function attach() { for i in $*; do anno -append -nodate -draft -comp Nmh-Attachment -text "$i"; done; }
141
142 The following examples show the different ways in which attachments can be
143 listed.
144
145         prompt% anno -list -draft -comp Nmh-Attachment
146         foo
147         bar
148         foo
149
150         prompt% anno -list -draft -comp Nmh-Attachment -text /
151         /export/home/jon/foo
152 v       /export/home/jon/bar
153         /export/home/jon/test/foo
154
155         prompt% anno -list -draft -comp Nmh-Attachment -number
156         1       foo
157         2       bar
158         3       foo
159
160         prompt% anno -list -draft -comp Nmh-Attachment -text / -number
161         1       /export/home/jon/foo
162         2       /export/home/jon/bar
163         3       /export/home/jon/test/foo
164
165         prompt%
166
167 Why all these listing options?
168
169 I feel that the listing as produced by the first example is what most people
170 would want most of the time.
171
172 The listing as produced by the second example seemed necessary for situations
173 where there were several attachments with the same file name in different
174 directories.
175
176 I included the numbering option so that attachments could be deleted by number
177 which might be easier in situations where there were several attachments with
178 the same file name in different directories, as in the above example.
179
180 Attachments are deleted using the -delete option.
181
182         prompt% anno -delete -draft -comp Nmh-Attachment -text foo
183
184 deletes the first attachment since the foo matches the basename of the
185 attachment name.
186
187         prompt% anno -delete -draft -comp Nmh-Attachment -text /export/home/jon/test/foo
188
189 deletes the third attachment since the text is a full path name and matches.
190
191         prompt% anno -delete -draft -comp Nmh-Attachment -number 2
192
193 deletes the second attachment.
194
195 The attachment annotations are converted to a MIME message by send.  I'm not
196 completely sure that this is the right place to do it, as opposed to doing
197 it in post, but both would work.  It seemed to me to make more sense to do
198 it in send so that all of the various post options would apply to the MIME
199 message instead of the original draft file.
200
201 I added an -attach option to send that specifies the header field name used
202 for attachments.  Send performs the following additional steps if this option
203 is set:
204
205  o  It scans the header of the draft for attachments.  Normal behavior applies
206     if none exist.
207
208  o  A temporary mhbuild composition file is created if there are attachments.
209
210  o  All non-attachment headers are copied from the draft file to the
211     composition file.
212
213  o  The body of the draft is copied to a temporary body file if it contains at
214     least one non-whitespace character.  A mhbuild directive for this file is
215     appended to the composition file.  Note that this eliminates the problem
216     of lines beginning with the # character in the message body.
217
218  o  A mhbuild directive is appended to the composition file for each attachment
219     header.
220
221  o  mhbuild is run on the composition file, converting it to a MIME message.
222
223  o  The converted composition file is substituted for the original draft file
224     and run through the rest of send.
225
226  o  The original draft file is renamed instead of the converted composition
227     file.  This preserves the original message instead of the composition file
228     which is really what a user would want.
229
230  o  The ,file.orig file created by mhbuild is removed as it's a nuisance.
231
232 The mhbuild directives appended to the composition file are constructed as
233 follows:
234
235  o  The content-type a file with a dot-suffix is obtained from the list of
236     mhshow-suffix- entries in the profile.
237
238  o  A file with no dot-suffix or no entry in the profile is assigned a
239     content-type of application/octet-stream if it contains any non-ASCII
240     characters.
241
242  o  A file with no dot-suffix or no entry in the profile is assigned a
243     content-type of text/plain if it contains only ASCII characters.
244
245  o  The directive is of the form:
246
247         #content-type; name="basename"; x-unix-mode=mode [ description ] filename
248
249     The content type is derived as discussed above.  The basename is the
250     last component of the pathname given in the body of the attachment header
251     field.  The mode is file permissions.  The description is obtained by
252     running the file command on the attachment file.  The filename is the
253     field body from the attachment header field.
254
255 I added an -attach option to whatnow that specifies the header field
256 name for attachments.
257
258 I added to the commands available at the whatnow prompt to provide an
259 interface to the attachment mechanism.
260
261 I'm not completely happy with some of these additions because they
262 duplicate shell functionality.  I'm not sure that there's a good way
263 around it other than to not use whatnow.
264
265 The first three additions (the ones I'm not happy with) are cd, ls,
266 and pwd.  These do the same thing as their system counterparts.  As a
267 matter of fact, these are implemented by running the commands in a
268 subshell.  I did this because I wanted proper interpretation of
269 shell-specific things like ~ and wildcard expansion.
270
271 The next command is attach.  This takes a list of files and adds them
272 to the draft as attachments using the same code as the modified anno.
273 The list of files is run through ls using the user's shell, so
274 wildcard expansion and all that works.
275
276 The alist command lists the attachments on the current draft using
277 listing function that I added to anno.  It takes two optional options,
278 -l for a long listing meaning full path names, and -n for a numbered
279 listing.
280
281 The detach command removes attachments from the current draft, again
282 using the modified anno.  The arguments are interpreted as numbers if
283 the -n option is used, otherwise they're interpreted as file names.
284 File names are shoveled through ls using the user's shell in the
285 directory containing the file for wildcard expansion and such.  File
286 names are matched against the last pathname component unless they
287 begin with a / in which case they're matched against the entire name.
288
289 What's Left To Do?
290 ~~~~~~~~~~~~~~~~~~
291
292 Nothing on this stuff.  When I get time I'd like to improve the interface
293 for reading messages with attachments.  It's my opinion that, because of the
294 command line nature of nmh, it makes the most sense to treat attachments as
295 separate messages.  In other words one should be able to read the next
296 attachment using next, and the previous one using prev.  One should be able
297 to show and scan attachments.  This would probably involve a major change
298 in the message numbering scheme to allow something like 123.4 to indicate
299 attachment 4 on message 123.
300
301         Jon Steinhart