MailBee.NET Objects 7.2

Imap.DownloadEnvelopesEx Method 

Fetches message envelopes, bodies, headers, flags, attributes, etc from the server allowing you to request different items for every message in the list.

public EnvelopeCollection DownloadEnvelopesEx(
   long[] messageIndices,
   bool indicesAreUids,
   EnvelopeParts[] parts,
   int[] bodyPreviewSizes,
   string[][] extraHeaders,
   string[][] extraItems
);

Parameters

messageIndices
The array of UIDs or message numbers of the messages to be fetched.
indicesAreUids
If true, messageIndices holds UIDs; otherwise, ordinal message numbers.
parts
For every message to be fetched, denotes its EnvelopeParts to be requested. If a null reference (Nothing in Visual Basic), MailBee will use Uid for all messages.
bodyPreviewSizes
For every message to be fetched, denotes how many bytes of the raw body part to download in addition to the raw header part. If a null reference, MailBee will use 0 for all messages.
extraHeaders
For every message to be fetched, denotes its extra MIME headers to be requested. If a null reference MailBee will not request any additional headers for any messages.
extraItems
For every message to be fetched, denotes its extra items to be requested. If a null reference MailBee will not request any additional items for any messages.

Return Value

EnvelopeCollection object if message envelopes were downloaded successfully; otherwise, a null reference (Nothing in Visual Basic).

Remarks

Use this method if you want to download different elements for different messages and would like to have the entire operation complete as a single command (pipelined batch). Typical cases for that are downloading text bodies or certain types of attachments from multiple messages. For other cases (when you need the same items for all messages, like envelope, header, full message, etc), use DownloadEnvelopes method or its overloads.

The main advantage of DownloadEnvelopesEx method is speed. You can do the same calling DownloadEnvelopes multiple times (one call per message) each time requesting different message items. DownloadEnvelopesEx just makes it possible to send all the requests at once and thus save time on multiple round-trips FETCH requests to the server and FETCH responses back from it. If performance is not a concern, use DownloadEnvelopes. See GetEnvelopeItem for example.

Usually, DownloadEnvelopesEx method is used after DownloadEnvelopes which requested body structures of the messages. Then you code analyzes these body structures, composes FETCH requests and the expected items in FETCH responses, and supplies the collected information to DownloadEnvelopesEx method.

Exceptions

Exception TypeCondition
MailBeeInvalidArgumentExceptionmessageIndices is a null reference (Nothing in Visual Basic) or empty; bodyPreviewSizes, extraHeaders and extraItems have length different from messageIndices length.
MailBeeExceptionAn error occurred and ThrowExceptions is true.

Example

Two samples in this topic (you may also find the sample in BeginDownloadEnvelopesEx topic). The first sample downloads all images from all e-mails in inbox (not downloading anything else) and saves them to disk.

