1MHFIXMSG(1)                 General Commands Manual                MHFIXMSG(1)
2
3
4

NAME

6       mhfixmsg - nmh's MIME-email rewriter with various transformations
7

SYNOPSIS

9       mhfixmsg [-help] [-version] [+folder] [msgs | absolute pathname | -file
10            file] [-decodetext 8bit|7bit|binary | -nodecodetext] [-decodetypes
11            type/[subtype][,...]]  [-decodeheaderfieldbodies utf-8 | -node‐
12            codeheaderfieldbodies] [-crlflinebreaks | -nocrlflinebreaks]
13            [-textcharset charset | -notextcharset] [-reformat | -noreformat]
14            [-replacetextplain | -noreplacetextplain] [-fixboundary |
15            -nofixboundary] [-fixcte | -nofixcte] [-checkbase64 | -nocheck‐
16            base64] [-fixtype mimetype] [-outfile outfile] [-rmmproc program]
17            [-normmproc] [-changecur | -nochangecur] [-verbose | -noverbose]
18

DESCRIPTION

20       mhfixmsg rewrites MIME messages, applying specific transformations such
21       as decoding of MIME-encoded message parts and  repairing  invalid  MIME
22       headers.
23
24       MIME  messages  are specified in RFC 2045 to RFC 2049 (see mhbuild(1)).
25       The mhlist command is invaluable for viewing the content  structure  of
26       MIME  messages.   mhfixmsg passes non-MIME messages through without any
27       transformations.  If no transformations apply to a  MIME  message,  the
28       original  message  or  file is not modified or removed.  Thus, mhfixmsg
29       can safely be run multiple times on a message.
30
31       The -decodetext switch enables a transformation to decode  each  base64
32       and quoted-printable text message part to the selected 8-bit, 7-bit, or
33       binary encoding.  If 7-bit is selected for a base64 part  but  it  will
34       only  fit  8-bit,  as  defined  by RFC 2045, then it will be decoded to
35       8-bit quoted-printable.  Similarly, with 8-bit,  if  the  decoded  text
36       would  be  binary,  then the part is not decoded (and a message will be
37       displayed if -verbose is enabled).  Note that  -decodetext  binary  can
38       produce messages that are not compliant with RFC 5322, §2.1.1.
39
40       When  the -decodetext switch is enabled, each carriage return character
41       that precedes a linefeed character is removed from text  parts  encoded
42       in ASCII, ISO-8859-x, UTF-8, or Windows-12xx.
43
44       The  -decodetypes  switch  specifies the message parts, by type and op‐
45       tionally subtype, to which -decodetext  applies.   Its  argument  is  a
46       comma-separated  list of type/subtype elements.  If an element does not
47       contain a subtype, then -decodetext applies  to  all  subtypes  of  the
48       type.   The  default  -decodetypes includes text; it can be overridden,
49       e.g., with -decodetypes text/plain  to  restrict  -decodetext  to  just
50       text/plain parts.
51
52       The  -decodeheaderfieldbodies  switch  enables decoding of header field
53       bodies to the specified character set.  The  -nodecodeheaderfieldbodies
54       inhibits this transformation.  The transformation can produce a message
55       that does not conform with RFC 2047, §1, paragraph 6, because  the  de‐
56       coded  header  field body could contain unencoded non-ASCII characters.
57       It is therefore not enabled by default.  Decoding of most header  field
58       bodies, or to a character set that is different from that of the user's
59       locale, requires that nmh be built with iconv(3);  see  mhparam(1)  for
60       how to determine whether your nmh installation includes that.
61
62       By default, carriage return characters are preserved or inserted at the
63       end of each line of text content.  The -crlflinebreaks  switch  selects
64       this  behavior and is enabled by default.  The -nocrlflinebreaks switch
65       causes carriage return characters to be stripped from, and not inserted
66       in, text content when it is decoded and encoded.  Note that its use can
67       cause the generation of MIME messages that  do  not  conform  with  RFC
68       2046, §4.1.1, paragraph 1.
69
70       The -textcharset switch specifies that all text/plain parts of the mes‐
71       sage(s) should be converted to charset.   Charset  conversions  require
72       that  nmh  be  built with iconv(3); see mhparam(1) for how to determine
73       whether your nmh installation includes that.   To  convert  text  parts
74       other than text/plain, an external program can be used, via the -refor‐
75       mat switch.  The -textcharset switch can also be used, depending on the
76       nmh  installation  as  described  below,  to  specify  the Content-Type
77       charset parameter for text/plain parts added with -reformat.
78
79       The -reformat switch enables a transformation for  text  parts  in  the
80       message.   For  each text part that is not text/plain and that does not
81       have a corresponding text/plain in a  multipart/alternative  part,  mh‐
82       fixmsg  looks  for  a  mhfixmsg-format-text/subtype  profile entry that
83       matches the subtype of the part.  If one is found and can  be  used  to
84       successfully  convert  the  part  to  text/plain, mhfixmsg inserts that
85       text/plain part at the beginning of the  containing  multipart/alterna‐
86       tive  part,  if  present.   If  not, it creates a multipart/alternative
87       part.
88
89       With the -reformat switch, multipart/related parts are handled  differ‐
90       ently  than multipart/alternative.  If the multipart/related has only a
91       single part that is not text/plain and can be converted to  text/plain,
92       a  text/plain part is added and the type of the part is changed to mul‐
93       tipart/alternative.  If the multipart/related has more  than  one  part
94       but does not have a text/plain part, mhfixmsg tries to add one.
95
96       The  -replacetextplain  switch broadens the applicability of -reformat,
97       by always replacing a corresponding text/plain part, if one exists.  If
98       -verbose is enabled, the replacement will be shown as two steps:  a re‐
99       moval of the text/plain part, followed by the usual insertion of a  new
100       part.
101
102       -reformat requires a profile entry for each text part subtype to be re‐
103       formatted.  The mhfixmsg-format-text/subtype profile entries are  based
104       on  external  conversion  programs,  and  are used in the same way that
105       mhshow uses its mhshow-show-text/subtype  entries.   When  nmh  is  in‐
106       stalled,  it  searches  for a conversion program for text/html content,
107       and if one is  found,  inserts  a  mhfixmsg-format-text/html  entry  in
108       /etc/nmh/mhn.defaults.  An entry of the same name in the user's profile
109       takes precedence.  The user can add entries for other text subtypes  to
110       their profile.
111
112       The  character  set (charset) of text/plain parts added by -reformat is
113       determined by the external program that generates the content.   Detec‐
114       tion  of  the  content  charset depends on how the nmh installation was
115       configured.  If a program, such as file with a --mime-encoding  option,
116       was  found  that  can  specify the charset of a file, then that will be
117       used for the Content-Type charset parameter.  To determine if your  nmh
118       was  so configured, run mhparam mimeencodingproc and see if a non-empty
119       string is displayed.
120
121       If your nmh was not configured with a program to determine the  charset
122       of a file, then the value of the -textcharset switch is used.  It is up
123       to the user to ensure that the -textcharset value  corresponds  to  the
124       character set of the content generated by the external program.
125
126       The -fixboundary switch enables a transformation to repair the boundary
127       portion of the Content-Type header field of the message  to  match  the
128       boundaries  of  the outermost multipart part of the message, if it does
129       not.  That condition is indicated by a “bogus multipart content in mes‐
130       sage”  error message from mhlist and other nmh programs that parse MIME
131       messages.
132
133       The -fixcte switch enables a  transformation  to  change  the  Content-
134       Transfer-Encoding  from an invalid value to 8-bit in message parts with
135       a Content-Type of multipart and message, as required by RFC 2045, §6.4.
136       That condition is indicated by a “must be encoded in 7bit, 8bit, or bi‐
137       nary” error message from mhlist and other nmh programs that parse  MIME
138       messages.
139
140       The  -checkbase64  switch  enables  a check of the encoding validity in
141       base64-encoded MIME parts.  The check  looks  for  a  non-encoded  text
142       footer  appended  to a base64-encoded part.  Per RFC 2045 §6.8, the oc‐
143       currence of a "=" character signifies the end of base-64  encoded  con‐
144       tent.   If  none is found, a heuristic is used:  specifically, two con‐
145       secutive invalid base64 characters signify the  beginning  of  a  plain
146       text footer.  If a text footer is found and this switch is enabled, mh‐
147       fixmsg separates the base64-encoded and non-encoded content and  places
148       them in a pair of subparts to a newly constructed multipart/mixed part.
149       That multipart/mixed part replaces the original base64-encoded part  in
150       the MIME structure of the message.
151
152       The  -fixtype switch ensures that each part of the message has the cor‐
153       rect MIME type shown in its Content-Type header.  It may  be  repeated.
154       It  is typically used to replace “application/octet-stream” with a more
155       descriptive MIME type.  It may not be used for  multipart  and  message
156       types.
157
158       mhfixmsg  applies  two  transformations unconditionally.  The first re‐
159       moves an extraneous trailing semicolon from the parameter lists of MIME
160       header  field  values.   The second replaces RFC 2047 encoding with RFC
161       2231 encoding of name and filename parameters in Content-Type and  Con‐
162       tent-Disposition header field values, respectively.
163
164       The  -verbose  switch  directs mhfixmsg to output informational message
165       for each transformation applied.
166
167       The return status of mhfixmsg is 0 if all of the requested  transforma‐
168       tions  are performed, or non-zero otherwise.  (mhfixmsg will not decode
169       to binary content with the default -decodetext setting, but  a  request
170       to  do so is not considered a failure, and is noted with -verbose.)  If
171       a problem is detected with any one of multiple messages such  that  the
172       return status is non-zero, then none of the messages will be modified.
173
174       The -file file switch directs mhfixmsg to use the specified file as the
175       source message, rather than a message from a folder.  Only one file ar‐
176       gument  may be provided.  The -file switch is implied if file is an ab‐
177       solute pathname.  If the file is “-”, then mhfixmsg accepts the  source
178       message  on  the  standard input stream.  If the -outfile switch is not
179       enabled when using the standard input stream, mhfixmsg will not produce
180       a transformed output message.
181
182       mhfixmsg, by default, transforms the message in place.  If the -outfile
183       switch is enabled, then mhfixmsg does not modify the input  message  or
184       file,  but instead places its output in the specified file.  An outfile
185       name of “-” specifies the standard output stream.
186
187       Combined with the -verbose switch, the -outfile switch can be  used  to
188       show  what transformations mhfixmsg would apply without actually apply‐
189       ing them, e.g.,
190
191            mhfixmsg -outfile /dev/null -verbose
192
193       As always, this usage obeys any mhfixmsg switches in  the  user's  pro‐
194       file.
195
196       -outfile can be combined with rcvstore to add a single transformed mes‐
197       sage to a different folder, e.g.,
198
199            mhfixmsg -outfile - | \
200            /usr/libexec/nmh/rcvstore +folder
201
202   Summary of Applicability
203       The transformations apply to the parts of a message depending  on  con‐
204       tent type and/or encoding as follows:
205
206            -decodetext              base64 and quoted-printable encoded text parts
207            -decodetypes             limits parts to which -decodetext applies
208            -decodeheaderfieldbodies all message parts
209            -crlflinebreaks          text parts
210            -textcharset             text/plain parts
211            -reformat                text parts that are not text/plain
212            -fixboundary             outermost multipart part
213            -fixcte                  multipart or message part
214            -checkbase64             base64 encoded parts
215            -fixtype                 all except multipart and message parts
216
217   Backup of Original Message/File
218       If  it  applies any transformations to a message or file, and the -out‐
219       file switch is not used, mhfixmsg backs up the original the same way as
220       rmm.   That  is, it uses the rmmproc profile component, if present.  If
221       not present, mhfixmsg moves the original message to a backup file.  The
222       -rmmproc  switch  may  be used to override this profile component.  The
223       -normmproc switch disables the use of any rmmproc profile component and
224       negates all prior -rmmproc switches.
225
226   Integration with inc
227       mhfixmsg    can   be   used   as   an   add-hook,   as   described   in
228       /usr/share/doc/nmh/README-HOOKS.  Note that add-hooks are  called  from
229       all  nmh programs that add a message to a folder, not just inc.  Alter‐
230       natively, a simple shell alias or function can be used to call mhfixmsg
231       immediately  after  a successful invocation of inc.  One approach could
232       be based on:
233
234            msgs=`inc -format '%(msg)'`  &&  [ -n "$msgs" ]   &&   scan  $msgs
235            &&  mhfixmsg -nochangecur $msgs
236
237       Another  approach  would  rely on adding a sequence to Unseen-Sequence,
238       which inc sets with the newly incorporated messages.  Those could  then
239       be supplied to mhfixmsg.  An example is shown below.
240
241   Integration with procmail
242       By  way of example, here is an excerpt from a procmailrc file that fil‐
243       ters messages through mhfixmsg before storing them in the  user's  nmh-
244       workers  folder.   It  also  stores the incoming message in the Backups
245       folder in a filename generated by mkstemp, which is a non-POSIX utility
246       to  generate a temporary file.  Alternatively, mhfixmsg could be called
247       on the message after it is stored.
248
249            PATH = /usr/bin:$PATH
250            LANG = en_US.utf8
251            MAILDIR = `mhparam path`
252            #### The Backups directory is relative to MAILDIR.
253            MKSTEMP = 'mkstemp -directory Backups -prefix mhfixmsg'
254            MHFIXMSG = 'mhfixmsg -noverbose -file - -outfile -'
255            STORE = /usr/libexec/nmh/rcvstore
256
257            :0 w: nmh-workers/procmail.$LOCKEXT
258            * ^TOnmh-workers@nongnu.org
259            | tee `$MKSTEMP` | $MHFIXMSG | $STORE +nmh-workers
260

