Archived Forum Post

Index of archived forum posts

Question:

IMAP Gmail UID, FetchSequenceHeaders not returning true uid, but only sequence number?

Nov 28 '12 at 11:13

Perhaps I'm not doing this right, but I'd like to use FetchSequenceHeaders to download chunks of message headers and save off the UID so I can pull down the specific message later as necessary.

Now, in order to this this I've got the following pseudo code:

 bundle = m_imap.FetchSequenceHeaders(messcount,messremainder);
     if (bundle == 0 ) {
        return;
        }       
     for (i = 0; i <= bundle->get_MessageCount() - 1; i++) {
        CkEmail *email = 0;
        email = bundle->GetEmail(i);
        uid.appendInt(email->GetImapUid()); //Always returns a simple sequence number, 1,2,3,etc, shouldn't this return something "universal"?
        delete email;
     }

Now there's a good chance I'm not doing this right, any suggestions would be appreciated.

-hz


Answer

The online reference documentation for Email.GetImapUid explains it:

When email headers are downloaded from an IMAP server (using Chilkat IMAP), a "ckx-imap-uid" header field is added. The content of this header is the UID or sequence number of the email on the IMAP server. In addition, a "ckx-imap-isUid" header field is added, and this will have the value YES or NO. If the value is YES, then ckx-imap-uid contains a UID, if the value is NO, then ckx-imap-uid contains the sequence number. This method returns the UID if ckx-imap-uid exists and contains a UID, otherwise it returns -1.

An application that wishes to download the full email would use this UID and then call the Chilkat IMAP object's FetchSingle or FetchSingleAsMime methods.

If this method is not yet available in your version of the Chilkat Email object, you may also call GetHeaderField("ckx-imap-uid") to fetch the UID as a string, and then convert it to an integer.


Answer

Also, given that you fetched the email via sequence numbers, the Email objects will not have the IMAP UID's available. The ckx-imap-uid header will contain the sequence number, and the ckx-imap-isUid header should be set to "NO".

Given that the UID is not available, the email.GetImapUid method should return -1 instead of the sequence number. I suspect this is the fix that is needed within Chilkat.


Answer

Thanks! So how would I go about getting the UID if I fetch by sequence? Or is fetching by sequence the wrong way to do this?

Perhaps it would help if I explained the goal of this exercise. I would like to parse out the IMAP folders and messages, storing off the headers and a "key" that can be used to pull down an individual message later if possible.

In reviewing IMAP it appears UIDVALIDITY is the first part of that 64bit UID value that identifies a messages, and UIDVALIDITY is returned as part of a SELECT MAILBOX process.

So, in order to have a unique key to any individual message I'd need to know the mailbox and the UID, or is it possible to store one value that chilkat will use to find the message?

Thanks!


Answer

I looked further into it by looking into the contents of the imap.SessionLog property as well as examining the MIME of the emails returned by FetchSequenceHeaders. The IMAP server is returning the UID as part of the response for each email, and Chilkat is using it. For example, this is from the SessionLog:

* 2 FETCH (UID 558 FLAGS (Seen) RFC822.SIZE 45569 BODYSTRUCTURE 
((("text" "plain" ("charset" "utf-8") NIL NIL "quoted-printable" 10137 386 NIL NIL NIL)("text" "html"  ...
Also, I see the UID in the headers of the email:
...
X-Mailer: Microsoft Office Outlook 12.0
Thread-Index: Ac3KnE2lfTZeczcXR2KgSB/vMb6wOwCU+Brw
Content-Language: de
X-OriginalArrivalTime: 27 Nov 2012 23:18:02.0432 (UTC) FILETIME=[728A1C00:01CDCCF5]
ckx-imap-uid: 558
ckx-imap-isUid: YES
ckx-imap-seen: YES
ckx-imap-answered: NO
ckx-imap-deleted: NO
ckx-imap-flagged: NO
ckx-imap-draft: NO
ckx-imap-flags: Seen
ckx-imap-totalSize: 45569
ckx-imap-numAttach: 0
Therefore, I think what you are seeing should indeed by the UID. The UID will still be a sequential integer.


Answer

Sounds fair, I'll confirm the ckx-imap-isUid is true, then use FetchSingleAsMime with true for isuid, all of this AFTER selecting the mailbox as desired.