makemime - MIME utility


makemime [options]

makemime @file


The makemime tool creates MIME-encoded messages of arbitrary complexity. makemime reads one or more individual files, encodes them appropriately, adds basic MIME headers, and adds additional headers specified via command line options. The result is saved to another file or standard output. Complex MIME-encoded messages are created by using options that direct makemime to run additional instances of itself, as child processes. The child processes create individual parts of a complex MIME message, then the parent makemime process combines them together.

In simple cases, options for makemime are specified directly on the command line. @file specifies that options will be read from a file. "@&n" reads options from a pipe on file descriptor #n. "@-" is a shortcut for "@&0", which reads options from standard input.

When options are read from a file or a pipe, each option must be on a line by itself. If an option requires an argument, the argument must follow on the next line.

For readability, leading whitespace on each line is deleted when options are read from a file or a pipe. Empty lines are also ignored, as well as lines that begin with the '#' character.

Options and their arguments may contain characters that are special characters to the shell, such as '(' and ')'. These characters must be backslashed when specified on the command line, to avoid their special meaning to the shell. These characters MUST NOT be backslashed when options are read from a file or a pipe. Similarly, the contents of most headers nearly always include spaces. Therefore they must be quoted when specified on the command line. Header contents MUST NOT be quoted when options come from a file or a pipe.

makemime reads the contents to be encoded into a MIME message from other files. Those files can also be pipes. It is possible to supply both the options and a file from the same pipe, by terminating the list of option with a line containing the single character "-". The remainder of the pipe will be available to be used as an input file (which must be explicitly specified via some other option). Of course, only one input file can come from a single pipe.

MIME overview

A MIME message consists of one or several MIME sections. MIME headers specify how multiple MIME sections are to be interpreted as a whole (whether they are attached together, or whether they are alternative representations of the same object, or something even more esoteric). This manual page gives a very brief, terse, overview of basic MIME concepts. The description is biased towards describing the functionality of the makemime utility. The complete description of MIME encoding is found in RFCs 2045 through 2048, where a formal definition is found.

Each file in a MIME message is encoded as a single MIME section. A MIME section consists of at least one header line, "Content-Type". The "Content-Type" headers gives the type of the data contained in the file. Other header lines may also be present. Their relative order does not matter. MIME headers are followed by a blank line, then the contents of the file, encoded appropriately. All MIME sections generated by makemime will always contain another header, "Content-Transfer-Encoding". This header gives the encoding method used for the file.

The encoding method defaults to "7bit" if this header is absent. 7bit encoding is only suitable for plain text messages in the US-ASCII character set. The "8bit" encoding method is used by plain text messages in other character sets which contain high-bit characters, with their 8th bit set. An alternative to 8bit encoding is "quoted-printable". The "base64" encoding method is used for files containing binary data.

MIME sections that contain text messages have their "Content-Type" header set to "text/plain"; or "text/html" for HTML messages. There are also several other, rare, content types that can be used. MIME sections that contain other kinds of data will use some other, appropriate Content-Type header, such as "image/gif", or "audio/x-wav".

MIME sections that contain textual content may use the base64 encoding method, they are not required to use 7bit, 8bit, or quoted-printable. "text/pdf" sections, that contain PDF files, typically consist of binary data, and must use base64 encoding. Consequently, MIME sections that typically contain binary data, such as image/gif and audio/x-wav, are free to use other encoding methods besides base64, as long as all the data can be represented by printable characters (but, in practice, that never happens).

MIME sections may also contain other, optional, headers such as "Content-Disposition", "Content-ID", and "Content-Name". Consult the appropriate RFCs for the specific usage of these headers. These headers can be added by makemime by using the -a option, as described below. These headers play no part in creating the overall structure of a MIME-encoded message, and makemime does not care much about these headers. It simply includes them, and their content, upon request.

Multiple files are encoded into a single message by initially creating a MIME section for each file, and then creating a single MIME section that contains other MIME sections. A "multipart/mixed" MIME section contains a collection of MIME sections that represent different objects, attached together. A "multipart/alternative" MIME section contains a collection of MIME sections which are alternative representations of the same object, such as an HTML and a plain text version of the same message. Other "multipart" MIME sections also exist, and their usage is defined by their respective RFCs.

Creating a single MIME section

    makemime -c "type" [-e "encoding"] [-o file] \
            [-a "header: value"] [-a "header: value"] file

The -c option reads file, encodes it appropriately, adds a "Content-Type" and "Content-Transfer-Encoding" MIME headers, then writes the result to standard output. type can be any valid MIME type, except for multipart. file can be "-", which specifies standard input. file can be "&n" to read the file from file descriptor #n.

The optional encoding argument should be specified. It's more efficient to do so. encoding must be one of the following: 7bit, 8bit, quoted-printable, or base64.

If encoding is not specified, makemime reads the file twice - once to select the best encoding method, and the second time to encode it. If file is a pipe makemime will be forced to create a temporary file, which is less efficient if the file is large. However letting makemime pick the encoding is probably more convenient if files are relatively small.

By default the encoded MIME section is written to standard output. The -o option writes the MIME section to a file. file can be "&n", which writes the MIME section to a pipe on file descriptor #n.

makemime does not generate any other headers. Particularly, the "Mime-Version" header (and others) is required to send a MIME message via E-mail. Additional headers are specified by the -a option, which may be used multiple times to insert multiple headers. makemime doesn't do anything with them except to insert the headers into the generated MIME section.

Note that "Mime-Version" is only required for the top level MIME section. This header is not required for individual MIME sections that are later combined into a multipart MIME collection.

Note that the -c option is required to be listed first, the remaining options must follow the -c option.

