+1 vote

Hello,

I have an mailbox account on Business Gmail and I receive messages using IMAP.
Also, for receiving new messages I store the maxReceivedUID, in order to receive only new UIDs every time.

Code

List uids = imap.Search().Where(Expression.UID(Range.From(maxReceivedUID)));

I have an issue with this and I will try to explain it.

The stored value of maxReceivedUID is 2601. This value is incorrect, and it should be 790 (because that was the UID value of last received message) but by mistake I stored wrong UID.
If I have a new message (with UID 791) then I expect to returns nothing because I ask with greater value on UID From (2601).

List<long> uids = imap.Search().Where(Expression.UID(Range.From(2601)));

But code returns UID value 790.

First question: Why returns 790 even if I asked with greater value?

Second question: Why the return value was not 791? If i try to receive message data with UID 791, then I get them (proves that message UID 791 exists)

imap.GetMessageByUID(791);

Every time that I try to receive new messages with the previous code, I get the same result. But if I have a new message (with UID 792), then the same code returns UID 792.

Could you please help me?

by (1.2k points)

1 Answer

0 votes

790 is the last UID in your mailbox.

IMAP protocol specification says that, if you ask for an UID range from X to infinity, X is always returned. E.g. 99 to infinity gives 99, 100, 101, ..., 789, 790 - note 99 in the result set. 790 to infinity gives 790.

If X is greater than the last UID, the last UID will be returned. 999 to infinity gives 790.

This is the behavior IMAP protocol requires.

This is why in all Limilabs samples we remove last processed UID from search results:

var uids = imap.Search().Where(
    Expression.UID(Range.From(lastProcessedUID)));

uids.Remove(lastProcessedUID);

Here's test that illustrates this:

// Get all uids
List<long> all= client.GetAll();
// search for max UID on the client
long max = all.Max();
// Get last from the server
long last = client.Search(Expression.UID(Range.Last())).Single();
// client max must match the server side found last
Assert.AreEqual(max, last); 


// search for uids greater then last
List<long> greaterThanLast = client.Search(
    Expression.UID(Range.From(last)));
// one element must be returned (last)
Assert.AreEqual(new[]{last}, greaterThanLast);


// search for uids greater then last by any value (e.g. 99)
List<long> greaterThanLastPlus99 = client.Search(
    Expression.UID(Range.From(last + 99)));
// one element must be returned (last)
Assert.AreEqual(new[] { last }, greaterThanLastPlus99);


// downloading last should succeed
Assert.IsNotNull(client.GetMessageByUID(last));
// downloading anything larger than last should fail
Assert.IsNull(client.GetMessageByUID(last + 1));
by (297k points)
edited by
Based on you answer, why the return value was not 791? If I try to receive message data with UID 791, then I get them (proves that message with UID 791 exists).

After that, if I have a new message (with UID 792), then the same code returns UID 792 (correct - but never returns 791).
Are you saying that search for Range.From(2601) gives one UID (790), and searching for Range.From(791) gives you a list of records (791, 792, ....)?
I understand where was the issue (based on your answer).

Because I have (by mistake) 2601 as the Max Received UID, when Mail Server receive 2 new messages (UIDs 791, 792) and I search for Range.From(2601) gave me one UID (792) and I lost 791.

Thank you for your help!
...