3

I have a requirement to read a mailbox having more than 3000 mails. I need to read these mails, fetch their mail contents and feed the body into another api. Its easy to do with a few mails (for me it was approx 250), but after that it slowed down significantly. Is the accepted answer in this link the only choice, or is there any other alternative way.

NOTE: I have purposely not pasted any snippet,as I have used the straight forward approach, and yes I did use FetchProfile too.

Shepherd
  • 320
  • 2
  • 16

1 Answers1

8

JavaMail IMAP performance is usually controlled by the speed of the server, the number of network round trips required, and the ammount of data being read. Using a FetchProfile is essential to reducing the number of round trips. Don't forget to consider the IMAP-specific FetchProfile items.

JavaMail will fetch message contents a buffer at a time. Large messages will obviously require many buffer fetches, and thus many round trips. You can change the size of the buffer (default 16K) by setting the mail.imap.fetchsize property. Or you can disable these partial fetches and require it to fetch the entire contents in one operation by setting the mail.imap.partialfetch property to false. Obviously the latter will require significant memory on the client if large messages are being read.

The JavaMail IMAP provider does not (usually; see below) cache message contents on the client, but it does cache message headers. When processing a very large number of messages it is sometimes helpful to invalidate the cache of headers when done processing a message by calling the IMAPMessage.invalidateHeaders method. When using IMAPFolder.FetchProfileItem.MESSAGE, the message contents are cache, and will also be invalidated by the above call.

Beyond that, you should examine the JavaMail debug output to ensure only the expected IMAP commands are being issued and that you're not doing something in your program that would cause it to issue unnecessary IMAP commands. You can also look at time-stamps for the protocol commands to determine whether the time is being spent on the server or the client.

Only after all of that has failed to yield acceptable performance, and you're sure the performance problems are not on the server (which you can't fix), would you need to look into custom IMAP commands as suggested in the link you referred to.

Bill Shannon
  • 29,579
  • 6
  • 38
  • 40
  • I have made three changes to the code: 1. mail.imap.partialfetch = false 2. Added IMAPFolder.FetchProfileItem.MESSAGE to the FetchProfile object 3. Used invalidateHeaders() method after every mail is parsed. This has improved the performance significantly, but one thing I would love to know how this partial fetch exactly works, I did not get a very good explanation of its flow of control from one buffer to the next. – Shepherd Nov 10 '17 at 19:35
  • When you ask for more data (e.g., reading from the stream returned by getInputStream) and the buffer is empty, it requests more data. – Bill Shannon Nov 11 '17 at 02:15