MH & nmh: Email for Users & Programmers

May, 2006

Listing MIME Message Parts

mhn -list (for MH) and mhlist (for nmh-1.0 and above) summarize the contents of MIME messages. The output has five columns: message number, message part number, content-type and subtype, size in octets (which are basically bytes or us-ascii characters), and content-description (if any). If you don't give message numbers, the current message is listed. For example, here's how to list the current and next messages (message numbers 33 and 34):

    % mhn -list cur next
     msg part  type/subtype              size description
      33       multipart/mixed            44K
         1     text/plain                1459 Description of picture
         2     image/x-pbm                40K Picture of front panel
      34       multipart/alternative     2914
         1     multipart/mixed           1688
         1.1   text/enriched              481
         1.2   message/external-body       69 "Louie Louie"
         1.3   message/external-body       67 Cruisers at Park concert
         2     text/plain                 817
Message 33 has multipart/mixed content. The total size is approximately 44,000 octets. The first part is text/plain, 1459 octets, with a Content-description: of "Description of picture." Part 2 is an image in the nonstandard content subtype x-pbm. (Although x-pbm means that the pbm format isn't an official MIME type registered with the IANA, it's widely used.) The total size of 44k is the sum of the parts, after decoding, plus the other header fields.

Message 34 has the content-type multipart/alternative. This means that either part 1 or part 2 will be shown. Note that mhn and mhlist don't necessarily list the parts of a multipart/alternative message in the same order they appear in the message. The alternatives are listed in descending priority. The MIME specification says that the "simplest" (closest to plain text) part should be first in the body; this lets people without MIME-capable MUAs make some sense of the message.

Message 34 has three subparts: text/enriched, message/external-body (which, if you retrieve it, will have audio/basic content), and another message/external-body part (this one with image/gif content). Notice that the body parts' sizes are small (69 and 67 characters). That's because they're external parts that haven't been retrieved yet.

To list only one part of a message, if you know the part number, you can call mhlist -part or mhn -list -part followed by the part number. Or, if you know the content type of the part(s) you want to see, use mhlist -type or mhn -type.

mhn -list and mhlist will show you any comments and parameters from the Content-Type: field if you use the -verbose switch. Compare this listing of message 33 to the one above:

    % mhn -list -verbose
     msg part  type/subtype              size description
      33       multipart/mixed            44K
         1     text/plain                1459 Description of picture
                 (sorry; I wrote this in a hurry)                           
         2     image/x-pbm                40K Picture of front panel
                 x-density="75 dpi"
By default, each body part is decoded before its size is checked. That isn't necessarily the size a body part has in the message. For example, in a message with base64 encoding, each four encoded characters (like LnNu) are decoded to three octets (8-bit bytes). If you add the -norealsize switch, mhn -list and mhlist will give you the encoded size of body parts. For long messages, -norealsize can save time, too, because the parts don't have to be decoded before their sizes are computed.

Sometimes I wish that mhn -list and mhlist would show the message Subject:, too. The little shell function called mscan, below, runs scan to show the subject, followed by mhn -list to show the contents. (nmh users: you can use mhlist instead.) It defaults to the current message, but you also can give it folder or message arguments.

    mscan() { scan ${*-cur} && mhn -list $* ; }
The Bourne-type shell parameter substitution operator, ${*-cur}, passes scan the message name cur if you run mscan with no arguments. (Otherwise, scan would scan all messages: not what we want here!) By default, mhn -list displays the current message; and, luckily, the shell ignores $* if there were no arguments. This is hard to write concisely in a C shell alias; if you use csh, you can make it into a one-line shell script. Here's an mscan of the current message:
    $ mscan
      53+ 05/18 To:Maree Winkler   Messages from Jon about next week's meeting
     msg part  type/subtype              size description
      53       multipart/mixed            12K
         1     text/plain                 434
         2     multipart/digest          8095 forwarded messages
         2.1   message/rfc822            4293
         2.2   message/rfc822            2491