1 .TH MHFIXMSG %manext1% 2018-01-14 "%nmhversion%"
6 mhfixmsg \- nmh's MIME-email rewriter with various transformations
15 .IR "absolute pathname" " | "
22 .IR "type/[subtype][,...]" ]
23 .RB [ \-decodeheaderfieldbodies
25 .BR \-nodecodeheaderfieldbodies ]
26 .RB [ \-crlflinebreaks " | " \-nocrlflinebreaks ]
29 .RB "| " \-notextcharset ]
30 .RB [ \-reformat " | " \-noreformat ]
31 .RB [ \-replacetextplain " | " \-noreplacetextplain ]
32 .RB [ \-fixboundary " | " \-nofixboundary ]
33 .RB [ \-fixcte " | " \-nofixcte ]
41 .RB [ \-changecur " | " \-nochangecur ]
42 .RB [ \-verbose " | " \-noverbose ]
46 rewrites MIME messages, applying specific transformations such as
47 decoding of MIME-encoded message parts and repairing invalid MIME
50 MIME messages are specified in RFC 2045 to RFC 2049
55 command is invaluable for viewing the content structure of MIME
58 passes non-MIME messages through without any transformations. If no
59 transformations apply to a MIME message, the original message or file
60 is not modified or removed. Thus,
62 can safely be run multiple times on a message.
66 switch enables a transformation to decode each base64 and quoted-printable
67 text message part to the selected 8-bit, 7-bit, or
69 If 7-bit is selected for a base64 part but it will only fit
70 8-bit, as defined by RFC 2045, then it will be decoded to 8-bit
72 Similarly, with 8-bit, if the decoded text would be binary,
73 then the part is not decoded (and a message will be displayed if
75 is enabled). Note that
77 binary can produce messages that are not compliant with RFC 5322, \(sc2.1.1.
81 switch is enabled, each carriage return character that precedes a
82 linefeed character is removed from text parts encoded in ASCII,
83 ISO-8859-x, UTF-8, or Windows-12xx.
87 switch specifies the message parts, by type and optionally subtype,
90 applies. Its argument is a comma-separated list of type/subtype
91 elements. If an element does not contain a subtype, then
93 applies to all subtypes of the type. The default is
96 it can be overridden, e.g., with
101 to just text/plain parts.
104 .B \-decodeheaderfieldbodies
105 switch enables decoding of UTF-8 header field bodies, when supplied
109 .B \-nodecodeheaderfieldbodies
110 inhibits this transformation. The transformation can produce a message
111 that does not conform with RFC 2047, \(sc1, paragraph 6, because the decoded
112 header field body could contain unencoded non-ASCII characters. It is
113 therefore not enabled by default.
115 By default, carriage return characters are preserved or inserted at
116 the end of each line of text content. The
118 switch selects this behavior and is enabled by default. The
119 .B \-nocrlflinebreaks
120 switch causes carriage return characters to be stripped from, and not
121 inserted in, text content when it is decoded and encoded. Note that
122 its use can cause the generation of MIME messages that do not conform
123 with RFC 2046, \(sc4.1.1, paragraph 1.
127 switch specifies that all text/plain parts of the message(s)
128 should be converted to
130 Charset conversions require that
136 for how determine whether your
138 installation includes that.
139 To convert text parts other than text/plain, an external program can
146 switch enables a transformation for text parts in the message. For
147 each text part that is not text/plain and that does not have a
148 corresponding text/plain in a multipart/alternative part,
150 looks for a mhfixmsg-format-text/subtype profile entry that matches
151 the subtype of the part. If one is found and can be used to
152 successfully convert the part to text/plain,
154 inserts that text/plain part at the beginning of the containing
155 multipart/alternative part, if present. If not, it creates a
156 multipart/alternative part.
160 switch, multipart/related parts are handled differently than
161 multipart/alternative. If the multipart/related has only a single
162 part that is not text/plain and can be converted to text/plain, a
163 text/plain part is added and the type of the part is changed to
164 multipart/alternative. If the multipart/related has more than one
165 part but does not have a text/plain part,
170 .B \-replacetextplain
171 switch broadens the applicability of
173 by always replacing a corresponding text/plain part, if one exists.
176 is enabled, the replacement will be shown as two steps: a removal of
177 the text/plain part, followed by the usual insertion of a new part.
180 requires a profile entry for each text part subtype to be reformatted.
181 The mhfixmsg-format-text/subtype profile entries are based on external
182 conversion programs, and are used in the same way that
184 uses its mhshow-show-text/subtype entries. When
186 is installed, it searches for a conversion program for text/html
187 content, and if one is found, inserts a mhfixmsg-format-text/html
188 entry in %nmhetcdir%/mhn.defaults. An entry of the same name in the
189 user's profile takes precedence. The user can add entries for
190 other text subtypes to their profile.
194 switch enables a transformation to repair the boundary portion of the
195 Content-Type header field of the message to match the boundaries of
196 the outermost multipart part of the message, if it does not. That
197 condition is indicated by a \*(lqbogus multipart content in
198 message\*(rq error message from
202 programs that parse MIME messages.
206 switch enables a transformation to change the
207 Content-Transfer-Encoding from an invalid value to 8-bit in message
208 parts with a Content-Type of multipart and message, as required by
209 RFC 2045, \(sc6.4. That condition is indicated by a \*(lqmust be
210 encoded in 7bit, 8bit, or binary\*(rq error message from
214 programs that parse MIME messages.
218 switch ensures that each part of the message has the correct MIME type
219 shown in its Content-Type header. It may be repeated. It is
220 typically used to replace \*(lqapplication/octet-stream\*(rq with a
221 more descriptive MIME type. It may not be used for multipart and
225 applies two transformations unconditionally.
226 The first removes an extraneous trailing semicolon from the parameter
227 lists of MIME header field values.
228 The second replaces RFC 2047 encoding with RFC 2231 encoding of name
229 and filename parameters in Content-Type and Content-Disposition header
230 field values, respectively.
236 to output informational message for each transformation applied.
240 is 0 if all of the requested transformations are performed, or
243 will not decode to binary content with the default
245 setting, but a request to do so is not considered a failure, and is noted
248 If a problem is detected with any one of multiple messages such that
249 the return status is non-zero, then none of the messages will be
257 to use the specified file as the source message, rather than a message
258 from a folder. Only one file argument may be provided. The
262 is an absolute pathname. If the file is \*(lq-\*(rq, then
264 accepts the source message on the standard input stream. If the
266 switch is not enabled when using the standard input stream,
268 will not produce a transformed output message.
271 by default, transforms the message in place. If the
273 switch is enabled, then
275 does not modify the input message or file, but instead places its
276 output in the specified file. An outfile name of \*(lq-\*(rq
277 specifies the standard output stream.
283 switch can be used to show what transformations
285 would apply without actually applying them, e.g.,
288 mhfixmsg -outfile /dev/null -verbose
291 As always, this usage obeys any
293 switches in the user's profile.
298 to add a single transformed message to a different folder, e.g.,
301 mhfixmsg -outfile - | \\
303 %nmhlibexecdir%/rcvstore +folder
306 .SS Summary of Applicability
307 The transformations apply to the parts of a message depending on
308 content type and/or encoding as follows:
312 .ta \w'\-decodeheaderfieldbodies 'u
313 \-decodetext base64 and quoted-printable encoded text parts
314 \-decodetypes limits parts to which -decodetext applies
315 \-decodeheaderfieldbodies all message parts
316 \-crlflinebreaks text parts
317 \-textcharset text/plain parts
318 \-reformat text parts that are not text/plain
319 \-fixboundary outermost multipart part
320 \-fixcte multipart or message part
321 \-fixtype all except multipart and message parts
324 .SS "Backup of Original Message/File"
325 If it applies any transformations to a message or file, and the
329 backs up the original the same way as
333 profile component, if present. If not present,
335 moves the original message to a backup file.
338 switch may be used to override this profile component. The
340 switch disables the use of any
342 profile component and negates all prior
345 .SS "Integration with inc"
347 can be used as an add-hook, as described in %docdir%/README-HOOKS.
348 Note that add-hooks are called from all
350 programs that add a message to a folder, not just
352 Alternatively, a simple shell alias or function can be used to call
354 immediately after a successful invocation of
356 One approach could be based on:
359 msgs=\`inc -format '%(msg)'\` && [ -n "$msgs" ] && scan $msgs && \
360 mhfixmsg -nochangecur $msgs
363 Another approach would rely on adding a sequence to Unseen-Sequence,
366 sets with the newly incorporated messages. Those could then be
369 An example is shown below.
370 .SS "Integration with procmail"
371 By way of example, here is an excerpt from a procmailrc file
372 that filters messages through
374 before storing them in the user's
376 folder. It also stores the incoming message in the
378 folder in a filename generated by
380 which is a non-POSIX utility to generate a temporary file.
383 could be called on the message after it is stored.
387 .ta \w'\-fixboundary 'u
388 PATH = %bindir%:$PATH
390 MAILDIR = \`mhparam path\`
391 #### The Backups directory is relative to MAILDIR.
392 MKSTEMP = 'mkstemp -directory Backups -prefix mhfixmsg'
393 MHFIXMSG = 'mhfixmsg -noverbose -file - -outfile -'
394 STORE = %nmhlibexecdir%/rcvstore
396 :0 w: nmh-workers/procmail.$LOCKEXT
397 * ^TOnmh-workers@nongnu.org
398 | tee \`$MKSTEMP\` | $MHFIXMSG | $STORE +nmh-workers
405 on the current message in the current folder, with default transformations to
406 fix MIME boundaries and Content-Transfer-Encoding, to decode text and
407 application/ics content parts to 8 bit, and to add a corresponding text/plain
415 .SS Specified folder and messages
418 on specified messages, without its informational output:
422 mhfixmsg +inbox last:4
425 .SS View without modification
428 transforms the message in place.
429 To view the MIME structure that would result from running
431 on the current message, without modifying the message:
435 mhfixmsg -outfile - | mhlist -file -
438 .SS Search message without modification
439 To search the current message, which possibly contains base64
440 or quoted printable encoded text parts, without modifying it,
447 mhfixmsg -outfile - | grep \fIpattern\fR
452 can be abbreviated in usual MH fashion, e.g., to -o. The search will be
453 on the entire message, not just text parts.
454 .SS Translate text/plain parts to UTF-8
455 To translate all text/plain parts in the current message to UTF-8, in addition
456 to all of the default transformations:
460 mhfixmsg -textcharset utf-8
463 .SS Fix all messages in a folder
466 on all of the messages in a folder:
476 can be run on each message separately, e.g., using a Bourne shell loop:
480 for msg in \`pick +folder\`; do mhfixmsg +folder $msg; done
484 The two appearances of the
486 switch in that command protect against concurrent context changes by other
489 .SS Run on newly incorporated messages
492 on messages as they are incorporated:
496 inc && mhfixmsg -nochangecur unseen
500 This assumes that the Unseen-Sequence profile entry is set to
506 looks for mhn.defaults in multiple locations: absolute pathnames are
507 accessed directly, tilde expansion is done on usernames, and files are
508 searched for in the user's
510 directory as specified in their profile. If not found there, the directory
511 .RI \*(lq %nmhetcdir% \*(rq
516 .ta \w'%nmhetcdir%/mhn.defaults 'u
517 ^$HOME/.mh_profile~^The user profile
518 ^%nmhetcdir%/mhn.defaults~^Default mhfixmsg conversion entries
520 .SH "PROFILE COMPONENTS"
524 .ta \w'ExtraBigProfileName 'u
525 ^Path:~^To determine the user's nmh directory
526 ^Current\-Folder:~^To find the default current folder
527 ^rmmproc:~^Program to delete original messages or files
544 .RB ` +folder "' defaults to the current folder"
545 .RB ` msgs "' defaults to cur"
546 .RB ` "\-decodetext 8bit"'
547 .RB ` "\-decodetypes text,application/ics"'
548 .RB ` \-nodecodeheaderfieldbodies '
549 .RB ` \-crlflinebreaks '
550 .RB ` \-notextcharset '
552 .RB ` \-noreplacetextplain '
553 .RB ` \-fixboundary '
559 If a folder is given, it will become the current folder. The last
560 message selected from a folder will become the current message, unless
563 switch is enabled. If the
565 switch or an absolute pathname is used, the context will not be