]> git.phdru.name Git - mimedecode.git/blob - mimedecode.docbook
Check filenames for --save-* for forbidden characters
[mimedecode.git] / mimedecode.docbook
1 <?xml version="1.0" standalone="no"?>
2 <!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
3   "file:///usr/share/xml/docbook/schema/dtd/4.5/docbookx.dtd">
4
5 <refentry id="mimedecode.py">
6
7 <refentryinfo>
8   <title>mimedecode.py</title>
9   <productname>mimedecode.docbook</productname>
10   <author>
11     <firstname>Oleg</firstname>
12     <surname>Broytman</surname>
13     <email>phd@phdru.name</email>
14     <personblurb/>
15   </author>
16   <copyright>
17     <year>2001-2014</year>
18     <holder>PhiloSoft Design.</holder>
19   </copyright>
20 </refentryinfo>
21
22 <refmeta>
23    <refentrytitle>mimedecode.py</refentrytitle>
24    <manvolnum>1</manvolnum>
25 </refmeta>
26
27 <refnamediv>
28    <refname>mimedecode.py</refname>
29    <refpurpose>decode MIME message</refpurpose>
30 </refnamediv>
31
32 <refsynopsisdiv>
33    <cmdsynopsis>
34       <command>mimedecode.py</command>
35       <arg choice="opt">
36          <option>-h|--help</option>
37       </arg>
38       <arg choice="opt">
39          <option>-V|--version</option>
40       </arg>
41       <arg choice="opt">
42          <option>-cCDP</option>
43       </arg>
44       <arg choice="opt">
45          <option>-f charset</option>
46       </arg>
47       <arg choice="opt">
48          <option>-H|--host=hostname</option>
49       </arg>
50       <arg choice="opt">
51          <option>-d header1[,header2,header3...]</option>
52       </arg>
53       <arg choice="opt">
54          <option>-d *[,-header1,-header2,-header3...]</option>
55       </arg>
56       <arg choice="opt">
57         <option>-p header1[,header2,header3,...]:param1[,param2,param3,...]</option>
58       </arg>
59       <arg choice="opt">
60         <option>-p *[,-header1,-header2,-header3,...]:param1[,param2,param3,...]</option>
61       </arg>
62       <arg choice="opt">
63         <option>-p header1[,header2,header3,...]:*[,-param1,-param2,-param3,...]</option>
64       </arg>
65       <arg choice="opt">
66         <option>-p *[,-header1,-header2,-header3,...]:*[,-param1,-param2,-param3,...]</option>
67       </arg>
68       <arg choice="opt">
69          <option>-r header1[,header2,header3...]</option>
70       </arg>
71       <arg choice="opt">
72          <option>-r *[,-header1,-header2,-header3...]</option>
73       </arg>
74       <arg choice="opt">
75         <option>-R header1[,header2,header3,...]:param1[,param2,param3,...]</option>
76       </arg>
77       <arg choice="opt">
78         <option>-R *[,-header1,-header2,-header3,...]:param1[,param2,param3,...]</option>
79       </arg>
80       <arg choice="opt">
81         <option>-R header1[,header2,header3,...]:*[,-param1,-param2,-param3,...]</option>
82       </arg>
83       <arg choice="opt">
84         <option>-R *[,-header1,-header2,-header3,...]:*[,-param1,-param2,-param3,...]</option>
85       </arg>
86       <arg choice="opt">
87          <option>--set-header header:value</option>
88       </arg>
89       <arg choice="opt">
90          <option>--set-param header:param=value</option>
91       </arg>
92       <arg choice="opt">
93          <option>-Bbeit mask</option>
94       </arg>
95       <arg choice="opt">
96          <option>--save-headers|body|message mask</option>
97       </arg>
98       <arg choice="opt">
99          <option>-O dest_dir</option>
100       </arg>
101       <arg choice="opt">
102          <option>-o output_file</option>
103       </arg>
104       <arg choice="opt">input_file
105         <arg choice="opt">output_file</arg>
106       </arg>
107    </cmdsynopsis>
108 </refsynopsisdiv>
109
110
111 <refsect1>
112 <title>DESCRIPTION</title>
113 <para>
114    Mail users, especially in non-English countries, often find that mail
115    messages arrived in different formats, with different content types, in
116    different encodings and charsets. Usually it is good because it allows to
117    use an appropriate format/encoding/whatever. Sometimes, though, some
118    unification is desirable. For example, one may want to put mail messages
119    into an archive, make HTML indices, run search indexer, etc. In such
120    situations converting messages to text in one character set and skipping
121    some binary attachments is much desirable.
122 </para>
123
124 <para>
125    Here is the solution - mimedecode.py!
126 </para>
127
128 <para>
129    This is a program to decode MIME messages. The program expects one input
130    file (either on command line or on stdin) which is treated as an RFC822
131    message, and decodes to stdout or an output file. If the file is not an
132    RFC822 message it is just copied to the output one-to-one. If the file is a
133    simple RFC822 message it is decoded as one part. If it is a MIME message
134    with multiple parts ("attachments") all parts are decoded. Decoding can be
135    controlled by command-line options.
136 </para>
137
138 <para>
139    First, for every part the program removes headers and parameters listed with
140    -r and -R options. Then, Subject and Content-Disposition headers (and all
141    headers listed with -d and -p options) are examined. If any of those exists,
142    they are decoded according to RFC2047. Content-Disposition header is not
143    decoded - only its "filename" parameter. Encoded header parameters violate
144    the RFC, but widely deployed anyway by ignorant coders who never even heard
145    about RFCs. Correct parameter encoding specified by RFC2231. This program
146    decodes RFC2231-encoded parameters, too.
147 </para>
148
149 <para>
150    Then the body of the message (or the current part) is decoded. Decoding
151    starts with looking at header Content-Transfer-Encoding. If the header
152    specifies non-8bit encoding (usually base64 or quoted-printable), the body
153    converted to 8bit. Then, if its content type is multipart (multipart/related
154    or multipart/mixed, e.g) every part is recursively decoded. If it is not
155    multipart, mailcap database is consulted to find a way to convert the body
156    to plain text. (I have no idea how mailcap can be configured on OSes other
157    than POSIX, please don't ask me; real OS users can consult my example at
158    <ulink url="http://phdru.name/Software/dotfiles/mailcap.html">http://phdru.name/Software/dotfiles/mailcap.html</ulink>).
159    The decoding process uses the first copiousoutput filter it can find. If
160    there are no filters the body just passed as is.
161 </para>
162
163 <para>
164    Then Content-Type header is consulted for charset. If it is not equal to the
165    current locale charset and recoding is allowed the body text is recoded.
166    Finally message headers and the body are flushed to stdout.
167 </para>
168 </refsect1>
169
170 <refsect1>
171   <para>
172     Please be warned that in the following options asterisk is a shell
173     metacharacter and should be escaped or quoted. Either write -d \*,-h1,-h2
174     or -d '*,-h1,-h2' or such.
175   </para>
176 </refsect1>
177
178 <refsect1>
179 <title>OPTIONS</title>
180 <variablelist>
181    <varlistentry>
182       <term>-h</term>
183       <term>-help</term>
184       <listitem>
185          <para>
186             Print brief usage help and exit.
187          </para>
188       </listitem>
189    </varlistentry>
190
191    <varlistentry>
192       <term>-V</term>
193       <term>--version</term>
194       <listitem>
195          <para>
196             Print version and exit.
197          </para>
198       </listitem>
199    </varlistentry>
200
201    <varlistentry>
202       <term>-c</term>
203       <listitem>
204          <para>
205             Recode different character sets in message bodies to the current
206             default charset; this is the default.
207          </para>
208       </listitem>
209    </varlistentry>
210
211    <varlistentry>
212       <term>-C</term>
213       <listitem>
214          <para>
215             Do not recode character sets in message bodies.
216          </para>
217       </listitem>
218    </varlistentry>
219
220    <varlistentry>
221       <term>-f charset</term>
222       <listitem>
223          <para>
224             Force this charset to be the current default charset instead of
225             the current locale.
226          </para>
227       </listitem>
228    </varlistentry>
229
230    <varlistentry>
231       <term>-H hostname</term>
232       <term>--host=hostname</term>
233       <listitem>
234          <para>
235            Use this hostname in X-MIME-Autoconverted headers instead of the
236            current hostname.
237          </para>
238       </listitem>
239    </varlistentry>
240
241    <varlistentry>
242       <term>-d header1[,header2,header3...]</term>
243       <listitem>
244          <para>
245             Add the header(s) to a list of headers to decode; initially the
246             list contains headers "From", "To", "Cc", "Reply-To",
247             "Mail-Followup-To" and "Subject".
248          </para>
249       </listitem>
250    </varlistentry>
251
252    <varlistentry>
253       <term>-d *[,-header1,-header2,-header3...]</term>
254       <listitem>
255          <para>
256            This variant completely changes headers decoding. First, the list of
257            headers to decode is cleared. Then all the headers are decoded
258            except the given list of exceptions (headers listed with '-'). In
259            this mode it would be meaningless to give more than one -d options
260            but the program doesn't enforce it.
261          </para>
262       </listitem>
263    </varlistentry>
264
265    <varlistentry>
266       <term>-D</term>
267       <listitem>
268          <para>
269             Clear the list of headers to decode (make it empty).
270          </para>
271       </listitem>
272    </varlistentry>
273
274    <varlistentry>
275       <term>-p header1[,header2,header3,...]:param1[,param2,param3,...]</term>
276       <listitem>
277          <para>
278             Add the parameters(s) to a list of headers parameters to decode;
279             the parameters will be decoded only for the given header(s).
280             Initially the list contains header "Content-Type", parameter "name";
281             and header "Content-Disposition", parameter "filename".
282          </para>
283       </listitem>
284    </varlistentry>
285
286    <varlistentry>
287       <term>-p *[,-header1,-header2,-header3,...]:param1[,param2,param3,...]</term>
288       <listitem>
289          <para>
290             Add the parameters(s) to a list of headers parameters to decode;
291             the parameters will be decoded for all headers except the given
292             ones.
293          </para>
294       </listitem>
295    </varlistentry>
296
297    <varlistentry>
298       <term>-p header1[,header2,header3,...]:*[,-param1,-param2,-param3,...]</term>
299       <listitem>
300          <para>
301            Decode all parameters except listed for the given list of headers.
302          </para>
303       </listitem>
304    </varlistentry>
305
306    <varlistentry>
307       <term>-p *[,-header1,-header2,-header3,...]:*[,-param1,-param2,-param3,...]</term>
308       <listitem>
309          <para>
310            Decode all parameters except listed for all headers (except listed).
311          </para>
312       </listitem>
313    </varlistentry>
314
315    <varlistentry>
316       <term>-P</term>
317       <listitem>
318          <para>
319             Clear the list of headers parameters to decode (make it empty).
320          </para>
321       </listitem>
322    </varlistentry>
323
324    <varlistentry>
325       <term>-r header1[,header2,header3...]</term>
326       <listitem>
327          <para>
328             Add the header(s) to a list of headers to remove completely;
329             initially the list is empty.
330          </para>
331       </listitem>
332    </varlistentry>
333
334    <varlistentry>
335       <term>-r *[,-header1,-header2,-header3...]</term>
336       <listitem>
337          <para>
338            Remove all headers except listed.
339          </para>
340       </listitem>
341    </varlistentry>
342
343    <varlistentry>
344       <term>-R header1[,header2,header3,...]:param1[,param2,param3,...]</term>
345       <listitem>
346          <para>
347             Add the parameters(s) to a list of headers parameters to remove;
348             the parameters will be decoded only for the given header(s).
349             Initially the list is empty.
350          </para>
351       </listitem>
352    </varlistentry>
353
354    <varlistentry>
355       <term>-R *[,-header1,-header2,-header3,...]:param1[,param2,param3,...]</term>
356    </varlistentry>
357
358    <varlistentry>
359       <term>-R header1[,header2,header3,...]:*[,-param1,-param2,-param3,...]</term>
360    </varlistentry>
361
362    <varlistentry>
363       <term>-R *[,-header1,-header2,-header3,...]:*[,-param1,-param2,-param3,...]</term>
364       <listitem>
365          <para>
366            Remove listed parameters (or all parameters except listed) frome
367            these headers (or from all headers except listed).
368          </para>
369       </listitem>
370    </varlistentry>
371
372    <varlistentry>
373       <term>--set-header header:value</term>
374       <listitem>
375          <para>
376            The program sets or changes value for the header to the given value
377            (only at the top-level message).
378          </para>
379       </listitem>
380    </varlistentry>
381
382    <varlistentry>
383       <term>--set-param header:param=value</term>
384       <listitem>
385          <para>
386            The program sets or changes value for the header's parameter to the
387            given value (only at the top-level message). The header must exist.
388          </para>
389       </listitem>
390    </varlistentry>
391
392    <varlistentry>
393       <term>-B mask</term>
394       <listitem>
395          <para>
396            Append mask to the list of binary content types that will be not
397            content-transfer-decoded (will be left as base64 or such).
398          </para>
399       </listitem>
400    </varlistentry>
401
402    <varlistentry>
403       <term>-b mask</term>
404       <listitem>
405          <para>
406             Append mask to the list of binary content types; if the message to
407             decode has a part of this type the program content-transfer-decodes
408             (base64 or whatever to 8bit binary) it and outputs the decoded part
409             as is, without any further processing.
410          </para>
411       </listitem>
412    </varlistentry>
413
414    <varlistentry>
415       <term>-e mask</term>
416       <listitem>
417          <para>
418             Append mask to the list of error content types; if the message to
419             decode has a part of this type the program fails with ValueError.
420          </para>
421       </listitem>
422    </varlistentry>
423
424    <varlistentry>
425       <term>-i mask</term>
426       <listitem>
427          <para>
428             Append mask to the list of content types to ignore; if the message
429             to decode has a part of this type the program outputs headers but
430             skips the body. Instead a line "Message body of type %s skipped."
431             will be issued.
432          </para>
433       </listitem>
434    </varlistentry>
435
436    <varlistentry>
437       <term>-t mask</term>
438       <listitem>
439          <para>
440             Append mask to the list of content types to convert to text; if the
441             message to decode has a part of this type the program consults
442             mailcap database, find the first copiousoutput filter and, if any
443             filter is found, converts the part.
444          </para>
445       </listitem>
446    </varlistentry>
447
448    <varlistentry>
449       <term>--save-headers mask</term>
450    </varlistentry>
451
452    <varlistentry>
453       <term>--save-body mask</term>
454    </varlistentry>
455
456    <varlistentry>
457       <term>--save-message mask</term>
458       <listitem>
459          <para>
460             Append mask to a list of content types to save to a file;
461             --save-headers saves only decoded headers of the message (or
462             subpart); --save-body saves only decoded body; --save-message saves
463             the entire message or subpart (headers + body).
464          </para>
465       </listitem>
466    </varlistentry>
467
468    <varlistentry>
469       <term>-O dest_dir</term>
470       <listitem>
471          <para>
472            Set destination directory for the output files; if the directory
473            doesn't exist it will be created. Default is the current directory.
474           </para>
475       </listitem>
476    </varlistentry>
477
478    <varlistentry>
479       <term>-o output_file</term>
480       <listitem>
481          <para>
482             Save output to the file related to the destination directory from
483             option -O. Also useful in case of redirected stdin:
484             <programlisting language="sh">mimedecode.py -o output_file &lt; input_file
485 cat input_file | mimedecode.py -o output_file</programlisting>
486          </para>
487       </listitem>
488    </varlistentry>
489 </variablelist>
490
491 <para>
492    The 5 list options (-Bbeit) require more explanation. They allow a user to
493    control body decoding with great flexibility. Think about said mail archive;
494    for example, its maintainer wants to put there only texts, convert
495    PDF/Postscript to text, pass HTML and images as is (decoding base64 to html
496    but left images in base64), and ignore everything else. Easy:
497 </para>
498
499 <para>
500 <code language="sh">
501    mimedecode.py -t application/pdf -t application/postscript -b text/html
502          -B 'image/*' -i '*/*'
503 </code>
504 </para>
505
506 <para>
507    When the program decodes a message (non-MIME or a non-multipart subpart of a
508    MIME message), it consults Content-Type header. The content type is searched
509    in all 5 lists, in order "text-binary-ignore-error". If found, appropriate
510    action performed. If not found, the program search the same lists for
511    "type/*" mask (the type of "text/html" is just "text"). If found,
512    appropriate action performed. If not found, the program search the same
513    lists for "*/*" mask. If found, appropriate action performed. If not found,
514    the program uses default action, which is to decode everything to text (if
515    mailcap specifies a filter).
516 </para>
517
518 <para>
519    Initially all 5 lists are empty, so without any additional parameters
520 the program always uses the default decoding.
521 </para>
522
523 <para>
524   The 3 save options (--save-headers/body/message) are similar. They make the
525   program to save every non-multipart subpart (only headers, or body, or the
526   entire subpart: headers + body) that corresponds to the given mask to a file.
527   Before saving the message (or the subpart) is decoded according to all other
528   options and placed to the output stream as usual. Filename for the file is
529   created using "filename" parameter from the Content-Disposition header, or
530   "name" parameter from the Content-Type header if one of those exist; a serial
531   counter is prepended to the filename to avoid collisions; if there are no
532   name/filename parameters, or the name/filename parameters contain forbidden
533   characters (null, slash, backslash) the filename is just the serial counter.
534   The file is saved in the directory set with -O (default is the current
535   directory).
536 </para>
537 </refsect1>
538
539
540 <refsect1>
541 <title>ENVIRONMENT</title>
542 <variablelist>
543   <varlistentry><term>LANG</term></varlistentry>
544   <varlistentry><term>LC_ALL</term></varlistentry>
545   <varlistentry><term>LC_CTYPE</term></varlistentry>
546 </variablelist>
547 <para>
548   Define current locale settings. Used to determine current default charset (if
549   your Python is properly installed and configured).
550 </para>
551 </refsect1>
552
553
554 <refsect1>
555 <title>BUGS</title>
556 <para>
557    The program may produce incorrect MIME message. The purpose of the program
558    is to decode whatever it is possible to decode, not to produce absolutely
559    correct MIME output. The incorrect parts are obvious - decoded
560    From/To/Cc/Reply-To/Mail-Followup-To/Subject headers and filenames. Other
561    than that output is correct MIME message. The program does not try to guess
562    whether the headers are correct. For example, if a message header states
563    that charset is iso8859-5, but the body is actually in utf-8 the program
564    will recode the message with the wrong charset.
565 </para>
566 </refsect1>
567
568
569 <refsect1>
570 <title>AUTHOR</title>
571 <para>
572   <firstname>Oleg</firstname>
573   <surname>Broytman</surname>
574   <email>phd@phdru.name</email>
575 </para>
576 </refsect1>
577
578
579 <refsect1>
580 <title>COPYRIGHT</title>
581 <para>
582   Copyright (C) 2001-2014 PhiloSoft Design.
583 </para>
584 </refsect1>
585
586
587 <refsect1>
588 <title>LICENSE</title>
589 <para>
590    GNU GPL
591 </para>
592 </refsect1>
593
594
595 <refsect1>
596 <title>NO WARRANTIES</title>
597 <para>
598    This program is distributed in the hope that it will be useful, but WITHOUT
599    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
600    FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
601    more details.
602 </para>
603 </refsect1>
604
605
606 <refsect1>
607 <title>SEE ALSO</title>
608 <para>
609   mimedecode.py home page:
610   <ulink url="http://phdru.name/Software/Python/#mimedecode">http://phdru.name/Software/Python/#mimedecode</ulink>
611 </para>
612 </refsect1>
613
614 </refentry>