1MHFIXMSG(1) General Commands Manual MHFIXMSG(1)
2
3
4
6 mhfixmsg - nmh's MIME-email rewriter with various transformations
7
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
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
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
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
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
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
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
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)