ImapDownloadEnvelopes Method (String, Boolean, EnvelopeParts, Int32, String, String) |
Namespace: MailBee.ImapMail
public EnvelopeCollection DownloadEnvelopes( string messageIndexSet, bool indexIsUid, EnvelopeParts parts, int bodyPreviewSize, string[] extraHeaders, string[] extraItems )
Exception | Condition |
---|---|
MailBeeException | An error occurred and ThrowExceptions is true. |
Ordinal message numbers and UIDs are one-based (minimum value is 1, not 0). However, the returned EnvelopeCollection is zero-based. The developer can use MessageNumber or Uid properties to obtain ordinal message numbers and UIDs of the downloaded envelopes.
To specify multiple message numbers or UIDs in messageIndexSet, delimit them with comma (,) or use ranges (such as "5:10" which means "download messages in the range from message #5 to the message #10"). Wildcard character (*), can be used to specify range which spans till the last message in the folder. In particular, "1:*" means "download all messages in the folder". "1:*" is also declared as AllMessages constant.
Examples of valid message sequences: "1", "1:*", "1,2", "1:2", "5:10,12:45,99,101,105,141:*".
Note |
---|
A message sequence string may NOT contain whitespaces. The following is INCORRECT: "1, 2, 5". The correct one is: "1,2,5". |
When using a range of UIDs (indexIsUid is true), it's important to understand the number of returned messages may be LESS than the length of the range (or even zero). This is because UIDs are not continuous. For instance, if the folder contains messages with UIDs 4, 5, 6, 10, and 22, the "1,2,8:20" sequence of UIDs corresponds to a single message with UID=10.
parts parameters can be used to specify which message elements to download. This allows the developer to request only required information from the server and thus reduce network traffic by not downloading unnecessary data.
Note |
---|
If certain message element, attribute, or group of elements/attributes is not requested from the server, the developer should not attempt to read the corresponding properties of Envelope objects within the returned collection. For instance, if parts didn't contain Envelope (or MailBeeEnvelope, which is a superset of Envelope), From, To, Subject, and some other properties will not return useful information. See remarks in EnvelopeParts topic for more information on dependencies between downloaded parts of FETCH response and related properties of Envelope object. |
bodyPreviewSize parameter makes sense only when parts includes MessagePreview flag. When bodyPreviewSize is 0, the component will download only header section of each message (accessible via MessagePreview property). If bodyPreviewSize is larger than 0, the component will download the header and the specified count of bytes of the body. If bodyPreviewSize is -1 or -2, the entire message is returned (-2 will keep UNSEEN status). Methods like DownloadEntireMessage(Int64, Boolean) or DownloadMessageHeaders(String, Boolean) simply call DownloadEnvelopes(String, Boolean, EnvelopeParts, Int32, String, String) inside and then return MessagePreview values.
extraHeaders can be used to request certain additional header fields which are not included into ENVELOPE item of FETCH response and thus not present in Envelope object properties. Alternatively, the developer may request downloading the message header by setting MessagePreview flag in parts. Thus, all header fields would be downloaded. However, if the developer wants to reduce traffic and do not download entire header sections of messages, extraHeaders should be used to retrieve specific header fields. The typical usage of extraHeaders is getting "Importance" or "X-Priority" headers.
Values specified in extraItems are passed to the IMAP4 server without alteration. Using extraItems, the developer can request any valid FETCH item from the server (for instance, the developer may request downloading the contents of certain attachment or text body part of the message via its PartID). The downloaded items can than be obtained via GetEnvelopeItem(String, Boolean) method call.
When using extraItems, it's important to remember that item names in FETCH request can be different from their counterparts in the corresponding FETCH response. E.g. if requested item name is "BODY.PEEK[3.HEADER]<0.100>", the server will return "BODY[3.HEADER]<0>" name in the response. The developer may refer to the IMAP4 protocol specification (RFC3501) for more information regarding FETCH requests and responses.
Note |
---|
Due to complexity of IMAP4 responses, some servers may return badly formed FETCH responses under certain circumstances. If MailBee detects this, it raises ErrorOccurred event and sets IsValid to false. Since this is done on per-envelope basis, some Envelope objects in the returned collection may have IsValid set to false while others - to true. Anyway, the component does not throw exception when it encounters invalid envelope. This allows the application to skip invalid response and successfully receive subsequent messages. |
This sample downloads "X-Priority" and "X-MS-Mail-Priority" header fields for all messages in Inbox, then finds out which messages have High priority, and downloads body structures for these messages. From the body structures, the sample code obtains which messages have attachments. Then, these messages are completely downloaded, and all attachments are saved into "C:\Temp" folder.
The sample performs search of high priority messages via downloading headers just to highlight how to download custom headers. In real world, it's more effective to use Search(Boolean, String, String) method for this. The sample allows the developer to change code path to using Search(Boolean, String, String) via setting searchViaEnvelopes variable value to false.
The sample also keeps track of invalid IMAP responses in ErrorOccurred event handler.
using System; using MailBee; using MailBee.ImapMail; class Sample { // ErrorOccurred event handler. private static void OnErrorOccurred(object sender, ErrorEventArgs e) { if (e.Reason is MailBeeImapInvalidEnvelopeException) { MailBeeImapInvalidEnvelopeException invEnvEx = (MailBeeImapInvalidEnvelopeException)e.Reason; Console.WriteLine("Fetched data for message #" + invEnvEx.InvalidEnvelope.MessageNumber + " could not be completed parsed and will be ignored"); } } static void Main(string[] args) { Imap imp = new Imap(); imp.Connect("imap.somehost.com"); imp.Login("jdoe@somehost.com", "secret"); // Select Inbox folder. imp.SelectFolder("INBOX"); // Subscribe to ErrorOccurred event to track invalid envelopes. // We could also subscribe before calling Login or Connect since // we check the type of occurred error in OnErrorOccurred handler. imp.ErrorOccurred += new ErrorEventHandler(OnErrorOccurred); EnvelopeCollection envs = null; // We'll collect UID of high priority messages in this collection. UidCollection uids = new UidCollection(); // If true, we'll search high priority messages using DownloadEnvelopes(). // Otherwise, we'll use Search() method (much more effective). Thus, this // sample highlights both approaches. bool searchViaEnvelopes = true; // Download "X-Priority" and "X-MS-Mail-Priority" headers for each message. // We could have used Search() instead (just set searchViaEnvelopes=false). // Using Search() would be more effective. Imap.DownloadEnvelopes is used // here only to demonstrate how to get custom header fields from the server. if (searchViaEnvelopes) { envs = imp.DownloadEnvelopes(Imap.AllMessages, false, EnvelopeParts.Uid, 0, new string[] {"X-Priority", "X-MS-Mail-Priority"}, null); // For each message, determine if it's high priority. foreach (Envelope env in envs) { bool highPriority = false; if (env.IsValid) { string priority = env.ExtraHeaders["X-Priority"]; if (priority != null && priority.Length > 0) { if (priority[0] == '1' || priority[0] == '2') { // X-Priority is High or Highest highPriority = true; } } else { priority = env.ExtraHeaders["X-MS-Mail-Priority"]; if (priority != null && string.Compare(priority, "High", true) == 0) { // X-MS-Mail-Priority is High highPriority = true; } } } if (highPriority) { uids.Add(env.Uid); } } } else { // To search for High-Priority messages in the most effective way, set // searchViaEnvelopes=false in the beginning of this sample. Search() method // performs the same job as the code block above but produces much less // traffic and consumes less resources. uids = (UidCollection)imp.Search(true,"OR OR HEADER \"X-Priority\" \"1\" " + "HEADER \"X-Priority\" \"2\" HEADER \"X-MS-Mail-Priority\" \"High\"", null); } if (uids.Count > 0) { // Download envelope structures of high priority messages. envs = imp.DownloadEnvelopes(uids.ToString(), true, EnvelopeParts.BodyStructure, 0, null, null); // We'll collect UID of high priority messages with attachments in this collection. uids = new UidCollection(); // For each message, determine if it has attachments. foreach (Envelope env in envs) { if (env.IsValid) { ImapBodyStructureCollection parts = env.BodyStructure.GetAllParts(); foreach (ImapBodyStructure part in parts) { // Detect if this part is attachment. if ((part.Disposition != null && part.Disposition.ToLower() == "attachment") || (part.Filename != null && part.Filename != string.Empty) || (part.ContentType != null && part.ContentType.ToLower() == "message/rfc822")) { uids.Add(env.Uid); break; } } } } if (uids.Count > 0) { // We could also call DownloadEntireMessages here. Internally, // DownloadEntireMessages would call DownloadEnvelopes with the same // parameters and returned MailMessageCollection where each MailMessage // would be taken from Envelope.MessagePreview. envs = imp.DownloadEnvelopes(uids.ToString(), true, EnvelopeParts.MessagePreview, -1, null, null); foreach (Envelope env in envs) { if (env.IsValid) { // Save all attachments. Note: if the folder already contains // attachment with the given name, MailBee will generate unique name // (e.g. pic.gif will be saved as pic[1].gif if pic.gif already exists // in the target folder. env.MessagePreview.Attachments.SaveAll(@"C:\Temp"); } } } } // Disconnect from the server. imp.Disconnect(); } }