MailBee.NET Objects 3.1

Pop3.LastDownloadedMessages Property

Gets the collection of the messages downloaded to the current moment.

public MailBee.Mime.MailMessageCollection LastDownloadedMessages {get;}

Property Value

A reference to the collection of the mail messages downloaded to the current moment by the corresponding method of Pop3 component, or a null reference (Nothing in Visual Basic) if EnableLastDownloaded is false or no method receiving mail messages has already been called (or if such method failed prior to starting receiving messages).

Remarks

Note   This is an advanced property which serves special purposes. It's activated via setting EnableLastDownloaded prior to calling a method which requests mail messages from the server.

This property can be used to get downloaded mail messages in the case if the corresponding method failed. Pop3 methods throw an exception or return a null reference on failure. Sometimes, however, the developer still wishes to get messages which had already been received to the moment of failure (for instance, if 100 messages had been received and error occured for message #101). In this case, the developer can use this property to get messages which had already been received and parsed to the moment of the failure.

When this collection is not needed any longer, the developer should set EnableLastDownloaded to false to free the resources. Also, LastDownloadedMessages will be reset to a null reference with a new call of any method requesting mail messages from the server.

Example

This sample demonstrates reliable approach to downloading messages from a POP3 account. The code tolerates disconnections and other errors which may occur during downloading messages. If any problem occurs, the code reconnects to the server if needed and attempts to download the remaining messages (already downloaded messages are not downloaded again, however). Also, the code execution won't end up in an endless loop in the case of permanent errors (if no messages had been downloaded at all, the code won't try again).

To simulate connection drops during the POP3 session, the code suddenly closes the connection during getting message data from the server.

