Prelimanary documenation. Class: mime-part-parsed Subclass of: mime-part Slot accessors: * mime-part-type * mime-part-subtype * mime-part-parameters * mime-part-id * mime-part-description * mime-part-encoding * mime-part-headers * mime-part-parts * mime-part-boundary * mime-part-headers-size This is the size, in bytes, of the header portion of the part (including the blank line terminator) * mime-part-body-size This is the size, in bytes, of the body of the part. * mime-part-lines For non-multipart types, this is the number of lines that make up the part body. * mime-part-position This is the file positon of the start of the part headers, relative to the beginning of the topmost part. * mime-part-body-position This is the file position of the start of the part body, relative to the beginning of the topmost part. * mime-part-message For message/rfc822 parts, this slot contains the mime-part-parsed object which represents the encapsulated message. Function: parse-mime-structure Arguments: stream &key mbox Return values: The function returns two values: 1) A mime-part-parsed object which represents the topmost MIME part (which may possibly contain subparts). If there was no message to parse (such as if the stream is at EOF), then nil is returned. 2) The number of bytes that were read. 'stream' should be a stream that is positioned at the first header of a MIME-compliant email message. If 'mbox' is true, then parsing will terminate at EOF or when a line which begins with "From " is read. MIME messages always have a topmost part and may possibly have multiple subparts which may recursively have their own subparts. This function reads 'stream' and creates a mime-part-parsed object which contains information about these parts and subparts. For each part, the following information is collected: * The major content type, (e.g, "text", if the Content-Type header is "text/html"). * The content subtype, (e.g., "html", if the Content-Type header is "text/html"). * Any parameter information that was supplied in the Content-Type header. * The part id, as determined by the Content-Id header, if there was one. * The part description, as determined by the Content-Description header, if there was one. * The part encoding, as determined by the Content-Transfer-Encoding header. * The boundary string, for multipart types. * The list of subparts (which are also mime-part-parsed objects) for multipart parts. * The encapsulated message (which is a mime-part-parsed object) for message/rfc822 parts. * The size of the part headers (in bytes). * The size of the part body (in bytes). * The number of lines comprising the part body. * The file position of the beginning of the part headers, relative to the position of the topmost part. For the topmost part, this value will always be zero. * The file position of the beginning of the part body, relative to the position of the topmost part. See also: . Function: map-over-parts Arguments: part function 'part' must be a mime-part. 'function' must be a function (or symbol naming a function) which takes a single argument, a mime-part. map-over-parts calls 'function' on 'part', then, if part contains subparts (or an encapsulated message in the case of a message/rfc822 part), map-over-parts is called recursively for each subpart (or encapsulated message). Function: qp-encode-stream Arguments: instream outstream &key wrap-at This function reads bytes from instream and writes them in quoted-printable format to outstream. Lines in the output are wrapped approximately every 'wrap-at' output characters (which defaults to 72). Wrapping may be late by up to 3 characters under some circumstances (e.g., when using the default 'wrap-at' value of 72, some lines may be 75 characters long). 'instream' is read until EOF is seen. 'instream' must be a stream capable of being read in an octet-oriented manner. In particular, it cannot be a string stream. See also: qp-decode-stream, base64-encode-stream, base64-decode-stream Function: qp-decode-stream Arguments: instream outstream This function reads quoted-printable encoded text from 'instream' and writes the decoded text to 'outstream'. Reading continues until end-of-file is seen on 'instream'. See also: qp-encode-stream, base64-encode-stream, base64-decoed-stream Macro: with-part-stream Arguments: (sym part instream &key (header t)) &body body with-part-stream evaluates 'body' with 'sym' bound to an input stream which, when read, supplies bytes from 'instream'. 'instream' must be positioned either at the beginning of the part headers (if keyword argument 'header' is true) or at the beginning of the part body (if keyword argument 'header' is false). The 'part' argument is used by the macro to determine how many bytes from 'instream' will be used. The primary purpose of this macro is to create a stream that will generate an end-of-file indicator when the contents of a part have been completely read. Such a stream is useful for passing to functions which expect to read a stream until EOF (such as 'decode-quoted-printable' or 'excl:base64-decode-stream'). See also: with-decoded-part-body-stream Macro: with-decoded-part-body-stream Arguments: (sym part instream) &body body with-decoded-part-body-stream evaluates 'body' with 'sym' bound to an input stream which, when read, supplies decoded bytes. The encoded bytes are read from 'instream', which should be an input stream whose file position is at the beginning of the part body. The 'part' argument is used by the macro to determine the size of the part body and also to determine the content transfer encoding of the part. The input stream bound to 'sym' will signal end-of-file when the part body has been exhausted. Example: (use-package :net.post-office) (defun extract-all-jpegs (filename) (with-open-file (f filename) (let ((toppart (parse-mime-structure f)) (count 0)) (flet ((extract-jpeg (part) (if* (and (equalp (mime-part-type part) "image") (equalp (mime-part-subtype part) "jpeg")) then (incf count) (let ((filename (format nil "image~d.jpg" count))) (format t "Saving ~a...~%" filename) (with-open-file (out filename :direction :output) ;; Position source file pointer to the beginning ;; of the part body. (file-position f (mime-part-body-position part)) (with-decoded-part-body-stream (bod part f) (sys:copy-file bod out))))))) (map-over-parts toppart #'extract-jpeg))))) See also: mime-part-body-position slot accessor.