Archived Forum Post

Index of archived forum posts

Question:

IMAP get UID results in 0

Aug 22 '12 at 04:24

Goodday,

since we installed Chilkat IMAP v9.3.2 the method email.GetHeaderField("ckx-imap-uid") returns an empty string. Also the (new?) method email.GetImapUID returns 1, so this is probably the index that is returned.

How do I retrieve the UID as before ?

We do the following :

  1. messageset = imap.search("ALL",1)
  2. bundle = imap.fetchbundle(messageset)
  3. email = bundle.getemail(index)

  4. UID_string = email.getheaderfield("ckx-imap-uid") < this results in an empty string

  5. UID_num = email.getimapUID < this results in 1, thus this is the index

Answer

I ran the same test, but everything works as expected: The ckx-imap-uid header is present, and the UID_string is returned as expected. To verify that you are using v9.3.2, examine the contents of the email.LastErrorText property after calling email.getHeaderField. Make sure the "DllDate" line within the LastErrorText shows a date from August 2012.


Answer

Just tested both methods, followed by lasterrortext :

email.getheaderfield("ckx-imap-uid")

ChilkatLog: GetHeaderField:

DllDate: Aug  5 2012
Architecture: Little Endian; 32-bit
Language: ActiveX
VerboseLogging: 0
Header field does not exist
fieldName: ckx-imap-uid

--GetHeaderField --ChilkatLog

email.getimapuid

ChilkatLog: GetImapUid:

DllDate: Aug  5 2012
Architecture: Little Endian; 32-bit
Language: ActiveX
VerboseLogging: 0
No IMAP UID found within email object.

--GetImapUid --ChilkatLog


Answer

UPDATE :

This works :

  1. bundle = IMAP.FetchHeaders(MessageSet)
  2. email = bundle.GetEmail(index)
  3. UID = email.GetImapUid

This doesn't

  1. bundle = IMAP.FetchBundle(MessageSet)
  2. email = bundle.GetEmail(index)
  3. UID = email.GetImapUid

In v9.3.1 the UID was available after fetchbundle


Answer

I found the cause of the problem. I was testing in C++, but the problem only occurs with the ActiveX. There is a reason the "ckx-*" headers are not available, and it's due to performance and other issues that are specific to the ActiveX. In the non-ActiveX implementations, a pointer (reference) to an email object can simply be added to a bundle object. In other words, the bundle object takes ownership of the email object.

However, w/ the ActiveX it's not possible. Inserting an email into a bundle object can only be done by passing the serialized email (i.e. the MIME source) to the bundle, which then loads the MIME into an internal email object such that the bundle now contains a copy of the email object.

Here's how FetchBundle worked internally before:
For each email to be downloaded:
1) The MIME is downloaded from the IMAP server.
2) The MIME is loaded into an email object. Any PKCS7 security wrappings are unwrapped (causing email object properties to be set), and the "ckx-*" headers are added to the email.
3) Given that it's not possible to have the returned ChilkatEmailBundle2 object take control of the email object, we must re-compose the MIME from the email object representation, and pass the MIME into the ChilkatEmailBundle2.
4) The ChilkatEmailBundle2 receives the MIME and loads it into a new instance of an email object, which can then be accessed by the application via the ChilkatEmailBundle2.GetEmail(index) method.

There are two big problems here:
1) Information about any digital signatures or encryption is lost. These are properties in the email object that are set when loaded from MIME. This information was lost in step #3 above.
2) It's very inefficient -- the MIME is being parsed into an email object, recomposed, then parsed again.

The newer version takes a lazy approach to solve both (1) and (2) FetchBundle simply passes the MIME as-is to the ChilkatEmailBundle2, and the ChilkatEmailBundle2 simply saves the MIME (internally in-memory) without any interpretation. So.. if for example, 100 emails are downloaded, the FetchBundle will not have parsed, re-composed, and re-parsed all 100. Nothing is parsed and the MIME is simply stored (in-memory) within the ChilkatEmailBundle2 object. It is at the point of accessing the email object from the bundle that the MIME is parsed and the email object is returned. Given that this is the 1st parsing of the MIME, the email object properties regarding digital signatures and encryption will be correct. Also, the ChilkatEmailBundle2 will now keep a reference to the email object so that it's not re-parsed if the email is accessed again. Unfortunately, the unintended side-effect is that the "ckx-*" headers are not available.

Fixing this side-effect is something that can be considered in the future, but unfortunately not at this moment.

The solution for now is to not use FetchBundle. Instead, write a loop that iterates over each email in the message set and fetches it separately. You should find the "ckx-*" headers present when doing it this way.


Answer

OK thanks. I need to go and make some changes then ...

Bundle = IMAP.FetchHeaders(MessageSet)

Email = Bundle.Getmail(index)

UID = Email.GetImapUID

Email = IMAP.FetchSingle(UID,1)

Should do the trick

Or even "better"

UID = MessageSet.GetID(index)

Email = IMAP.FetchSingle(UID,1)