Get email information from IMAP (fast)

Email messages include attachments (encoded as text using Base64 or Quoted-Printable encoding). This causes emails to became quite big and download process slow. In many cases you don’t require to download entire message (including attachments) to process it. Think about displaying only a list of messages that are in the INBOX folder or only deciding if you should process a message.

When using IMAP protocol, Mail.dll IMAP client offers extremely fast way of downloading such email information. This include message envelope information (Subject, Date, From and To recipients) and message structure (Attachment count, attachment names and sizes).

In the following sample, we’ll download those data for all unseen messages that are in the INBOX folder:

//  C#

using (Imap imap = new Imap())
{
    imap.Connect("imap.example.com");   // or ConnectSSL
    imap.UseBestLogin("user", "password");

    imap.SelectInbox();
    List<long> uids = imap.Search(Flag.Unseen);
    List<MessageInfo> infos = imap.GetMessageInfoByUID(uids);

    foreach (MessageInfo info in infos)
    {
        Console.WriteLine("Subject: " + info.Envelope.Subject);
        Console.WriteLine("From: " + info.Envelope.From);
        Console.WriteLine("To: " + info.Envelope.To);
        foreach (MimeStructure attachment in info.BodyStructure.Attachments)
        {
            Console.WriteLine("  Attachment: '{0}' ({1} bytes)",
                attachment.SafeFileName,
                attachment.Size);
        }
        Console.WriteLine();
    }
    imap.Close();
}
' VB.NET

Using imap As New Imap()
	imap.Connect("imap.example.com")    ' or ConnectSSL
	imap.UseBestLogin("user", "password")

	imap.SelectInbox()
	Dim uids As List(Of Long) = imap.Search(Flag.Unseen)
	Dim infos As List(Of MessageInfo) = imap.GetMessageInfoByUID(uids)

	For Each info As MessageInfo In infos
		Console.WriteLine("Subject: " + info.Envelope.Subject)
		Console.WriteLine("From: " + info.Envelope.From)
		Console.WriteLine("To: " + info.Envelope.[To])
		For Each attachment As MimeStructure In info.BodyStructure.Attachments
			Console.WriteLine("  Attachment: '{0}' ({1} bytes)", _
				attachment.SafeFileName,  _
				attachment.Size)
		Next
		Console.WriteLine()
	Next
	imap.Close()
End Using

The result of the code above is list of all unread emails with attachments:


Subject: Contract
From: Alice <alice@company.com>
To: Bob <bob@company.com>
Attachment: 'document1.doc' (42738 bytes)
Attachment: '.NET.pdf' (1243 bytes)

Envelope object contains following information:

  • Subject
  • Date
  • From
  • Sender
  • To
  • Cc
  • InReplyTo
  • Message id
  • Message size
  • Gmail thread id (if available)
  • Gmail message id (if available)

BodyStructure contains information about:

  • All attachments including their size, name, content type
  • HTML message part
  • Pain text message part

It’s really fast. Downloading 1000 email information takes approximately 13 seconds.

You can read more about downloading email parts (single attachment) here

You can download Mail.dll .NET IMAP library here.

Tags: , , ,

17 Responses to “Get email information from IMAP (fast)”

  1. Khash Says:

    Hi,

    Is this any different from the one you did for us? Shall we upgrade to this version for faster download?

  2. Limilabs support Says:

    @Khash
    This feature was introduced in version 3.0.10257.1855.
    So if you are using previous version and want to use GetMessageInfo or GetMessageInfoByUID methods you should upgrade.

  3. GMail's POP3 behavior Says:

    […] download emails’ basic information very fast […]

  4. Download parts of email message Says:

    […] There are two methods for that: GetBodyStructureByUID and GetBodyStructure. You can also use GetMessageInfo and GetMessageInfoByUID methods. Both methods return more information about the email (subject, from, to headers) and […]

  5. Roberto Says:

    Hi,
    I tested this code but the Size property returns the mimestructure I have nothing to do with what actually holds the file (eg XLS file size of 59,392 bytes, the property returns me 81274 bytes)
    Something wrong?

  6. Limilabs support Says:

    @Roberto

    Can you enable logging, as described here:
    http://www.limilabs.com/blog/i-have-problems-issuing-imap-pop3-smtp-command

    and we’ll see what the server is sending.

  7. Limilabs support Says:

    @Roberto

    The attachment is Base64 encoded, which typically increase the size of
    the attachment by 33%.

    Server returns so called ‘transfer size’ (71566 bytes)
    Note that this size is the size in attachment’s transfer encoding (Base64) and
    not the resulting size after any decoding (‘actual size’).

    The problem is that without decoding (which means downloading the
    entire attachment) there is no way to know the actual attachment size.

    We’ll add better comment on the MimeStructure.Size property.

    We’ll also add EstimateActualSize method to MimeStructure that is going to estimate
    the ‘actual size’ from the ‘transfer size’ and encoding used.

  8. b0ris Says:

    Hello,

    I’d like to use this fast method in my application, but can’t think about a way to retrieve the Priority/Importance this way. I’m sure there is a way, so can you please help me out if you have a little time?
    Thanks in advance!

  9. Limilabs support Says:

    @Boris,

    Unfortunately not all headers are included in envelope response.
    You can use Imap.GetSpecificHeadersByUID(List uids, string[] headers) to get those you are missing, but expect significant performance drop as this command expects multi-line response.

    Please note that this method is available in the newest version of Mail.dll

  10. Jacek Says:

    I noticed that when i use GetSpecificHeadersByUID to recieve headers for specified messages, these messages are being flagged as seen. Please let me know if you plan to fix this. Thanks.

  11. Limilabs support Says:

    @Jacek

    It’s not a bug.

    The latest version has PeekSpecificHeaders and PeekSpecificHeadersByUID methods that don’t set Seen flag. Generally Peek* methods in contrast to Get* methods don’t set Seen flag.

  12. Download emails from Gmail via POP3 Says:

    […] download emails’ basic information very fast […]

  13. Save all attachments to disk using IMAP | Blog | Limilabs Says:

    […] working with attachments. You can download only parts of email message, which in conjunction with getting basic email information without downloading entire message can make your code very […]

  14. Math Says:

    You say this is the fastest way but when I use: imap.GetHeadersByUID(uids)
    I can read 1000 mails in 7-8 seconds, how GetMessageInfo then be the fastest?

  15. Limilabs support Says:

    @Math,

    GetHeadersByUID downloads only message headers, there are no information about attachments, message size.

    You are trying to compare apples to oranges here.

    If you don’t care about attachments’ info, GetEnvelopeByUID should be faster then GetHeadersByUID and GetMessageInfoByUID.

  16. Richard Taylor Says:

    Hi, I have followed the example but when trying to output the email from by using info.Envelope.From but instead of getting the actual information I am getting

    System.Collections.Generic.List`1[Limilabs.Mail.Headers.MailBox]

    Help?!?

  17. Limilabs support Says:

    @Richard,

    Have you used foreach? Envelope.From is a collection.
    Each item in this collection is of MailBox type, which has Address and Name properties.

Questions?

Consider using our Q&A forum for asking any questions.