Showing Opened Message
Usually clients show some interesting message headers, message's plaintext body and attachment icons if there are any.
The most important thing is to avoid fetching the entire message body. If the message has 1MB attachment, there's no need to download it until user has expressed interest in opening or saving it. You can do this by parsing BODY or BODYSTRUCTURE reply and fetching only the MIME parts you're going to show.
If you already fetched BODY or BODYSTRUCTURE when showing message list, you can fetch everything with one command:
1 FETCH (RFC822.HEADER BODY.PEEK)
RFC822.HEADER can be used to fetch the whole header, which by this time should be pretty cheap since you're fetching the message body as well. However if you're interested of only a few specific headers (and you should already know some of them from message list!), you can fetch them instead:
1 FETCH (BODY.PEEK[HEADER.FIELDS (List-Id)] BODY.PEEK)
If you don't know the BODY or BODYSTRUCTURE before opening the message, you'll need two commands:
1 FETCH (RFC822.HEADER BODYSTRUCTURE) * FETCH (...) 1 OK 2 FETCH (BODY.PEEK)
If you're fetching a large attachment, it's no excuse to have your user interface unresponsive until the download is complete. You have two choices for this:
- Create a new connection (or use another existing one), open the mailbox with EXAMINE (because some servers allow mailbox to be SELECTed only once) and download the attachment using it.
Fetch the attachment in pieces: FETCH 1 BODY.PEEK<0.102400>, wait for OK, FETCH 1 BODY.PEEK<102401.204800>, etc. The block size should be large enough so that network latency doesn't add too much wasted time, but small enough that any other more important commands can be executed without too much delay.
In both of these cases it's useful to know the approximate latency and available bandwidth between the client and the server. If you know that simply sending a single FETCH command to download the entire message takes less time than using a separate connection, then there's no point in doing that. The block size can be also be dynamically adjusted so that each FETCH request takes for example a second.
You can calculate the latency easily by keeping track of how long it typically takes for server to answer commands that shouldn't be resource intensive (e.g. CAPABILITY, LOGIN, LIST). If you don't know the bandwidth, pick a small enough block size initially and keep growing it.
With high latency links (e.g. 0,3sec+) creating a second connection is probably a better idea than fetching in small blocks, because a lot of time can be wasted on waiting for the OK replies. With low latency links it's probably better to use partial fetches.