This project is read-only.

Loop through certain messages only

Topics: Help requests
Nov 11, 2013 at 10:35 PM
I'm trying to optimize my program to run most efficiently. Right now, I have
      ImapX.Folder myInbox = client.Folders.Inbox;                    
                    ImapX.Folder myArchive = client.Folders.All;
                    ImapX.Message[] messages = myInbox.Search("ALL",       ImapX.Enums.MessageFetchMode.Basic | ImapX.Enums.MessageFetchMode.GMailExtendedData, 1000);
with some filters a bit later on doing this
 if (messages[i].From.DisplayName.Contains("Company A") || messages[i].From.DisplayName.Contains("Company B"))
                        {
                            if (!messages[i].Labels.Contains("Processed")
                                && !messages[i].Labels.Contains("Research")
                                && !messages[i].Labels.Contains("MANUAL")
                                && !messages[i].Labels.Contains("Failed")
                                && !messages[i].Labels.Contains("Success")
                                && !messages[i].Labels.Contains("Duplicate"))
                            {//check email}
I am now thinking it might better/more efficient to loop through one message at a time, check it, and process it - rather than loading 100 - 1000 emails into memory.

Before I rewrite the code to try this method, I want to see if there is a way to filter the emails before they are loaded into memory.
Nov 12, 2013 at 11:15 AM
Hi maylortaylor,

of course it is possible to filter messages on the server side. For it, you can use filter options provided by the IMAP SEARCH command, such as:
myInbox.Search("FROM \"Company A\")
But, as you're using GMail, you can take advantage of the X-GM-RAW search extension, which is more comfortable.

A sample query could look like this:
X-GM-RAW "(from:Company A) OR (from:Company B) -((label:excluded label 1) OR (label:excluded label 2))"
To make it simplier, I put a sample together, based on the code your provided:
ImapX.Folder myInbox = client.Folders.Inbox;                    
ImapX.Folder myArchive = client.Folders.All;

var excludeLabels = new string[] {"Processed", "Research", "MANUAL", "Failed", "Success", "Duplicate"};
var senders = new string[] {"Company A", "Company B"};

var query = string.Format("X-GM-RAW \"{0} -({1})\"",
    string.Join(" OR ", senders.Select(sender => "(from:" + sender + ")")),
    string.Join(" OR ", excludeLabels.Select(label => "(label:" + label + ")")));

ImapX.Message[] messages = myInbox.Search(query, ImapX.Enums.MessageFetchMode.Basic | ImapX.Enums.MessageFetchMode.GMailExtendedData, 1000);
For a full reference of the possible filters for the X-GM-RAW search extension you can read this article: GMail Advanced search

Another option to optimize the fetching is requesting the UIds only, and downloading each message separately:
ImapX.Message[] messages = myInbox.Search(query, ImapX.Enums.MessageFetchMode.None, 1000);
foreach(var msg in messages)
{
       msg.Download(ImapX.Enums.MessageFetchMode.Basic | ImapX.Enums.MessageFetchMode.GMailExtendedData);
}
Best regards,

Pavel
Nov 13, 2013 at 10:28 PM
Edited Nov 13, 2013 at 11:14 PM
This helped a lot! Thank you Pavel

Is there a way to select messages from a certain time?

Such as "is a message sent before DateTime.Today() before 4pm"

EDIT:


Is this the best way?
if (messages[i].Date.Value > DateTime.Today.AddHours(16))
                         {
                             messages[i].Remove();
                         }
It seems that X-GM-Raw only allows you to do "before: Date" (11/13/2013) and not "before: DateTime" (11/13/2013 4:00pm)
Nov 14, 2013 at 10:48 AM
Hi maylortaylor,

this is a limitation of the IMAP protocol, as the messages can only be filtered by date, and not by time. The X-GM-RAW extension, being just an overlay, surely has same limitation. The only way to filter messages by time is after you requested them.

Greets,

Pavel