| 1 | SquirrelMail MIME Support Introduction |
| 2 | ====================================== |
| 3 | |
| 4 | The intended audience for this document are people who want to understand how |
| 5 | the MIME code works. This is a technical documentation of how mime.php |
| 6 | works and how it parses a MIME encoded message. |
| 7 | |
| 8 | |
| 9 | Object Structure |
| 10 | ---------------- |
| 11 | There are two objects that are used: "message" and "msg_header". Here is a |
| 12 | brief overview of what each object contains. |
| 13 | |
| 14 | msg_header |
| 15 | Contains variables for all the necessary parts of the header of a |
| 16 | message. This includes (but is not limited to) the following: to, from, |
| 17 | subject, type (type0), subtype (type1), filename ... |
| 18 | |
| 19 | message |
| 20 | This contains the structure for the message. It contains two parts: |
| 21 | $header and $entities[]. $header is of type msg_header, and $entities[] |
| 22 | is an array of type $message. The $entities[] array is optional. If |
| 23 | it does not exist, then we are at a leaf node, and have an actual |
| 24 | attachment (entity) that can be displayed. Here is a tree view of how |
| 25 | this object functions. |
| 26 | |
| 27 | header |
| 28 | entities |
| 29 | | |
| 30 | +--- header |
| 31 | | |
| 32 | +--- header |
| 33 | | entities |
| 34 | | | |
| 35 | | +--- header |
| 36 | | | |
| 37 | | +--- header |
| 38 | | |
| 39 | +--- header |
| 40 | |
| 41 | |
| 42 | Getting the Structure |
| 43 | --------------------- |
| 44 | Previously (version 0.4 and below), SquirrelMail handled all the parsing of |
| 45 | the email message. It would read the entire message in, search for |
| 46 | boundaries, and create an array similar to the $message object described |
| 47 | above. This was very inefficient. |
| 48 | |
| 49 | Currently, all the parsing of the body of the message takes place on the |
| 50 | IMAP server itself. According to RFC 2060 section 7.4.2, we can use the |
| 51 | BODYSTRUCTURE function which will return the structure of the body (imagine |
| 52 | that). It goes into detail of how the bodystructure should be formatted, |
| 53 | and we have based our new MIME support on this specification. |
| 54 | |
| 55 | A simple text/plain message would have a BODYSTRUCTURE similar to the |
| 56 | following: |
| 57 | |
| 58 | ("TEXT" "PLAIN" ("CHARSET" "US-ASCII") NIL NIL "7BIT" 1152 23) |
| 59 | |
| 60 | A more complicated multipart message with an attachment would look like: |
| 61 | |
| 62 | (("TEXT" "PLAIN" ("CHARSET" "US-ASCII") NIL NIL "7BIT" 1152 23)("TEXT" |
| 63 | "PLAIN" ("CHARSET" "US-ASCII" "NAME" "cc.diff") |
| 64 | "<960723163407.20117h@cac.washington.edu>" "Compiler diff" "BASE64" |
| 65 | 4554 73) "MIXED")) |
| 66 | |
| 67 | Our MIME functionality implements different functions that recursively |
| 68 | run through this text and parses out the structure of the message. If you |
| 69 | want to learn more about how the structure of a message is returned with |
| 70 | the BODYSTRUCTURE function, please see RFC 2060 section 7.4.2. |
| 71 | |
| 72 | NOTE: SquirrelMail passes the MIME Torture Test written by Mark |
| 73 | Crispin (author of the IMAP protocol). This message is crazy! It |
| 74 | has about 30 parts nested inside each other. A very good test, |
| 75 | and SquirrelMail passed it. It can be found here: |
| 76 | |
| 77 | ftp://ftp.lysator.liu.se/mirror/unix/imapd/mime/torture-test.mbox |
| 78 | |
| 79 | Getting the Body |
| 80 | ---------------- |
| 81 | Once all the structure of the message has been read into the $message |
| 82 | object, we then need to display the body of one entity. There are a number |
| 83 | of ways we decide which entity to display at a certain time, and I won't go |
| 84 | into that here. |
| 85 | |
| 86 | Each entity has its own ID. Entity IDs look something like "1.2.1", or |
| 87 | "4.1", or just "2". You can find a detailed description of how entities |
| 88 | should be identified by reading RFC 2060 section 6.4.5. To fetch the body |
| 89 | of a particular entity, we use the function "BODY[<section>]". For |
| 90 | instance, if we were wanting to return entity 1.2.1, we would send the |
| 91 | IMAP server the command: "a001 FETCH <msg_id> BODY[1.2.1]". |
| 92 | |
| 93 | This returns a string of the entire body. Based upon what is in the header, |
| 94 | we may need to decode it or do other things to it. |
| 95 | |
| 96 | |
| 97 | Closing Notes |
| 98 | ------------- |
| 99 | That is basically how it works. There is a variable in mime.php called |
| 100 | $debug_mime that is defined at the top of that file. If you set it to true, |
| 101 | it will output all kinds of valuable information while it tries to decode |
| 102 | the MIME message. |
| 103 | |
| 104 | The code in mime.php is pretty well documented, so you might want to poke |
| 105 | around there as well to find out more details of how this works. |
| 106 | |
| 107 | If you have questions about this, please direct them to our mailing list: |
| 108 | squirrelmail-users@sourceforge.net |