Creating a multipart MIME collection

    makemime -m "type" [-e "encoding"] [-o file] \
            [-a "header: value"] [-a "header: value"] file

The -m option is identical in usage to the -c option, except for three differences.

type must be either "multipart/mixed", "multipart/alternative", or some other MIME multipart content type. Additionally, "encoding" can only be "7bit" or "8bit", and will default to "8bit" if not specified. Finally, file must be a MIME-encoded section, NOT a regular file. Usually file is also created by makemime (it can also be a pipe, like the -c option), but it can be created via any other means.

The -m option creates an initial multipart MIME collection, that contains only one MIME section, taken from file. The collection is written to standard output, or the pipe or the file specified by the -o option. The -j option is used to add additional MIME sections to this collection.

Creating a multipart MIME section

    makemime -j file1 [-o file] file2

This option appends a MIME section to an existing MIME collection. file1 contains a MIME collection that's been created by the -m option. file2 must contain a MIME section that's been created by the -c option. The MIME section in file2 is appended after the last MIME section in file1. The result is written to standard output or the file specified by the -o option.

file1 and/or file2 can be "&n", which reads the corresponding file from a pipe on the indicated file descriptor. The -o option, as always, can also specify a file descriptor.

file1 and file2 should ideally be created by makemime as well. It's also possible to use files created by other software, but with some degree of care. makemime is not intended to be a MIME parser, but a MIME generator. However some amount of MIME parsing is necessary to append a MIME section to an existing MIME collection. makemime's parsing does a sufficient job to append a new section to a MIME collection, as long as the MIME headers in the MIME collections are straightforward. Very convoluted MIME headers may confuse makemime, and it may not be able to handle them.

Recursive MIME collections

MIME collection may contain other MIME collections as well as MIME sections. The -m and the -j option may use a multipart MIME collection in place of a MIME section automatically, simply because a multipart MIME collection is just a special type of a MIME section. The following example encodes a text message that can be alternatively represented as HTML or plain text, with some additional attachments:

1. Create a MIME collection containing a text/plain and a text/html MIME section.

2. Create a MIME collection consisting of the MIME section generated in step one, plus additional MIME sections containing other attachments.

For example:

    # Take two files containing the text and the html version of a message, and
    # add MIME headers to them.

    makemime -c "text/plain; charset=iso-8859-1" -o tmp1.txt msg.txt
    makemime -c "text/html; charset=iso-8859-1" -o tmp1.html msg.html

    # Combine the result into a multipart/alternative collection

    makemime -m "multipart/alternative" -a "Content-Disposition: inline" \
                                        -o tmp.ma1 tmp1.txt
    makemime -j tmp.ma1 -o tmp.ma2 tmp1.html

    # Add MIME headers to an image attachment.

    makemime -c "image/gif" -a "Content-Disposition: attachment" \
                            -o tmp2.gif attachment.gif

    # Create the final multipart/mixed collection

    makemime -m "multipart/mixed" -a "Mime-Version: 1.0" \
                                  -o tmp.mm1 tmp.ma2
    makemime -j tmp.mm1 -o output.msg tmp2.gif

output.msg now contains the complete MIME collection. Just add the subject, from, and to headers (can also be done by additional -a options, of course), and send it on its way.

Building complex MIME encodings

There are several different ways to build complete MIME encodings from multiple MIME sections. One way is to use temporary files to create MIME sections, then combine them together into a single MIME collection. A slightly more complicated approach involves setting up pipes between multiple makemime processes, in order to avoid using temporary files.

This can be done manually, by hand. It is also possible to have makemime do this automatically. makemime will set up these pipes and run multiple instances of itself to create a single MIME collection, with multiple attachments of arbitrary complexity.

Any file that's read by the -c, -m, and -j options (-o specifies a file to create, and doesn't count) may be replaced by a single argument containing a left parenthesis, additional options, then a single argument containing a right parenthesis. A single invocation of makemime can only use one -c, -m, or -j option. However, another -c, -m, or -j option may be specified inside the left and the right parenthesis, and its output is used in place of the file it replaced. In the previous example the third and the fourth invocation of makemime can be replaced with the following command:

    makemime -j \(                           \
                   -m "multipart/alternative" \
                   -a "Content-Disposition: inline" tmp1.txt \
                 \) -o tmp.ma2                    \

Note that the parenthesis must be backslashed, to avoid their special meaning to the shell. An equivalent argument file would have the following contents:

              Content-Disposition: inline

These constructs can be arbitrarily nested, and are limited by the amount of available memory and resources. The entire sequence in the previous section is equivalent to the following command:

    makemime -j                                                 \
             \(                                                 \
                -m "multipart/mixed"                            \
                -a "Mime-Version: 1.0"                          \
                \(                                              \
                    -j                                          \
                    \(                                          \
                       -m "multipart/alternative"               \
                       -a "Content-Disposition: inline"         \
                       \(                                       \
                          -c "text/plain; charset=iso-8859-1"   \
                          msg.txt                               \
                       \)                                       \
                    \)                                          \
                    \(                                          \
                        -c "text/html; charset=iso-8859-1"      \
                        msg.html                                \
                    \)                                          \
                \)                                              \
             \)                                                 \
             -o output.msg                                      \
             \(                                                 \
                -c "image/gif"                                  \
                -a "Content-Disposition: attachment"            \
                attachment.gif                                  \

An equivalent argument file would be:

           Mime-Version: 1.0
                   Content-Disposition: inline
                       text/plain; charset=iso-8859-1
                   text/html; charset=iso-8859-1
           Content-Disposition: attachment


maildrop(1), maildropfilter(1), reformail(1), reformime(1), egrep(1), grep(1), courier(8), sendmail(8), RFC 2045, RFC 2046, RFC 2047, RFC 2048.