]> diplodocus.org Git - nmh/blob - man/mhfixmsg.man
Simplified m_strn() per Ralph's suggestions.
[nmh] / man / mhfixmsg.man
1 .TH MHFIXMSG %manext1% 2016-11-08 "%nmhversion%"
2 .
3 .\" %nmhwarning%
4 .
5 .SH NAME
6 mhfixmsg \- rewrite nmh MIME messages with various transformations
7 .SH SYNOPSIS
8 .HP 5
9 .na
10 .B mhfixmsg
11 .RB [ \-help ]
12 .RB [ \-version ]
13 .RI [ +folder ]
14 .RI [ msgs " | "
15 .IR "absolute pathname" " | "
16 .RB \-file
17 .IR file ]
18 .RB [ \-decodetext
19 8bit|7bit|binary |
20 .BR \-nodecodetext ]
21 .RB [ \-decodetypes
22 .IR "type/[subtype][,...]" ]
23 .RB [ \-crlflinebreaks " | " \-nocrlflinebreaks ]
24 .RB [ \-textcharset
25 .I charset
26 .RB "| " \-notextcharset ]
27 .RB [ \-reformat " | " \-noreformat ]
28 .RB [ \-replacetextplain " | " \-noreplacetextplain ]
29 .RB [ \-fixboundary " | " \-nofixboundary ]
30 .RB [ \-fixcte " | " \-nofixcte ]
31 .RB [ \-fixtype
32 .IR mimetype ]
33 .RB [ \-outfile
34 .IR outfile ]
35 .RB [ \-rmmproc
36 .IR program ]
37 .RB [ \-normmproc ]
38 .RB [ \-changecur " | " \-nochangecur ]
39 .RB [ \-verbose " | " \-noverbose ]
40 .ad
41 .SH DESCRIPTION
42 .B mhfixmsg
43 rewrites MIME messages, applying specific transformations such as
44 decoding of MIME-encoded message parts and repairing invalid MIME
45 headers.
46 .PP
47 MIME messages are specified in RFC 2045 to RFC 2049
48 (see
49 .IR mhbuild (1)).
50 The
51 .B mhlist
52 command is invaluable for viewing the content structure of MIME
53 messages.
54 .B mhfixmsg
55 passes non-MIME messages through without any transformations. If no
56 transformations apply to a MIME message, the original message or file
57 is not modified or removed. Thus,
58 .B mhfixmsg
59 can safely be run multiple times on a message.
60 .PP
61 The
62 .B \-decodetext
63 switch enables a transformation to decode each base64 and quoted-printable
64 text message part to the selected 8-bit, 7-bit, or
65 binary encoding.
66 If 7-bit is selected for a base64 part but it will only fit
67 8-bit, as defined by RFC 2045, then it will be decoded to 8-bit
68 quoted-printable.
69 Similarly, with 8-bit, if the decoded text would be binary,
70 then the part is not decoded (and a message will be displayed if
71 .B \-verbose
72 is enabled). Note that
73 .B \-decodetext
74 binary can produce messages that are not RFC 2045 compliant.
75 .PP
76 When the
77 .B \-decodetext
78 switch is enabled, each carriage return character that precedes a
79 linefeed character is removed from text parts encoded in ASCII,
80 ISO-8859-x, UTF-8, or Windows-12xx.
81 .PP
82 The
83 .B \-decodetypes
84 switch specifies the message parts, by type and optionally subtype,
85 to which
86 .B \-decodetext
87 applies. Its argument is a comma-separated list of type/subtype
88 elements. If an element does not contain a subtype, then
89 .B \-decodetext
90 applies to all subtypes of the type. The default is
91 .B \-decodetypes
92 .IR text ;
93 it can be overridden, e.g., with
94 .B \-decodetypes
95 .I text/plain
96 to restrict
97 .B \-decodetext
98 to just text/plain parts.
99 .PP
100 By default, carriage return characters are preserved or inserted at
101 the end of each line of text content. The
102 .B \-crlflinebreaks
103 switch selects this behavior and is enabled by default. The
104 .B \-nocrlflinebreaks
105 switch causes carriage return characters to be stripped from, and not
106 inserted in, text content when it is decoded and encoded. Note that
107 its use can cause the generation of MIME messages that do not conform
108 to RFC 2046, §4.1.1, paragraph 1.
109 .PP
110 The
111 .B \-textcharset
112 switch specifies that all text/plain parts of the message(s)
113 should be converted to
114 .IR charset .
115 Charset conversions require that
116 .B nmh
117 be built with
118 .IR iconv (3);
119 see the
120 .BR mhparam (1)
121 man page for how determine whether your
122 .B nmh
123 installation includes that.
124 To convert text parts other than text/plain, an external program can
125 be used, via the
126 .B \-reformat
127 switch.
128 .PP
129 The
130 .B \-reformat
131 switch enables a transformation for text parts in the message. For
132 each text part that is not text/plain and that does not have a
133 corresponding text/plain in a multipart/alternative part,
134 .B mhfixmsg
135 looks for a mhfixmsg-format-text/subtype profile entry that matches
136 the subtype of the part. If one is found and can be used to
137 successfully convert the part to text/plain,
138 .B mhfixmsg
139 inserts that text/plain part at the beginning of the containing
140 multipart/alternative part, if present. If not, it creates a
141 multipart/alternative part.
142 .PP
143 With the
144 .B \-reformat
145 switch, multipart/related parts are handled differently than
146 multipart/alternative. If the multipart/related has only a single
147 part that is not text/plain and can be converted to text/plain, a
148 text/plain part is added and the type of the part is changed to
149 multipart/alternative. If the multipart/related has more than one
150 part but does not have a text/plain part,
151 .B mhfixmsg
152 tries to add one.
153 .PP
154 The
155 .B \-replacetextplain
156 switch broadens the applicability of
157 .BR \-reformat ,
158 by always replacing a corresponding text/plain part, if one exists.
159 If
160 .B \-verbose
161 is enabled, the replacement will be shown as two steps: a removal of
162 the text/plain part, followed by the usual insertion of a new part.
163 .PP
164 .B \-reformat
165 requires a profile entry for each text part subtype to be reformatted.
166 The mhfixmsg-format-text/subtype profile entries are based on external
167 conversion programs, and are used in the same way that
168 .B mhshow
169 uses its mhshow-show-text/subtype entries. When
170 .B nmh
171 is installed, it searches for a conversion program for text/html
172 content, and if one is found, inserts a mhfixmsg-format-text/html
173 entry in %nmhetcdir%/mhn.defaults. An entry of the same name in the
174 user's profile takes precedence. The user can add entries for
175 other text subtypes to their profile.
176 .PP
177 The
178 .B \-fixboundary
179 switch enables a transformation to repair the boundary portion of the
180 Content-Type header field of the message to match the boundaries of
181 the outermost multipart part of the message, if it does not. That
182 condition is indicated by a \*(lqbogus multipart content in
183 message\*(rq error message from
184 .B mhlist
185 and other
186 .B nmh
187 programs that parse MIME messages.
188 .PP
189 The
190 .B \-fixcte
191 switch enables a transformation to change the
192 Content-Transfer-Encoding from an invalid value to 8-bit in message
193 parts with a Content-Type of multipart and message, as required by
194 RFC 2045, §6.4. That condition is indicated by a \*(lqmust be
195 encoded in 7bit, 8bit, or binary\*(rq error message from
196 .B mhlist
197 and other
198 .B nmh
199 programs that parse MIME messages.
200 .PP
201 The
202 .B \-fixtype
203 switch ensures that each part of the message has the correct MIME type
204 shown in its Content-Type header. It may be repeated. It is
205 typically used to replace \*(lqapplication/octet-stream\*(rq with a
206 more descriptive MIME type. It may not be used for multipart and
207 message types.
208 .PP
209 .B mhfixmsg
210 applies two transformations unconditionally.
211 The first removes an extraneous trailing semicolon from the parameter
212 lists of MIME header field values.
213 The second replaces RFC 2047 encoding with RFC 2231 encoding of name
214 and filename parameters in Content-Type and Content-Disposition header
215 field values, respectively.
216 .PP
217 The
218 .B \-verbose
219 switch directs
220 .B mhfixmsg
221 to output informational message for each transformation applied.
222 .PP
223 The return status of
224 .B mhfixmsg
225 is 0 if all of the requested transformations are performed, or
226 non-zero otherwise.
227 .RB ( mhfixmsg
228 will not decode to binary content with the default
229 .B \-decodetext
230 setting, but a request to do so is not considered a failure, and is noted
231 with
232 .BR \-verbose .)
233 If a problem is detected with any one of multiple messages such that
234 the return status is non-zero, then none of the messages will be
235 modified.
236 .PP
237 The
238 .B \-file
239 .I file
240 switch directs
241 .B mhfixmsg
242 to use the specified file as the source message, rather than a message
243 from a folder. Only one file argument may be provided. The
244 .B \-file
245 switch is implied if
246 .I file
247 is an absolute pathname. If the file is \*(lq-\*(rq, then
248 .B mhfixmsg
249 accepts the source message on the standard input stream. If the
250 .B \-outfile
251 switch is not enabled when using the standard input stream,
252 .B mhfixmsg
253 will not produce a transformed output message.
254 .PP
255 .BR mhfixmsg ,
256 by default, transforms the message in place. If the
257 .B \-outfile
258 switch is enabled, then
259 .B mhfixmsg
260 does not modify the input message or file, but instead places its
261 output in the specified file. An outfile name of \*(lq-\*(rq
262 specifies the standard output stream.
263 .PP
264 Combined with the
265 .B \-verbose
266 switch, the
267 .B \-outfile
268 switch can be used to show what transformations
269 .B mhfixmsg
270 would apply without actually applying them, e.g.,
271 .PP
272 .RS 5
273 mhfixmsg -outfile /dev/null -verbose
274 .RE
275 .PP
276 As always, this usage obeys any
277 .B mhfixmsg
278 switches in the user's profile.
279 .PP
280 .B \-outfile
281 can be combined with
282 .B rcvstore
283 to add a single transformed message to a different folder, e.g.,
284 .PP
285 .RS 5
286 mhfixmsg -outfile - | \\
287 .RS 0
288 %nmhlibexecdir%/rcvstore +folder
289 .RE
290 .RE
291 .SS Summary of Applicability
292 The transformations apply to the parts of a message depending on
293 content type and/or encoding as follows:
294 .PP
295 .RS 5
296 .nf
297 .ta \w'\-crlflinebreaks 'u
298 \-decodetext base64 and quoted-printable encoded text parts
299 \-decodetypes limits parts to which -decodetext applies
300 \-crlflinebreaks text parts
301 \-textcharset text/plain parts
302 \-reformat text parts that are not text/plain
303 \-fixboundary outermost multipart part
304 \-fixcte multipart or message part
305 \-fixtype all except multipart and message parts
306 .fi
307 .RE
308 .SS "Backup of Original Message/File"
309 If it applies any transformations to a message or file, and the
310 .B \-outfile
311 switch is not used,
312 .B mhfixmsg
313 backs up the original the same way as
314 .BR rmm .
315 That is, it uses the
316 .I rmmproc
317 profile component, if present. If not present,
318 .B mhfixmsg
319 moves the original message to a backup file.
320 The
321 .B \-rmmproc
322 switch may be used to override this profile component. The
323 .B \-normmproc
324 switch disables the use of any
325 .I rmmproc
326 profile component and negates all prior
327 .B \-rmmproc
328 switches.
329 .SS "Integration with inc"
330 .B mhfixmsg
331 can be used as an add-hook, as described in %docdir%/README-HOOKS.
332 Note that add-hooks are called from all
333 .B nmh
334 programs that add a message to a folder, not just
335 .BR inc .
336 Alternatively, a simple shell alias or function can be used to call
337 .B mhfixmsg
338 immediately after a successful invocation of
339 .BR inc .
340 One approach could be based on:
341 .PP
342 .RS 5
343 msgs=`inc -format '%(msg)'` && [ -n "$msgs" ] && scan $msgs && \
344 mhfixmsg -nochangecur $msgs
345 .RE
346 .PP
347 Another approach would rely on adding a sequence to Unseen-Sequence,
348 which
349 .B inc
350 sets with the newly incorporated messages. Those could then be
351 supplied to
352 .BR mhfixmsg .
353 An example is shown below.
354 .SS "Integration with procmail"
355 By way of example, here is an excerpt from a procmailrc file
356 that filters messages through
357 .B mhfixmsg
358 before storing them in the user's
359 .I nmh-workers
360 folder. It also stores the incoming message in the
361 .I Backups
362 folder in a filename generated by
363 .BR mkstemp ,
364 which is a non-POSIX utility to generate a temporary file.
365 Alternatively,
366 .B mhfixmsg
367 could be called on the message after it is stored.
368 .PP
369 .RS 5
370 .nf
371 .ta \w'\-fixboundary 'u
372 PATH = %bindir%:$PATH
373 LANG = en_US.utf8
374 MAILDIR = `mhparam path`
375 #### The Backups directory is relative to MAILDIR.
376 MKSTEMP = 'mkstemp -directory Backups -prefix mhfixmsg'
377 MHFIXMSG = 'mhfixmsg -noverbose -file - -outfile -'
378 STORE = %nmhlibexecdir%/rcvstore
379
380 :0 w: nmh-workers/procmail.$LOCKEXT
381 * ^TOnmh-workers@nongnu.org
382 | tee `$MKSTEMP` | $MHFIXMSG | $STORE +nmh-workers
383 .fi
384 .RE
385 .SH "EXAMPLES"
386 .SS Basic usage
387 To run
388 .B mhfixmsg
389 on the current message in the current folder, with default transformations to
390 fix MIME boundaries and Content-Transfer-Encoding, to decode text and
391 application/ics content parts to 8 bit, and to add a corresponding text/plain
392 part where lacking:
393 .PP
394 .RS
395 .nf
396 mhfixmsg -verbose
397 .fi
398 .RE
399 .SS Specified folder and messages
400 To run
401 .B mhfixmsg
402 on specified messages, without its informational output:
403 .PP
404 .RS
405 .nf
406 mhfixmsg +inbox last:4
407 .fi
408 .RE
409 .SS View without modification
410 By default,
411 .B mhfixmsg
412 transforms the message in place.
413 To view the MIME structure that would result from running
414 .B mhfixmsg
415 on the current message, without modifying the message:
416 .PP
417 .RS
418 .nf
419 mhfixmsg -outfile - | mhlist -file -
420 .fi
421 .RE
422 .SS Search message without modification
423 To search the current message, which possibly contains base64
424 or quoted printable encoded text parts, without modifying it,
425 use the
426 .B \-outfile
427 switch:
428 .PP
429 .RS
430 .nf
431 mhfixmsg -outfile - | grep \fIpattern\fR
432 .fi
433 .RE
434 .PP
435 .B \-outfile
436 can be abbreviated in usual MH fashion, e.g., to -o. The search will be
437 on the entire message, not just text parts.
438 .SS Translate text/plain parts to UTF-8
439 To translate all text/plain parts in the current message to UTF-8, in addition
440 to all of the default transformations:
441 .PP
442 .RS
443 .nf
444 mhfixmsg -textcharset utf-8
445 .fi
446 .RE
447 .SS Fix all messages in a folder
448 To run
449 .B mhfixmsg
450 on all of the messages in a folder:
451 .PP
452 .RS
453 .nf
454 mhfixmsg +folder all
455 .fi
456 .RE
457 .PP
458 Alternatively,
459 .B mhfixmsg
460 can be run on each message separately, e.g., using a Bourne shell loop:
461 .PP
462 .RS
463 .nf
464 for msg in `pick +folder`; do mhfixmsg +folder $msg; done
465 .fi
466 .RE
467 .PP
468 The two appearances of the
469 .B +folder
470 switch in that command protect against concurrent context changes by other
471 .B nmh
472 command invocations.
473 .SS Run on newly incorporated messages
474 To run
475 .B mhfixmsg
476 on messages as they are incorporated:
477 .PP
478 .RS
479 .nf
480 inc && mhfixmsg -nochangecur unseen
481 .fi
482 .RE
483 .PP
484 This assumes that the Unseen-Sequence profile entry is set to
485 .BR unseen ,
486 as shown in
487 .IR mh-profile (5).
488 .SH FILES
489 .B mhfixmsg
490 looks for mhn.defaults in multiple locations: absolute pathnames are
491 accessed directly, tilde expansion is done on usernames, and files are
492 searched for in the user's
493 .I Mail
494 directory as specified in their profile. If not found there, the directory
495 .RI \*(lq %nmhetcdir% \*(rq
496 is checked.
497 .PP
498 .fc ^ ~
499 .nf
500 .ta \w'%nmhetcdir%/mhn.defaults 'u
501 ^$HOME/.mh_profile~^The user profile
502 ^%nmhetcdir%/mhn.defaults~^Default mhfixmsg conversion entries
503 .fi
504 .SH "PROFILE COMPONENTS"
505 .fc ^ ~
506 .nf
507 .ta 2.4i
508 .ta \w'ExtraBigProfileName 'u
509 ^Path:~^To determine the user's nmh directory
510 ^Current\-Folder:~^To find the default current folder
511 ^rmmproc:~^Program to delete original messages or files
512 .fi
513 .SH "SEE ALSO"
514 .IR iconv (3),
515 .IR inc (1),
516 .IR mh-mkstemp (1),
517 .IR mh-profile (5),
518 .IR mhbuild (1),
519 .IR mhlist (1),
520 .IR mhparam (1),
521 .IR mhshow (1),
522 .IR procmail (1),
523 .IR procmailrc (5),
524 .IR rcvstore (1),
525 .IR rmm (1)
526 .SH DEFAULTS
527 .nf
528 .RB ` +folder "' defaults to the current folder"
529 .RB ` msgs "' defaults to cur"
530 .RB ` "\-decodetext 8bit"'
531 .RB ` "\-decodetypes text,application/ics"'
532 .RB ` \-crlflinebreaks '
533 .RB ` \-notextcharset '
534 .RB ` \-reformat '
535 .RB ` \-noreplacetextplain '
536 .RB ` \-fixboundary '
537 .RB ` \-fixcte '
538 .RB ` \-changecur '
539 .RB ` \-noverbose '
540 .fi
541 .SH CONTEXT
542 If a folder is given, it will become the current folder. The last
543 message selected from a folder will become the current message, unless
544 the
545 .B \-nochangecur
546 switch is enabled. If the
547 .B \-file
548 switch or an absolute pathname is used, the context will not be
549 modified.