EXAMPLES

262   Basic usage
263       To run mhfixmsg on the current message in the current folder, with  de‐
264       fault  transformations  to fix MIME boundaries and Content-Transfer-En‐
265       coding, to decode text and application/ics content parts to 8 bit,  and
266       to add a corresponding text/plain part where lacking:
267
268              mhfixmsg -verbose
269
270   Specified folder and messages
271       To  run  mhfixmsg on specified messages, without its informational out‐
272       put:
273
274              mhfixmsg +inbox last:4
275
276   View without modification
277       By default, mhfixmsg transforms the message in place.  To view the MIME
278       structure  that  would result from running mhfixmsg on the current mes‐
279       sage, without modifying the message:
280
281              mhfixmsg -outfile - | mhlist -file -
282
283   Search message without modification
284       To search the current message, which possibly contains base64 or quoted
285       printable  encoded  text  parts, without modifying it, use the -outfile
286       switch:
287
288              mhfixmsg -outfile - | grep pattern
289
290       -outfile can be abbreviated in usual MH  fashion,  e.g.,  to  -o.   The
291       search will be on the entire message, not just text parts.
292
293   Translate text/plain parts to UTF-8
294       To  translate  all text/plain parts in the current message to UTF-8, in
295       addition to all of the default transformations:
296
297              mhfixmsg -textcharset utf-8
298
299   Fix all messages in a folder
300       To run mhfixmsg on all of the messages in a folder:
301
302              mhfixmsg +folder all
303
304       Alternatively, mhfixmsg can be run on each  message  separately,  e.g.,
305       using a Bourne shell loop:
306
307              for msg in `pick +folder`; do mhfixmsg +folder $msg; done
308
309       The  two  appearances  of  the  +folder  switch in that command protect
310       against concurrent context changes by other nmh command invocations.
311
312   Run on newly incorporated messages
313       To run mhfixmsg on messages as they are incorporated:
314
315              inc  &&  mhfixmsg -nochangecur unseen
316
317       This assumes that the Unseen-Sequence profile entry is set  to  unseen,
318       as shown in mh-profile(5).
319