[C#]
using System;
using MailBee;
using MailBee.Mime;
using MailBee.Pop3Mail;

class Sample
{
    static int  traffic;
    static bool downloadingMsgs;

    // We use Pop3.DataReceived event to simulate connection drop during
    // getting message data from the server. We do this through closing
    // the connection after 50000 bytes of message data has been received from the
    // server. This may occur multiple times (for instance, if there is 1MB of mail
    // in the inbox, the connection will be dropped about 20 times).
    // If, however, there is a message larger than 50KB in the inbox, the download process
    // will stop because it would otherwise end up in an endless loop (because this code
    // always disconnects on getting 50-th KB of the data and it would never have received
    // such message completely).
    static void pop_DataReceived(object sender, DataTransferEventArgs e)
    {
        if (downloadingMsgs)
        {
            traffic += e.Data.Length;

            // Increase 50000 to a larger value if you wish to test this code with
            // a mailbox containing large messages (larger than 50KB).
            if (traffic > 50000)
            {
                ((Pop3)sender).Log.WriteLine("SIMULATE CONNECTION DROP");
                ((Pop3)sender).GetSocket().Close();
            }
        }
    }

    static void Main(string[] args)
    {
        // Initialize Pop3 object and make it automatically load UIDs of all messages on the server.
        Pop3 pop = new Pop3();
        pop.InboxPreloadOptions = Pop3InboxPreloadOptions.Uidl;

        // Enable logging POP3 session into a file. Useful for troubleshooting.
        // Also, this log can be used to track the history of disconnections and
        // reconnections during downloading messages.
        pop.Log.Filename = @"C:\log.txt";
        pop.Log.Enabled = true;
        pop.Log.Clear();

        // Attach to a DataReceived event which will be used for simulating
        // connection failures.
        pop.DataReceived += new DataTransferEventHandler(pop_DataReceived);

        // Will set it to true once either everything has been downloaded
        // or a permanent error has occurred.
        bool finished = false;

        // Remember UID of the last message which had already been downloaded.
        // After reconnecting, we'll download messages with UIDs corresponding to
        // subsequent messages. For the first time, set it to null to indicate no
        // messages had already been downloaded.
        string lastUid = null;

        // We'll collect downloaded messages in this collection.
        MailMessageCollection msgs = new MailMessageCollection();

        // Because we catch exceptions in this code but still want to know
        // which error has occurred in the case of permanent failure, we remember
        // the reason of it.
        MailBeeException permanentException = null;

        // Enable cache of messages downloaded during execution of the last method.
        pop.EnableLastDownloaded = true;

        do
        {
            // Prevent connection drop simulation when not downloading messages.
            downloadingMsgs = false;

            // Connect or reconnect to the server if required (and login/select inbox).
            if (!pop.IsConnected)
            {
                pop.Connect("pop.company.com");
            }
            if (!pop.IsLoggedIn)
            {
                pop.Login("jdoe", "secret");
            }

            traffic = 0;

            try
            {
                // Enable connection drop simulation.
                downloadingMsgs = true;

                int lastMsgNumber = 0;
                if (lastUid != null)
                {
                    lastMsgNumber = pop.GetMessageIndexFromUid(lastUid);
                }

                if (lastMsgNumber < pop.InboxMessageCount)
                {
                    // Download the remaining messages.
                    pop.DownloadEntireMessages(lastMsgNumber + 1, -1);
                    msgs.Add(pop.LastDownloadedMessages);
                }

                // Disable connection drop simulation.
                downloadingMsgs = false;

                // All's done.
                finished = true;
            }
            catch (MailBeeException e)
            {
                downloadingMsgs = false;

                if (pop.LastDownloadedMessages == null ||
                    pop.LastDownloadedMessages.Count == 0)
                {
                    // Haven't got any messages. Assume this is permanent error
                    // (otherwise, we could get endless loop).
                    finished = true;
                    permanentException = e;
                }
                else
                {
                    // Error has occurred but some messages have still been
                    // downloaded. We'll proceed with getting the rest of messages.
                    msgs.Add(pop.LastDownloadedMessages);

                    // Get last UID from the value of UID of the last downloaded message.
                    lastUid = (string)pop.LastDownloadedMessages[pop.LastDownloadedMessages.Count - 1].UidOnServer;
                }
            }
        } while (!finished);

        // Clear and disable the cache of the last downloaded messages.
        pop.EnableLastDownloaded = false;

        if (pop.IsConnected)
        {
            // Attempt to disconnect (we need to catch MailBeeSocketObjectDisposedException
            // here because we simulated connection drop bypassing MailBee (using Socket.Close()
            // method) and Pop3.IsConnected could remain true). In real world apps, this
            // is not required and Pop3.IsConnected always reflects the actual state of
            // the connection.
            try
            {
                pop.Disconnect();
            }
            catch (MailBeeSocketObjectDisposedException) {}
        }

        // Display UIDs of the downloaded messages.
        foreach (MailMessage msg in msgs)
        {
            Console.Write((string)msg.UidOnServer + " ");
        }
    }
}
[Visual Basic]
Imports System
Imports MailBee
Imports MailBee.Mime
Imports MailBee.Pop3Mail

Class Sample
    Shared traffic As Integer
    Shared downloadingMsgs As Boolean

    ' We use Pop3.DataReceived event to simulate connection drop during
    ' getting message data from the server. We do this through closing
    ' the connection after 50000 bytes of message data has been received from the
    ' server. This may occur multiple times (for instance, if there is 1MB of mail
    ' in the inbox, the connection will be dropped about 20 times).
    ' If, however, there is a message larger than 50KB in the inbox, the download process
    ' will stop because it would otherwise end up in an endless loop (because this code
    ' always disconnects on getting 50-th KB of the data and it would never have received
    ' such message completely).
    Shared Sub pop_DataReceived(ByVal sender As Object, ByVal e As DataTransferEventArgs)
        If downloadingMsgs Then
            traffic += e.Data.Length

            ' Increase 50000 to a larger value if you wish to test this code with
            ' a mailbox containing large messages (larger than 50KB).
            If traffic > 50000 Then
                CType(sender, Pop3).Log.WriteLine("SIMULATE CONNECTION DROP")
                CType(sender, Pop3).GetSocket().Close()
            End If
        End If
    End Sub

    Shared Sub Main(ByVal args() As String)
        ' Initialize Pop3 object and make it automatically load UIDs of all messages on the server.
        Dim pop As Pop3 = New Pop3
        pop.InboxPreloadOptions = Pop3InboxPreloadOptions.Uidl

        ' Enable logging POP3 session into a file. Useful for troubleshooting.
        ' Also, this log can be used to track the history of disconnections and
        ' reconnections during downloading messages.
        pop.Log.Filename = "C:\log.txt"
        pop.Log.Enabled = True
        pop.Log.Clear()

        ' Attach to a DataReceived event which will be used for simulating
        ' connection failures.
        AddHandler pop.DataReceived, AddressOf pop_DataReceived

        ' Will set it to true once either everything has been downloaded
        ' or a permanent error has occurred.
        Dim finished As Boolean = False

        ' Remember UID of the last message which had already been downloaded.
        ' After reconnecting, we'll download messages with UIDs corresponding to
        ' subsequent messages. For the first time, set it to null to indicate no
        ' messages had already been downloaded.
        Dim lastUid As String = Nothing

        ' We'll collect downloaded messages in this collection.
        Dim msgs As MailMessageCollection = New MailMessageCollection

        ' Because we catch exceptions in this code but still want to know
        ' which error has occurred in the case of permanent failure, we remember
        ' the reason of it.
        Dim permanentException As MailBeeException = Nothing

        ' Enable cache of messages downloaded during execution of the last method.
        pop.EnableLastDownloaded = True

        Do
            ' Prevent connection drop simulation when not downloading messages.
            downloadingMsgs = False

            ' Connect or reconnect to the server if required (and login/select inbox).
            If Not pop.IsConnected Then
                pop.Connect("pop.company.com")
            End If
            If Not pop.IsLoggedIn Then
                pop.Login("jdoe", "secret")
            End If

            traffic = 0

            Try
                ' Enable connection drop simulation.
                downloadingMsgs = True

                Dim lastMsgNumber As Integer = 0
                If Not lastUid Is Nothing Then
                    lastMsgNumber = pop.GetMessageIndexFromUid(lastUid)
                End If

                If lastMsgNumber < pop.InboxMessageCount Then
                    ' Download the remaining messages.
                    pop.DownloadEntireMessages(lastMsgNumber + 1, -1)
                    msgs.Add(pop.LastDownloadedMessages)
                End If

                ' Disable connection drop simulation.
                downloadingMsgs = False

                ' All's done.
                finished = True
            Catch e As MailBeeException
                downloadingMsgs = False

                If pop.LastDownloadedMessages Is Nothing Or pop.LastDownloadedMessages.Count = 0 Then
                    ' Haven't got any messages. Assume this is permanent error
                    ' (otherwise, we could get endless loop).
                    finished = True
                    permanentException = e
                Else
                    ' Error has occurred but some messages have still been
                    ' downloaded. We'll proceed with getting the rest of messages.
                    msgs.Add(pop.LastDownloadedMessages)

                    ' Get last UID from the value of UID of the last downloaded message.
                    lastUid = CType(pop.LastDownloadedMessages(pop.LastDownloadedMessages.Count - 1).UidOnServer, String)
                End If
            End Try
        Loop While Not finished

        ' Clear and disable the cache of the last downloaded messages.
        pop.EnableLastDownloaded = False

        If pop.IsConnected Then
            ' Attempt to disconnect (we need to catch MailBeeSocketObjectDisposedException
            ' here because we simulated connection drop bypassing MailBee (using Socket.Close()
            ' method) and Pop3.IsConnected could remain true). In real world apps, this
            ' is not required and Pop3.IsConnected always reflects the actual state of
            ' the connection.
            Try
                pop.Disconnect()
            Catch e As MailBeeSocketObjectDisposedException
            End Try
        End If

        ' Display UIDs of the downloaded messages.
        Dim msg As MailMessage
        For Each msg In msgs
            Console.Write(CType(msg.UidOnServer, String) & " ")
        Next
    End Sub
End Class

See Also

Pop3 Class | MailBee.Pop3Mail Namespace | EnableLastDownloaded