ImapLastDownloadedEnvelopes Property |
Namespace: MailBee.ImapMail
Note |
---|
This is an advanced property which serves special purposes. It's activated via setting EnableLastDownloaded prior to calling a method which requests envelopes from the server. |
This property can be used to get downloaded envelopes in the case if the corresponding method failed. Imap methods throw an exception or return a null reference on failure. Sometimes, however, the developer still wishes to get envelopes which had already been received to the moment of failure (for instance, if 100 envelopes had been received and error occurred for envelope #101). In this case, the developer can use this property to get envelopes 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, LastDownloadedEnvelopes will be reset to a null reference with a new call of any method requesting envelopes from the server.
This sample demonstrates reliable approach to downloading messages from an IMAP4 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 IMAP4 session, the code suddenly closes the connection during getting message data from the server.
using System; using MailBee; using MailBee.ImapMail; class Sample { static int traffic; static bool downloadingEnvelopes; // We use Imap.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 imp_DataReceived(object sender, DataTransferEventArgs e) { if (downloadingEnvelopes) { 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) { ((Imap)sender).Log.WriteLine("SIMULATE CONNECTION DROP"); ((Imap)sender).GetSocket().Close(); } } } static void Main(string[] args) { Imap imp = new Imap(); // Enable logging IMAP4 session into a file. Useful for troubleshooting. // Also, this log can be used to track the history of disconnections and // reconnections during downloading messages. imp.Log.Filename = @"C:\Temp\log.txt"; imp.Log.Enabled = true; imp.Log.Clear(); // Attach to a DataReceived event which will be used for simulating // connection failures. imp.DataReceived += new DataTransferEventHandler(imp_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 envelopes with UIDs larger than // lastUid. For the first time, set it to 0 (which is less than UID of // any message because minimum value of UID is 1). long lastUid = 0; // We'll collect downloaded messages in this collection. EnvelopeCollection envs = new EnvelopeCollection(); // 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 envelopes downloaded during execution of the last method. imp.EnableLastDownloaded = true; do { // Prevent connection drop simulation when not downloading messages. downloadingEnvelopes = false; // Connect or reconnect to the server if required (and login/select inbox). if (!imp.IsConnected) { imp.Connect("mail.domain.com"); } if (!imp.IsLoggedIn) { imp.Login("jdoe", "secret"); } if (!imp.IsFolderSelected) { imp.SelectFolder("INBOX"); } traffic = 0; try { // Enable connection drop simulation. downloadingEnvelopes = true; // Download the remaining messages. imp.DownloadEnvelopes((lastUid + 1).ToString() + ":*", true, EnvelopeParts.MessagePreview, -1); // Disable connection drop simulation. downloadingEnvelopes = false; // All's done. envs.Add(imp.LastDownloadedEnvelopes); finished = true; } catch (MailBeeException e) { downloadingEnvelopes = false; if (imp.LastDownloadedEnvelopes == null || imp.LastDownloadedEnvelopes.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 envelopes have still been // downloaded. We'll proceed with getting the rest of messages. envs.Add(imp.LastDownloadedEnvelopes); // Get last UID from the value of UID of the last downloaded message. lastUid = imp.LastDownloadedEnvelopes[imp.LastDownloadedEnvelopes.Count - 1].Uid; } } } while (!finished); // Clear and disable the cache of the last downloaded envelopes. imp.EnableLastDownloaded = false; if (imp.IsConnected) { // Attempt to disconnect (we need to catch MailBeeSocketObjectDisposedException // here because we simulated connection drop bypassing MailBee (using Socket.Close() // method) and Imap.IsConnected could remain true). In real world apps, this // is not required and Imap.IsConnected always reflects the actual state of // the connection. try { imp.Disconnect(); } catch (MailBeeSocketObjectDisposedException) {} } // Display UIDs of the downloaded messages. foreach (Envelope env in envs) { Console.Write(env.Uid + " "); } } }