source: project/mime/mime.html @ 5159

Last change on this file since 5159 was 5159, checked in by felix winkelmann, 14 years ago

added qdbm

File size: 19.2 KB
Line 
1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2<!-- Generated by eggdoc Revision: 1.17  -->
3<html>
4<head>
5<title>Eggs Unlimited - mime</title><style type="text/css"> <!--
6      CODE {
7            color: #666666;
8          }
9/*   DT.definition EM { font-weight: bold; font-style: normal; } */
10
11     DT.definition { 
12                   background: #eee;
13                   color: black;
14                   padding: 0.2em 1em 0.2em 0.7em;
15                   margin-left: 0.2em;
16border: 1px solid #bbc;
17                   font-family: "Andale Mono", monospace;
18                   /* font-size: 1.2em; */
19                   
20                 }
21     DD {
22                   margin-top: 0.8em;
23                   margin-bottom: 0.8em;
24     }
25     DIV.subsection {
26                    border-top: 1px solid #448;
27                    padding-left: 1em;
28     }
29         DIV.section {
30                 margin-bottom: 1.5em;
31         }
32         a:link {
33                 color: #336;
34         }
35         a:visited { color: #666; }
36         a:active  { color: #966; }
37         a:hover   { color: #669; }
38         body { margin: 0; padding: 0; background: #fff; color: #000; font: 9pt "Lucida Grande", "Verdana", sans-serif; }
39         H2 {
40                 background: #336;
41                 color: #fff;
42                 padding-top: 0.5em;
43                 padding-bottom: 0.5em;
44                 padding-left: 16px;
45                 margin: 0 0 1em 0;
46        }
47        LI {
48                list-style: none;
49        }
50        TT {
51                font-family: "Andale Mono", monospace;
52                /* font-size: 1.2em; */
53        }
54        H3 {
55                color: #113;
56                margin-bottom: 0.5em;
57        }
58     DIV#eggheader {
59         text-align: center;
60                 float: right;
61                 margin-right: 2em;
62     }
63     DIV#header IMG {
64            /* display: block; margin-left: auto; margin-right: auto;  */
65            /* float: right; */
66            border: none;  /* firefox */
67     }
68     DIV#footer {
69                background: #bbd;
70                padding: 0.7em ;
71                border-top: 1px solid #cce;
72     }
73     DIV#footer hr {
74                display: none;
75     }
76     DIV#footer a {
77                float: left;
78     }
79     DIV#revision-history {
80         float: right;
81     }
82     
83     DIV#body {
84                 margin: 1em 1em 1em 16px;
85         }
86
87     DIV#examples PRE {
88       background: #eef;
89       padding: 0.1em;
90       border: 1px solid #aac;
91     }
92     PRE#license, DIV#examples PRE {
93       padding: 0.5em;
94     }
95     DIV#examples PRE {
96       /* font-size: 85%; */
97     }
98     PRE { font-family: "Andale Mono", monospace; }
99     TABLE {
100       background: #eef;
101       padding: 0.2em;
102       border: 1px solid #aac;
103       width: 100%;
104     }
105     TABLE.symbol-table TD.symbol {
106          width: 15em;
107          font-family: "Andale Mono", monospace;
108          /* font-size: 1.2em; */
109     }
110     TH {
111       border-bottom: 1px solid black;
112     } --></style></head>
113<body>
114<div id="header">
115<h2>mime</h2>
116<div id="eggheader"><a href="index.html">
117<img src="egg.jpg" alt="[Picture of an egg]" /></a></div></div>
118<div id="body">
119<div class="section">
120<h3>Description</h3>Parse MIME Messages.</div>
121<div class="section">
122<h3>Author</h3>Shiro Kawai, Chicken-port and some additions by Hans Bulfone</div>
123<div class="section">
124<h3>Version</h3>
125<ul>
126<li>1.0 Initial release</li>
127<li>1.1 Generating MIME messages</li>
128<li>1.2 fixed .setup script to handle change in argument processing of csc</li>
129</ul></div>
130<div class="section">
131<h3>Requires</h3>
132<ul>
133<li>rfc822</li>
134<li>base64</li>
135<li>iconv</li></ul></div>
136<div class="section">
137<h3>Usage</h3><tt>(require-extension mime)</tt></div>
138<div class="section">
139<h3>Download</h3><a href="mime.egg">mime.egg</a></div>
140<div class="section">
141<h3>Documentation</h3>
142<p>This documentation is based on Gauches <tt>rfc.mime</tt> and <tt>rfc.quoted-printable</tt> documentation with some changes where the Chicken version differs.</p>
143<p>This egg provides utility procedures to handle Multipurpose Internet Mail Extensions (MIME) messages, defined in RFC2045 through RFC2049. This egg is supposed to be used with the <tt>rfc822</tt> egg.</p>
144<div class="subsection">
145<p><b>Quoted-printable encoding/decoding</b></p>
146<p>A few functions to encode/decode Quoted-printable format, defined in RFC2045, section 6.7.</p>
147<dl>
148<dt class="definition"><strong>procedure:</strong> (quoted-printable-encode)</dt>
149<dd>Reads a byte stream from the current input port, encodes it in Quoted-printable format and writes the result character stream to the current output port. The conversion ends when it reads <tt>#!eof</tt> from the current input port.</dd>
150<dt class="definition"><strong>procedure:</strong> (quoted-printable-encode-string STRING)</dt>
151<dd>Converts the contents of <tt>STRING</tt> to Quoted-printable encoded format. The input string can be either a complete or incomplete string; it is always interpreted as a byte sequence.</dd>
152<dt class="definition"><strong>procedure:</strong> (quoted-printable-decode)</dt>
153<dd>Reads characters from the current input port, decodes them from Quoted-printable format and writes the result byte stream to the current output port. The conversion ends when it reads <tt>#!eof</tt>. If it encounters illegal character sequences (such as <tt>#\=</tt> followed by non-hexadecimal characters), it copies them literally to the output.</dd>
154<dt class="definition"><strong>procedure:</strong> (quoted-printable-decode-string STRING)</dt>
155<dd>Decodes a Quoted-printable encoded string <tt>STRING</tt> and returns the result as a string.</dd></dl></div>
156<div class="subsection">
157<p><b>Utilities for header fields</b></p>
158<p>A few utility procedures to parse MIME-specific header fields.</p>
159<dl>
160<dt class="definition"><strong>procedure:</strong> (mime-parse-version FIELD)</dt>
161<dd>If <tt>FIELD</tt> is a valid header field for MIME-Version, returns its major and minor versions in a list. Otherwise, returns <tt>#f</tt>. It is allowed to pass <tt>#f</tt> to <tt>FIELD</tt>, so that you can directly pass the result of <tt>rfc822-header-ref</tt> to it. Given a parsed header list from <tt>rfc822-header-&gt;list</tt>, you can get the MIME version (currently, it should be <tt>(1 0)</tt>) by the following code:
162<pre>(mime-parse-version (rfc822-header-ref headers &quot;mime-version&quot;))</pre>Note: simple regexp such as <tt>&quot;\d+\.\d+&quot;</tt> doesn't do this job, for <tt>FIELD</tt> may contain comments between tokens.</dd>
163<dt class="definition"><strong>procedure:</strong> (mime-parse-content-type FIELD)</dt>
164<dd>Parses the &quot;content-type&quot; header field, and returns a list such as:
165<pre>(type subtype (attribute . value) ...)</pre>where <tt>type</tt> and <tt>subtype</tt> are MIME media type and subtype in a string, respectively.
166<pre>(mime-parse-content-type &quot;text/html; charset=iso-2022-jp&quot;)
167=&gt; (&quot;text&quot; &quot;html&quot; (&quot;charset&quot; . &quot;iso-2022-jp&quot;))</pre>If <tt>FIELD</tt> is not a valid content-type field, <tt>#f</tt> is returned.</dd>
168<dt class="definition"><strong>procedure:</strong> (mime-decode-word WORD)</dt>
169<dd>Decodes RFC2047-encoded word. If <tt>WORD</tt> isn't an encoded word, it is returned as is.
170<pre>(mime-decode-word &quot;=?iso-8859-1?q?this=20is=20some=20text?=&quot;)
171=&gt; &quot;this is some text&quot;</pre></dd></dl></div>
172<div class="subsection">
173<p><b>Streaming parser</b></p>
174<p>The streaming parser is designed so that you can decide how to do with the message body before the entire message is read.</p>
175<dl>
176<dt class="definition"><strong>procedure:</strong> (mime-parse-message PORT HEADERS HANDLER)</dt>
177<dd>
178<p>The fundamental streaming parser. <tt>PORT</tt> is an input port from where the mssage is read. <tt>HEADERS</tt> is a list of headers parsed by <tt>rfc822-header-&gt;list</tt>; that is, this procedure is supposed to be called after the header part of the message is parsed from port:</p>
179<pre>(let* ((headers (rfc822-header-&gt;list port)))
180  (if (mime-parse-version (rfc822-header-ref headers &quot;mime-version&quot;))
181     ;; parse MIME message
182     (mime-parse-message port headers handler)
183     ;; retrieve a non-MIME body
184     ...))</pre>
185<p><tt>mime-parse-message</tt> analyzes headers, and calls <tt>HANDLER</tt> on each message body with two arguments:</p>
186<pre>(HANDLER PART-INFO XPORT)</pre>
187<p><tt>PART-INFO</tt> is a <tt>:mime-part</tt> record described below that encapsulates the information of this part of the message. <tt>XPORT</tt> is an input port, initially points to the beginning of the body of message. The handler can read from the port as if it is reading from the original port. However, <tt>XPORT</tt> recognizes MIME boundary internally, and returns <tt>#!eof</tt> when it reaches the end of the part. (Do not read from the original port directly, or it will mess up the internal state of <tt>XPORT</tt>).</p>
188<p><tt>HANDLER</tt> can read the part into the memory, or save it to the disk, or even discard the part. Whatever it does, it has to read from <tt>XPORT</tt> until it returns <tt>#!eof</tt>.</p>
189<p>The return value of handler will be set in the content slot of <tt>PART-INFO</tt>. If the message has nested multipart messages, <tt>HANDLER</tt> is called for each &quot;leaf&quot; part, in depth-first order. <tt>HANDLER</tt> can know its nesting level by examining <tt>PART-INFO</tt> record. The message doesn't need to be a multipart type; if it is a MIME message type, <tt>HANDLER</tt> is called on the body of enclosed message. If it is other media types such as <tt>text</tt> or <tt>application</tt>, <tt>HANDLER</tt> is called on the (only) message body.</p></dd>
190<dt class="definition"><strong>record:</strong> :mime-part</dt>
191<dd>
192<p>A SRFI-9 record that encloses metainformation about a MIME part. It is constructed when the header of the part is read, and passed to the handler that reads the body of the part.</p>
193<p>The following procedures for manipulating <tt>:mime-part</tt>-records exist:</p>
194<dl>
195<dt class="definition"><strong>procedure:</strong> (make-mime-part #:type TYPE #:subtype STYPE #:parameters PARAMS #:transfer-encoding TENC #:parent P #:index I #:headers HDRS #:content C #:attrs ATTRS</dt>
196<dd>Create a <tt>:mime-part</tt>-record.  The arguments default to <tt>&quot;text&quot;</tt>, <tt>&quot;plain&quot;</tt>, <tt>'()</tt>, <tt>&quot;7bit&quot;</tt>, <tt>#f</tt>, <tt>0</tt>, <tt>'()</tt>, <tt>#f</tt>, and <tt>'()</tt>.</dd>
197<dt class="definition"><strong>procedure:</strong> (mime-part:type PART-INFO)</dt>
198<dd></dd>
199<dt class="definition"><strong>procedure:</strong> (mime-part:type-set! PART-INFO TYPE)</dt>
200<dd>MIME media type string. If <tt>content-type</tt> header is omitted to the part, an appropriate default value is set.</dd>
201<dt class="definition"><strong>procedure:</strong> (mime-part:subtype PART-INFO)</dt>
202<dd></dd>
203<dt class="definition"><strong>procedure:</strong> (mime-part:subtype-set! PART-INFO SUBTYPE)</dt>
204<dd>MIME media subtype string. If <tt>content-type</tt> header is omitted to the part, an appropriate default value is set.</dd>
205<dt class="definition"><strong>procedure:</strong> (mime-part:parameters PART-INFO)</dt>
206<dd></dd>
207<dt class="definition"><strong>procedure:</strong> (mime-part:parameters-set! PART-INFO PARAMETERS)</dt>
208<dd>Associative list of parameters given to <tt>content-type</tt> header field.</dd>
209<dt class="definition"><strong>procedure:</strong> (mime-part:transfer-encoding PART-INFO)</dt>
210<dd></dd>
211<dt class="definition"><strong>procedure:</strong> (mime-part:transfer-encoding-set! PART-INFO TRANSFER-ENCODING)</dt>
212<dd>The value of the <tt>content-transfer-encoding</tt> header field. If the header field is omitted, an appropriate default value is set.</dd>
213<dt class="definition"><strong>procedure:</strong> (mime-part:parent PART-INFO)</dt>
214<dd></dd>
215<dt class="definition"><strong>procedure:</strong> (mime-part:parent-set! PART-INFO PARENT)</dt>
216<dd>If this is a part of multipart message or encapsulated message, points to the enclosing part's <tt>:mime-part</tt> record. Otherwise <tt>#f</tt>.</dd>
217<dt class="definition"><strong>procedure:</strong> (mime-part:index PART-INFO)</dt>
218<dd></dd>
219<dt class="definition"><strong>procedure:</strong> (mime-part:index-set! PART-INFO INDEX)</dt>
220<dd>Sequence number of this part within the same parent.</dd>
221<dt class="definition"><strong>procedure:</strong> (mime-part:headers PART-INFO)</dt>
222<dd></dd>
223<dt class="definition"><strong>procedure:</strong> (mime-part:headers-set! PART-INFO HEADERS)</dt>
224<dd>The list of header fields, as parsed by <tt>rfc822-header-&gt;list</tt>.</dd>
225<dt class="definition"><strong>procedure:</strong> (mime-part:content PART-INFO)</dt>
226<dd></dd>
227<dt class="definition"><strong>procedure:</strong> (mime-part:content-set! PART-INFO CONTENT)</dt>
228<dd>If this part is <tt>multipart/*</tt> or <tt>message/*</tt> media type, this slot contains a list of parts within it. Otherwise, the return value of handler is stored.</dd>
229<dt class="definition"><strong>procedure:</strong> (mime-part:attrs PART-INFO)</dt>
230<dd></dd>
231<dt class="definition"><strong>procedure:</strong> (mime-part:attrs-set! PART-INFO ATTRS)</dt>
232<dd>This alist provides a place for the message parser/generator or the application to store additional information. At the moment, only the <tt>'qp-encode-binary?</tt> attribute is used by the quoted-printable encoder to decide if the content should be treated as binary.</dd></dl></dd>
233<dt class="definition"><strong>procedure:</strong> (mime-retrieve-body PART-INFO XPORT OUTP)</dt>
234<dd>
235<p>A procedure to retrieve a message body. It is intended to be a building block for a handler to be passed to <tt>mime-parse-message</tt>.</p>
236<p><tt>PART-INFO</tt> is a <tt>:mime-part</tt> record. <tt>XPORT</tt> is an input port passed to the handler, from which the MIME part can be read. This procedure reads from <tt>XPORT</tt> until it returns <tt>#!eof</tt>. It also looks at the <tt>transfer-encoding</tt> of <tt>PART-INFO</tt>, and decodes the body accordingly; that is, base64 encoding and quoted-printable encoding is handled. The result is written out to an output port <tt>OUTP</tt>.</p>
237<p>This procedure does not handle charset conversion. The caller can use facilities from the <tt>charconv</tt> and/or <tt>iconv</tt> modules if conversion is desired.</p></dd></dl>
238<p>A couple of convenience procedures are defined for typical cases on top of <tt>mime-retrieve-body</tt>.</p>
239<dl>
240<dt class="definition"><strong>procedure:</strong> (mime-body-&gt;string PART-INFO XPORT)</dt>
241<dd></dd>
242<dt class="definition"><strong>procedure:</strong> (mime-body-&gt;file PART-INFO XPORT FILENAME)</dt>
243<dd>Reads in the body of mime message, decoding transfer encoding, and returns it as a string or writes it to a file, respectively.</dd></dl></div>
244<div class="subsection">
245<p><b>Message generator</b></p>
246<p>The message generator generates a RFC822/MIME message out of <tt>:mime-part</tt> objects.</p>
247<dl>
248<dt class="definition"><strong>procedure:</strong> (mime-part-write PART-INFO)</dt>
249<dd>
250<p>Formats <tt>PART-INFO</tt> as a MIME message and writes the result to the current output port.</p>
251<p><tt>PART-INFO</tt> may describe a single mail body or a <tt>multipart/*</tt> or <tt>message/*</tt> hierarchy.</p>
252<p>For multipart messages a boundary may be given in <tt>(mime-part:parameters PART-INFO)</tt> which will be used as a base for the message boundary (but modified if needed).</p>
253<p>If <tt>(mime-part:transfer-encoding PART-INFO)</tt> specifies <tt>&quot;base64&quot;</tt> or <tt>&quot;quoted-printable&quot;</tt> the body is encoded accordingly; else it is put into the message literally.</p></dd>
254<dt class="definition"><strong>procedure:</strong> (mime-part-&gt;string PART-INFO)</dt>
255<dd>
256<p>Like <tt>(mime-part-write)</tt> but returns the message as a string.</p></dd></dl></div></div>
257<div class="section">
258<h3>Examples</h3>
259<div id="examples">
260<p>The simplest form of MIME message parser would be like this:</p>
261<pre>(let ((headers (rfc822-header-&gt;list port)))
262  (mime-parse-message port headers
263                      (cut mime-body-&gt;string &lt;&gt; &lt;&gt;)))
264</pre>
265<p>This reads all the message on memory (i.e. the &quot;leaf&quot; <tt>:mime-part</tt> records' content fields would hold the part's body as a string), and returns the top <tt>:mime-part</tt> record. Content transfer encoding is recognized and handled, but character set conversion isn't done.</p>
266<p>You may want to feed the message body to a file directly, or even want to skip some body according to mime media types and/or other header information. Then you can put the logic in the handler closure. That's the reason that this module provides building blocks, instead of all-in-one procedure.</p>
267<p>A simple MIME-Message could be generated as follows:</p>
268<pre>(mime-part-write
269 (make-mime-part
270  #:type &quot;multipart&quot;
271  #:subtype &quot;mixed&quot;
272  #:headers
273  '((&quot;from&quot; &quot;test &lt;test@test.com&gt;&quot;)
274    (&quot;to&quot;   &quot;foo &lt;foo@bar.com&gt;&quot;)
275    (&quot;mime-version&quot; &quot;1.0&quot;)
276    (&quot;subject&quot; &quot;a test&quot;)
277    (&quot;message-id&quot; &quot;&lt;test123@test.com&gt;&quot;))
278  #:content
279  (list
280   (make-mime-part
281    #:transfer-encoding &quot;quoted-printable&quot;
282    #:content
283    &quot;This = a simple test.&quot;)
284   (make-mime-part
285    #:type &quot;application&quot; #:subtype &quot;octet-stream&quot;
286    #:transfer-encoding &quot;base64&quot;
287    #:content &quot;a simple test&quot;))))</pre>
288<pre>From: test &lt;test@test.com&gt;
289To: foo &lt;foo@bar.com&gt;
290Mime-Version: 1.0
291Subject: a test
292Message-Id: &lt;test123@test.com&gt;
293Content-Type: multipart/mixed;boundary=&quot;MIME-Message-Boundary-&quot;
294Content-Transfer-Encoding: 7bit
295
296This message is in MIME format.
297
298--MIME-Message-Boundary-
299Content-Type: text/plain
300Content-Transfer-Encoding: quoted-printable
301
302This =3D a simple test.
303--MIME-Message-Boundary-
304Content-Type: application/octet-stream
305Content-Transfer-Encoding: base64
306
307YSBzaW1wbGUgdGVzdA==
308
309--MIME-Message-Boundary---</pre></div></div>
310<div class="section">
311<h3>License</h3>
312<pre id="license">
313<pre>Copyright (c) 2000-2004 Shiro Kawai, All rights reserved.
314
315Redistribution and use in source and binary forms, with or without
316modification, are permitted provided that the following conditions
317are met:
318
3191. Redistributions of source code must retain the above copyright
320   notice, this list of conditions and the following disclaimer.
321
3222. Redistributions in binary form must reproduce the above copyright
323   notice, this list of conditions and the following disclaimer in the
324   documentation and/or other materials provided with the distribution.
325
3263. Neither the name of the authors nor the names of its contributors
327   may be used to endorse or promote products derived from this
328   software without specific prior written permission.
329
330THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
331&quot;AS IS&quot; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
332LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
333A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
334OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
335SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
336TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
337PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
338LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
339NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
340SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</pre></pre></div></div>
341<div id="footer">
342<hr /><a href="index.html">&lt; Egg index</a>
343<div id="revision-history">$Revision$ $Date$</div>&nbsp;</div></body></html>
Note: See TracBrowser for help on using the repository browser.