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