[C#]
using System;
using System.Collections;
using MailBee;
using MailBee.ImapMail;
using MailBee.Mime;

class Sample
{
    static void Main(string[] args)
    {
        Imap imp = new Imap();

        // Enable logging for troubleshooting (for instance, you can see
        // if you send and receive correct FETCH requests and responses.
        imp.Log.Filename = @"C:\Temp\log.txt";
        imp.Log.Enabled = true;
        imp.Log.Clear();

        // Connect to the server, login and select inbox.
        imp.Connect("mail.company.com");
        imp.Login("user", "password");
        imp.SelectFolder("INBOX");

        // Download body structure for all e-mails in the inbox.
        EnvelopeCollection envs = imp.DownloadEnvelopes(Imap.AllMessages, true,
            EnvelopeParts.BodyStructure, 0);

        // The array of lists of FETCH keys to request from the server.
        string[][] fetchRequestKeyListArray = new string[envs.Count][];

        // The array of lists of FETCH keys to expect from the server in return
        // to requests of items listed in each element of fetchRequestKeyListArray.
        string[][] fetchResponseKeyListArray = new string[envs.Count][];

        // UIDs of the messages for which we received the body structure.
        long[] uids = new long[envs.Count];

        for (int i = 0; i < envs.Count; i++)
        {
            Envelope env = envs[i];

            ArrayList fetchRequestKeyList = new ArrayList();
            ArrayList fetchResponseKeyList = new ArrayList();

            // Get body structures of all MIME parts as flat list.
            ImapBodyStructureCollection parts = env.BodyStructure.GetAllParts();
            foreach (ImapBodyStructure part in parts)
            {
                if (part.ContentType.ToLower().IndexOf("image/") > -1)
                {
                    if (parts.Count > 1)
                    {
                        // For each image, we request its MIME part header and body
                        // (the IMAP4 protocol does not support getting the entire MIME
                        // part as a single block of data). Also note using .MIME instead of .HEADER
                        // because some mail servers don't support .HEADER syntax.
                        fetchRequestKeyList.Add("BODY.PEEK[" + part.PartID + ".MIME]");
                        fetchRequestKeyList.Add("BODY.PEEK[" + part.PartID + "]");

                        // For BODY.PEEK[...] request the server will return BODY[...] response.
                        fetchResponseKeyList.Add("BODY[" + part.PartID + ".MIME]");
                        fetchResponseKeyList.Add("BODY[" + part.PartID + "]");
                    }
                    else
                    {
                        fetchRequestKeyList.Add("BODY.PEEK[HEADER]");
                        fetchRequestKeyList.Add("BODY.PEEK[TEXT]");

                        // For BODY.PEEK[...] request the server will return BODY[...] response.
                        fetchResponseKeyList.Add("BODY[HEADER]");
                        fetchResponseKeyList.Add("BODY[TEXT]");
                    }
                }
            }

            // Second time, we'll get message by its UID. This will avoid the situation
            // when new message arrives between two queries (and thus it could be possible
            // to download wrong message second time).
            uids[i] = env.Uid;

            // Save the generated items for FETCH request and FETCH response.
            fetchRequestKeyListArray[i] = (string[])fetchRequestKeyList.ToArray(typeof(string));
            fetchResponseKeyListArray[i] = (string[])fetchResponseKeyList.ToArray(typeof(string));
        }

        if (envs.Count > 0)
        {
            // Download images.
            envs = imp.DownloadEnvelopesEx(uids, true,
                null, null, null,
                fetchRequestKeyListArray);

            foreach (Envelope env in envs)
            {
                // We need this to find FETCH request and response keys
                // which correspond to the envelope being examined.
                int index = Array.IndexOf(uids, env.Uid);

                if (index < 0)
                {
                    // For some odd reason, we got envelope we haven't requested.
                    // Hope this will never happen. Anyway, skip such envelope.
                    continue;
                }

                string[] fetchRequestKeys = fetchRequestKeyListArray[index];
                string[] fetchResponseKeys = fetchResponseKeyListArray[index];

                for (int i = 0; i < fetchRequestKeys.Length; i += 2)
                {
                    // Get MIME part header data.
                    byte[] mimePartHeader = (byte[])env.GetEnvelopeItem(
                        fetchResponseKeys[i], true);

                    // Get MIME part body data.
                    byte[] mimePartBody = (byte[])env.GetEnvelopeItem(
                        fetchResponseKeys[i + 1], true);

                    // Build MIME part data from header data and body data.
                    byte[] mimePartData = new byte[mimePartHeader.Length + mimePartBody.Length];
                    Buffer.BlockCopy(mimePartHeader, 0, mimePartData, 0, mimePartHeader.Length);
                    Buffer.BlockCopy(mimePartBody, 0, mimePartData,
                        mimePartHeader.Length, mimePartBody.Length);
                    mimePartHeader = null;
                    mimePartBody = null;

                    // Build Attachment object from the MIME part data.
                    MimePart part = MimePart.Parse(mimePartData);
                    Attachment picture = new Attachment(part);

                    // Save the image into C:\Temp folder.
                    picture.SaveToFolder(@"C:\Temp", false);
                }
            }
        }

        imp.Disconnect();
    }
}
[Visual Basic]
Imports System
Imports System.Collections
Imports MailBee
Imports MailBee.ImapMail
Imports MailBee.Mime

Class Sample
    Shared Sub Main(ByVal args() As String)
        Dim imp As Imap = New Imap

        ' Enable logging for troubleshooting (for instance, you can see
        ' if you send and receive correct FETCH requests and responses.
        imp.Log.Filename = "C:\Temp\log.txt"
        imp.Log.Enabled = True
        imp.Log.Clear()

        ' Connect to the server, login and select inbox.
        imp.Connect("mail.company.com")
        imp.Login("user", "password")
        imp.SelectFolder("INBOX")

        ' Download body structure for all e-mails in the inbox.
        Dim envs As EnvelopeCollection = imp.DownloadEnvelopes(Imap.AllMessages, True, _
         EnvelopeParts.BodyStructure, 0)

        ' The array of lists of FETCH keys to request from the server.
        Dim fetchRequestKeyListArray()() As String = New String(envs.Count)() {}

        ' The array of lists of FETCH keys to expect from the server in return
        ' to requests of items listed in each element of fetchRequestKeyListArray.
        Dim fetchResponseKeyListArray()() As String = New String(envs.Count)() {}

        ' UIDs of the messages for which we received the body structure.
        Dim uids() As Long = New Long(envs.Count) {}

        Dim i As Integer
        For i = 0 To envs.Count - 1
            Dim env As Envelope = envs(i)

            Dim fetchRequestKeyList As ArrayList = New ArrayList
            Dim fetchResponseKeyList As ArrayList = New ArrayList

            ' Get body structures of all MIME parts as flat list.
            Dim parts As ImapBodyStructureCollection = env.BodyStructure.GetAllParts()
            Dim part As ImapBodyStructure
            For Each part In parts
                If part.ContentType.ToLower().IndexOf("image/") > -1 Then
                    If parts.Count > 1 Then
                        ' For each image, we request its MIME part header and body
                        ' (the IMAP4 protocol does not support getting the entire MIME
                        ' part as a single block of data). Also note using .MIME instead of .HEADER
                        ' because some mail servers don't support .HEADER syntax.
                        fetchRequestKeyList.Add("BODY.PEEK[" + part.PartID + ".MIME]")
                        fetchRequestKeyList.Add("BODY.PEEK[" + part.PartID + "]")

                        ' For BODY.PEEK[...] request the server will return BODY[...] response.
                        fetchResponseKeyList.Add("BODY[" + part.PartID + ".MIME]")
                        fetchResponseKeyList.Add("BODY[" + part.PartID + "]")
                    Else
                        fetchRequestKeyList.Add("BODY.PEEK[HEADER]")
                        fetchRequestKeyList.Add("BODY.PEEK[TEXT]")

                        ' For BODY.PEEK[...] request the server will return BODY[...] response.
                        fetchResponseKeyList.Add("BODY[HEADER]")
                        fetchResponseKeyList.Add("BODY[TEXT]")
                    End If
                End If
            Next

            ' Second time, we'll get message by its UID. This will avoid the situation
            ' when new message arrives between two queries (and thus it could be possible
            ' to download wrong message second time).
            uids(i) = env.Uid

            ' Save the generated items for FETCH request and FETCH response.
            fetchRequestKeyListArray(i) = CType(fetchRequestKeyList.ToArray(GetType(String)), String())
            fetchResponseKeyListArray(i) = CType(fetchResponseKeyList.ToArray(GetType(String)), String())
        Next

        If envs.Count > 0 Then
            ' Download images.
            envs = imp.DownloadEnvelopesEx(uids, True, Nothing, Nothing, Nothing, fetchRequestKeyListArray)

            Dim env As Envelope
            For Each env In envs
                ' We need this to find FETCH request and response keys
                ' which correspond to the envelope being examined.
                Dim index As Integer = Array.IndexOf(uids, env.Uid)

                If index < 0 Then
                    ' For some odd reason, we got envelope we haven't requested.
                    ' Hope this will never happen. Anyway, skip such envelope.
                    ' In VB 2005 and higher you can use Continue statement instead of Goto.
                    GoTo ContinueHere
                End If

                Dim fetchRequestKeys() As String = fetchRequestKeyListArray(index)
                Dim fetchResponseKeys() As String = fetchResponseKeyListArray(index)

                Dim j As Integer
                For j = 0 To fetchRequestKeys.Length - 1 Step 2
                    ' Get MIME part header data.
                    Dim mimePartHeader, mimePartBody As Byte()
                    mimePartHeader = env.GetEnvelopeItem(CType(fetchResponseKeys(j), String), True)

                    ' Get MIME part body data.
                    mimePartBody = env.GetEnvelopeItem(CType(fetchResponseKeys(j + 1), String), True)

                    ' Build MIME part data from header data and body data.
                    Dim mimePartData As Byte()
                    ReDim mimePartData(mimePartHeader.Length + mimePartBody.Length)
                    Buffer.BlockCopy(mimePartHeader, 0, mimePartData, 0, mimePartHeader.Length)
                    Buffer.BlockCopy(mimePartBody, 0, mimePartData, mimePartHeader.Length, mimePartBody.Length)
                    mimePartHeader = Nothing
                    mimePartBody = Nothing

                    ' Build Attachment object from the MIME part data.
                    Dim part As MimePart = MimePart.Parse(mimePartData)
                    Dim picture As New Attachment(part)

                    ' Save the image into C:\Temp folder.
                    picture.SaveToFolder("C:\Temp", False)
                Next
ContinueHere:
            Next
        End If

        imp.Disconnect()
    End Sub
End Class

The second example is very similar to the first one but it downloads HTML and plain-text bodies rather than images.
[C#]

using System;
using System.Collections;
using MailBee;
using MailBee.ImapMail;
using MailBee.Mime;

class Sample
{
    static void Main(string[] args)
    {
        Imap imp = new Imap();

        // Enable logging for troubleshooting (for instance, you can see
        // if you send and receive correct FETCH requests and responses.
        imp.Log.Filename = @"C:\Temp\log.txt";
        imp.Log.Enabled = true;
        imp.Log.Clear();

        // Connect to the server, login and select inbox.
        imp.Connect("mail.company.com");
        imp.Login("user", "password");
        imp.SelectFolder("INBOX");

        // Download body structure for all e-mails in the inbox.
        EnvelopeCollection envs = imp.DownloadEnvelopes(Imap.AllMessages, true,
            EnvelopeParts.BodyStructure, 0);

        // The array of lists of FETCH keys to request from the server.
        string[][] fetchRequestKeyListArray = new string[envs.Count][];

        // The array of lists of FETCH keys to expect from the server in return
        // to requests of items listed in each element of fetchRequestKeyListArray.
        string[][] fetchResponseKeyListArray = new string[envs.Count][];

        // UIDs of the messages for which we received the body structure.
        long[] uids = new long[envs.Count];

        for (int i = 0; i < envs.Count; i++)
        {
            Envelope env = envs[i];

            ArrayList fetchRequestKeyList = new ArrayList();
            ArrayList fetchResponseKeyList = new ArrayList();

            // Get body structures of all MIME parts as flat list.
            ImapBodyStructureCollection parts = env.BodyStructure.GetAllParts();
            foreach (ImapBodyStructure part in parts)
            {
                string contentType = part.ContentType.ToLower();
                string disposition = (part.Disposition == null ? string.Empty : part.Disposition.ToLower());
                if (disposition != "attachment" &&
                    (contentType == "text/plain" || contentType == "text/html"))
                {
                    if (parts.Count > 1)
                    {
                        // For each text body part, we request its MIME part header and body
                        // (the IMAP4 protocol does not support getting the entire MIME
                        // part as a single block of data). Also note using .MIME instead of .HEADER
                        // because some mail servers don't support .HEADER syntax.
                        fetchRequestKeyList.Add("BODY.PEEK[" + part.PartID + ".MIME]");
                        fetchRequestKeyList.Add("BODY.PEEK[" + part.PartID + "]");

                        // For BODY.PEEK[...] request the server will return BODY[...] response.
                        fetchResponseKeyList.Add("BODY[" + part.PartID + ".MIME]");
                        fetchResponseKeyList.Add("BODY[" + part.PartID + "]");
                    }
                    else
                    {
                        fetchRequestKeyList.Add("BODY.PEEK[HEADER]");
                        fetchRequestKeyList.Add("BODY.PEEK[TEXT]");

                        // For BODY.PEEK[...] request the server will return BODY[...] response.
                        fetchResponseKeyList.Add("BODY[HEADER]");
                        fetchResponseKeyList.Add("BODY[TEXT]");
                    }
                }
            }

            // Second time, we'll get message by its UID. This will avoid the situation
            // when new message arrives between two queries (and thus it could be possible
            // to download wrong message second time).
            uids[i] = env.Uid;

            // Save the generated items for FETCH request and FETCH response.
            fetchRequestKeyListArray[i] = (string[])fetchRequestKeyList.ToArray(typeof(string));
            fetchResponseKeyListArray[i] = (string[])fetchResponseKeyList.ToArray(typeof(string));
        }

        if (envs.Count > 0)
        {
            // Download text parts.
            envs = imp.DownloadEnvelopesEx(uids, true, null, null, null, fetchRequestKeyListArray);

            foreach (Envelope env in envs)
            {
                // We need this to find FETCH request and response keys
                // which correspond to the envelope being examined.
                int index = Array.IndexOf(uids, env.Uid);

                if (index < 0)
                {
                    // For some odd reason, we got envelope we haven't requested.
                    // Hope this will never happen. Anyway, skip such envelope.
                    continue;
                }

                string[] fetchRequestKeys = fetchRequestKeyListArray[index];
                string[] fetchResponseKeys = fetchResponseKeyListArray[index];

                for (int i = 0; i < fetchRequestKeys.Length; i += 2)
                {
                    // Get MIME part header data.
                    byte[] mimePartHeader = (byte[])env.GetEnvelopeItem(
                        fetchResponseKeys[i], true);

                    // Get MIME part body data.
                    byte[] mimePartBody = (byte[])env.GetEnvelopeItem(
                        fetchResponseKeys[i + 1], true);

                    // Build MIME part data from header data and body data.
                    byte[] mimePartData = new byte[mimePartHeader.Length + mimePartBody.Length];
                    Buffer.BlockCopy(mimePartHeader, 0, mimePartData, 0, mimePartHeader.Length);
                    Buffer.BlockCopy(mimePartBody, 0, mimePartData,
                        mimePartHeader.Length, mimePartBody.Length);
                    mimePartHeader = null;
                    mimePartBody = null;

                    // Build TextBodyPart object from the MIME part data.
                    MimePart part = MimePart.Parse(mimePartData);
                    TextBodyPart textPart = new TextBodyPart(part);

                    // Print content-type and text content of the message.
                    Console.WriteLine("For message with UID=" + env.Uid);
                    Console.WriteLine("Content-Type=" + part.ContentType);
                    Console.WriteLine("The text follows...");
                    Console.WriteLine(textPart.Text);
                    Console.WriteLine("---------------------------------");
                    Console.WriteLine();
                }
            }
        }

        imp.Disconnect();
    }
}
[Visual Basic]
Imports System
Imports System.Collections
Imports MailBee
Imports MailBee.ImapMail
Imports MailBee.Mime

Class Sample
    Shared Sub Main(ByVal args() As String)
        Dim imp As Imap = New Imap

        ' Enable logging for troubleshooting (for instance, you can see
        ' if you send and receive correct FETCH requests and responses.
        imp.Log.Filename = "C:\Temp\log.txt"
        imp.Log.Enabled = True
        imp.Log.Clear()

        ' Connect to the server, login and select inbox.
        imp.Connect("localhost")
        imp.Login("alex", "12345")
        imp.SelectFolder("INBOX")

        ' Download body structure for all e-mails in the inbox.
        Dim envs As EnvelopeCollection = imp.DownloadEnvelopes(Imap.AllMessages, True, _
         EnvelopeParts.BodyStructure, 0)

        ' The array of lists of FETCH keys to request from the server.
        Dim fetchRequestKeyListArray()() As String = New String(envs.Count)() {}

        ' The array of lists of FETCH keys to expect from the server in return
        ' to requests of items listed in each element of fetchRequestKeyListArray.
        Dim fetchResponseKeyListArray()() As String = New String(envs.Count)() {}

        ' UIDs of the messages for which we received the body structure.
        Dim uids() As Long = New Long(envs.Count) {}

        Dim i As Integer
        For i = 0 To envs.Count - 1
            Dim env As Envelope = envs(i)

            Dim fetchRequestKeyList As ArrayList = New ArrayList
            Dim fetchResponseKeyList As ArrayList = New ArrayList

            ' Get body structures of all MIME parts as flat list.
            Dim parts As ImapBodyStructureCollection = env.BodyStructure.GetAllParts()
            Dim part As ImapBodyStructure
            For Each part In parts
                Dim contentType As String = part.ContentType.ToLower()
                Dim disposition As String = String.Empty
                If Not part.Disposition Is Nothing Then disposition = part.Disposition.ToLower()
                If disposition <> "attachment" AndAlso (contentType = "text/plain" Or contentType = "text/html") Then
                    If parts.Count > 1 Then
                        ' For each text body part, we request its MIME part header and body
                        ' (the IMAP4 protocol does not support getting the entire MIME
                        ' part as a single block of data). Also note using .MIME instead of .HEADER
                        ' because some mail servers don't support .HEADER syntax.
                        fetchRequestKeyList.Add("BODY.PEEK[" + part.PartID + ".MIME]")
                        fetchRequestKeyList.Add("BODY.PEEK[" + part.PartID + "]")

                        ' For BODY.PEEK[...] request the server will return BODY[...] response.
                        fetchResponseKeyList.Add("BODY[" + part.PartID + ".MIME]")
                        fetchResponseKeyList.Add("BODY[" + part.PartID + "]")
                    Else
                        fetchRequestKeyList.Add("BODY.PEEK[HEADER]")
                        fetchRequestKeyList.Add("BODY.PEEK[TEXT]")

                        ' For BODY.PEEK[...] request the server will return BODY[...] response.
                        fetchResponseKeyList.Add("BODY[HEADER]")
                        fetchResponseKeyList.Add("BODY[TEXT]")
                    End If
                End If
            Next

            ' Second time, we'll get message by its UID. This will avoid the situation
            ' when new message arrives between two queries (and thus it could be possible
            ' to download wrong message second time).
            uids(i) = env.Uid

            ' Save the generated items for FETCH request and FETCH response.
            fetchRequestKeyListArray(i) = CType(fetchRequestKeyList.ToArray(GetType(String)), String())
            fetchResponseKeyListArray(i) = CType(fetchResponseKeyList.ToArray(GetType(String)), String())
        Next

        If envs.Count > 0 Then
            ' Download text parts.
            envs = imp.DownloadEnvelopesEx(uids, True, Nothing, Nothing, Nothing, fetchRequestKeyListArray)

            Dim env As Envelope
            For Each env In envs
                ' We need this to find FETCH request and response keys
                ' which correspond to the envelope being examined.
                Dim index As Integer = Array.IndexOf(uids, env.Uid)

                If index < 0 Then
                    ' For some odd reason, we got envelope we haven't requested.
                    ' Hope this will never happen. Anyway, skip such envelope.
                    ' In VB 2005 and higher you can use Continue statement instead of Goto.
                    GoTo ContinueHere
                End If

                Dim fetchRequestKeys() As String = fetchRequestKeyListArray(index)
                Dim fetchResponseKeys() As String = fetchResponseKeyListArray(index)

                Dim j As Integer
                For j = 0 To fetchRequestKeys.Length - 1 Step 2
                    ' Get MIME part header data.
                    Dim mimePartHeader, mimePartBody As Byte()
                    mimePartHeader = env.GetEnvelopeItem(CType(fetchResponseKeys(j), String), True)

                    ' Get MIME part body data.
                    mimePartBody = env.GetEnvelopeItem(CType(fetchResponseKeys(j + 1), String), True)

                    ' Build MIME part data from header data and body data.
                    Dim mimePartData As Byte()
                    ReDim mimePartData(mimePartHeader.Length + mimePartBody.Length)
                    Buffer.BlockCopy(mimePartHeader, 0, mimePartData, 0, mimePartHeader.Length)
                    Buffer.BlockCopy(mimePartBody, 0, mimePartData, mimePartHeader.Length, mimePartBody.Length)
                    mimePartHeader = Nothing
                    mimePartBody = Nothing

                    ' Build TextBodyPart object from the MIME part data.
                    Dim part As MimePart = MimePart.Parse(mimePartData)
                    Dim textPart As TextBodyPart = New TextBodyPart(part)

                    ' Print content-type and text content of the message.
                    Console.WriteLine("For message with UID=" & env.Uid)
                    Console.WriteLine("Content-Type=" & part.ContentType)
                    Console.WriteLine("The text follows...")
                    Console.WriteLine(textPart.Text)
                    Console.WriteLine("---------------------------------")
                    Console.WriteLine()
                Next
ContinueHere:
            Next
        End If

        imp.Disconnect()
    End Sub
End Class

See Also

Imap Class | MailBee.ImapMail Namespace