ews-managed-api
ews-managed-api copied to clipboard
SearchFilter.IsGreaterThan returns same items for DateTimeReceived with Milliseconds DateTimePrecision
Hi there, I'm trying to create mechanism that will read all unread mails from certain mailbox. In each cycle I'm getting 10 emails from that mailbox.
ItemView view = new ItemView(10)
{
PropertySet = new PropertySet(ItemSchema.Id, EmailMessageSchema.DateTimeReceived)
};
view.OrderBy.Add(EmailMessageSchema.DateTimeReceived, SortDirection.Ascending);
SearchFilter receivedAfterFilter = new SearchFilter.IsGreaterThan(EmailMessageSchema.DateTimeReceived, lastSyncDate ?? DateTime.Now.AddYears(-1));
SearchFilter notReadFilter = new SearchFilter.IsEqualTo(EmailMessageSchema.IsRead, false);
var sf = new SearchFilter.SearchFilterCollection(LogicalOperator.And)
{
receivedAfterFilter,
notReadFilter
};
I've set DateTimePrecision = DateTimePrecision.Milliseconds
so DateTimeReceived contains milliseconds.
If last email in my results has DateTimeReceived= 2017-11-27 11:41:14.704
and I set that in my filter I get same email over and over.
My workaround is adding one millisecond like this:
receivedAfterFilter = new SearchFilter.IsGreaterThan(EmailMessageSchema.DateTimeReceived, lastMailTime.Value.AddMilliseconds(1));
Below is fully working example showing my issue. I'm not native English speaker, so code will speak for itself.
public IEnumerable<EmailMessage> GetEmails(FolderId root, SearchFilter itemsFilter, ItemView view)
{
foreach (Item item in _exchangeService.FindItems(root, itemsFilter, view))
{
if (item is EmailMessage mail)
{
Debug.WriteLine(mail.Id.UniqueId + " - " + mail.DateTimeReceived.ToString("yyyy-MM-dd HH:mm:ss.fff") + " - " + mail.Subject);
yield return mail;
}
}
}
private void button3_Click(object sender, EventArgs e)
{
var service = new ExchangeService(ExchangeVersion.Exchange2010_SP2)
{
Credentials = CredentialCache.DefaultNetworkCredentials,
TraceEnabled = true,
TraceFlags = TraceFlags.None, //All
TraceEnablePrettyPrinting = true,
Url = new Uri("https://mail.example.com/ews/exchange.asmx"),
Timeout = Int32.MaxValue,
DateTimePrecision = DateTimePrecision.Milliseconds
};
ItemView view = new ItemView(10)
{
PropertySet = new PropertySet(ItemSchema.Id, EmailMessageSchema.DateTimeReceived)
};
view.OrderBy.Add(EmailMessageSchema.DateTimeReceived, SortDirection.Ascending);
SearchFilter receivedAfterFilter = new SearchFilter.IsGreaterThanOrEqualTo(EmailMessageSchema.DateTimeReceived, DateTime.Now.Date);
SearchFilter notReadFilter = new SearchFilter.IsEqualTo(EmailMessageSchema.IsRead, false);
var sf = new SearchFilter.SearchFilterCollection(LogicalOperator.And)
{
receivedAfterFilter,
notReadFilter
};
var mailbox = new Mailbox("[email protected]");
var folderId = new FolderId(WellKnownFolderName.Inbox, mailbox);
DateTime? lastMailTime = null;
bool more = true;
while (more)
{
var emails = GetEmails(folderId, sf, view);
int i = 0;
foreach (var item in emails)
{
lastMailTime = item.DateTimeReceived;
i++;
}
if (i == 0)
{
more = false;
}
else
{
//receivedAfterFilter = new SearchFilter.IsGreaterThan(EmailMessageSchema.DateTimeReceived, lastMailTime.Value);// this cause infinite loop
receivedAfterFilter = new SearchFilter.IsGreaterThan(EmailMessageSchema.DateTimeReceived, lastMailTime.Value.AddMilliseconds(1));
sf = new SearchFilter.SearchFilterCollection(LogicalOperator.And)
{
receivedAfterFilter,
notReadFilter
};
}
Debug.WriteLine("END");
}
}
I think this is a bug, because IsGreaterThan
should return items except exact match (like in my case)
That is interesting. I am curious though - what are you trying to accomplish here? It seems like you are trying to do some dateTime based paging or something. There might be a better way to accomplish this.
I experienced the same issue, and also solved it with the +1 millisecond trick.
What I am doing is making a tool that iterates through emails in an inbox. I process 100 at a time, and I need to know which email to start with next time I run the tool. To do this I store the received date on the last email i retrieved, and then I search for all emails newer than this. If there is a better way to do this, please feel free to comment.
@snarum my final workaround was to move processed emails into folder (called Imported
for example).
This way I don't care about that time and I'm sure I don't miss anything.
More than 7 month but still not labeled and no assignee.
I'm also seeing the same issue. Moving to a 'Processed' folder is good but I'm not in a position to that.
Has anyone had any other solutions?
I understand, that this is not an issue of EWS Managed API, but how we can push this to EWS side to fix it?