Chapter 15 ■ IMap
282
The value "MIXED" indicates exactly what kind of multipart container is being represented—in this case, the full
type is multipart/mixed. Other common “multipart” subtypes, besides "MIXED", are "ALTERNATIVE", "DIGEST",
and "PARALLEL". The remaining items beyond the multipart type are optional, but if present, they provide a set of
name-value parameters (here indicating what the MIME multipart boundary string was), the multipart’s disposition,
its language, and its location (typically given by a URL).
Given these rules, you can see how a recursive routine like display_structure() in Listing 15-7 is perfect for
unwinding and displaying the hierarchy of parts in a message. When the IMAP server returns a BODYSTRUCTURE, the
routine goes to work and prints out something like this for examination by the user:
Folder INBOX - type a message UID, or "q" to quit: 2701
Flags: \Seen
HEADER
TEXT multipart/mixed
1 multipart/alternative
1.1 text/plain size=253
1.2 text/html size=508
2 application/octet-stream size=5448 ATTACHMENT FILENAME='test.py'
Message 2701 - type a part name, or "q" to quit:
You can see that the message whose structure is shown here is a quite typical modern e-mail, with a fancy
rich-text HTML portion for users who view it in a browser or modern e-mail client, and a plain-text version of the
same message for those using more traditional devices or applications. It also contains a file attachment, complete
with a suggested file name in case the user wants to download it to the local file system. This sample program does not
attempt to save anything to the hard drive, both for simplicity and safety; instead, the user can select any portion of
the message—such as the special sections HEADER and TEXT, or one of the specific parts like 1.1—and its content will
be printed to the screen.
If you examine the program listing, you will see that all of this is supported simply by calls to the IMAP fetch()
method. Part names like HEADER and 1.1 are simply more options for what you can specify when you call fetch(),
and they can be used right alongside other values like BODY.PEEK and FLAGS. The only difference is that the latter
values work for all messages; whereas a part name like 2.1.3 would exist only for multipart messages whose structure
included a part with that designation.
One oddity that you will note is that the IMAP protocol does not actually provide you with any of the
multipart names that a particular message supports! Instead, you have to count the number of parts listed in the
BODYSTRUCTURE starting with the index 1 in order to determine which part number you should request. You can see
that the display_structure() routine here uses a simple loop to accomplish this counting.
One final note about the fetch() command: it not only lets you pull just the parts of a message that you need at
any given moment, but it also truncates them if they are quite long and you just want to provide an excerpt from the
beginning to tantalize the user! To use this feature, follow any part name with a slice in angle brackets that indicates
the range of characters that you want—it works very much like Python’s slice operation:
BODY[]<0.100>
This would return the first 100 bytes of the message body, from offset zero to offset one hundred. This can let you
inspect both text and the beginning of an attachment to learn more about its content before letting the user decide
whether to select or download it.