FILES

321       mhfixmsg  looks  for mhn.defaults in multiple locations: absolute path‐
322       names are accessed directly, tilde expansion is done on usernames,  and
323       files  are  searched  for  in the user's Mail directory as specified in
324       their profile.   If  not  found  there,  the  directory  “/etc/nmh”  is
325       checked.
326
327       $HOME/.mh_profile      The user profile
328       /etc/nmh/mhn.defaults  Default mhfixmsg conversion entries
329

PROFILE COMPONENTS

331       Path:                To determine the user's nmh directory
332       Current-Folder:      To find the default current folder
333       rmmproc:             Program to delete original messages or files
334

SEE ALSO

336       iconv(3),  inc(1), mh-mkstemp(1), mh-profile(5), mhbuild(1), mhlist(1),
337       mhparam(1), mhshow(1), procmail(1), procmailrc(5), rcvstore(1), rmm(1)
338

DEFAULTS

340       `+folder' defaults to the current folder
341       `msgs' defaults to cur
342       `-decodetext 8bit'
343       `-decodetypes text,application/ics'
344       `-nodecodeheaderfieldbodies'
345       `-crlflinebreaks'
346       `-notextcharset'
347       `-reformat'
348       `-noreplacetextplain'
349       `-fixboundary'
350       `-fixcte'
351       `-checkbase64'
352       `-changecur'
353       `-noverbose'
354

CONTEXT

356       If a folder is given, it will become the current folder.  The last mes‐
357       sage selected from a folder will become the current message, unless the
358       -nochangecur switch is enabled.  If the -file  switch  or  an  absolute
359       pathname is used, the context will not be modified.
360
361
362
363nmh-1.8                           2022-02-27                       MHFIXMSG(1)
Impressum