Search code examples
indyindy10

What belongs in AExpectedResponses parameter to tidimap4.SendCmd?


The slightly out of date documentation for Indy 10 does not explain what belongs in the AExpectedResponses parameter for the SendCmd function in the TIdImap4 class. But even after looking through the source code for TIdImap4 to see how SendCmd is used internally and searching on google, I'm not getting a consistent picture of when to include items from the responses and/or results section of the IMAP RFCs and/or leave that parameter blank. Can anyone explain a little bit how this parameter is used and what should be in it?

Or, perhaps, it would help to use a concrete example:

I am implementing UID MOVE for servers that support that RFC... so so far I have:

IMAP.SendCmd('UID MOVE '+uidList.CommaText +' '+destFolder,[],true);

And from reading the RFC (6851), there are some hints about the expected responses ("nothing specific") and result (OK, NO, BAD).

3.1.  MOVE Command
   Arguments: sequence set
              mailbox name
   Responses: no specific responses for this command
   Result: OK - move completed
           NO - move error: can't move those messages or to that name
           BAD - command unknown or arguments invalid

but there's also a note later on that there may be untagged "unrelated" responses in relation to this command before the OK:

Note that the server may send unrelated EXPUNGE responses as well, if
any happen to have been expunged at the same time; this is normal
IMAP operation.

And the RFC gives an example of such:

   C: a UID MOVE 42:69 foo
   S: * OK [COPYUID 432432 42:69 1202:1229]
   S: * 22 EXPUNGE
   S: (more expunges)
   S: a OK Done

It seems fairly but not exactly the same as what I'm really seeing connecting to gmail, which is basically, the same with no untagged OK, and the addition of an untagged EXISTS command (which I believe is included to support the UIDPLUS extension support):

Sent 6/25/2016 4:08:04 PM: C246 UID MOVE 179,180,181,183,184,198,199 [Gmail]/Trash<EOL>
Recv 6/25/2016 4:08:04 PM: * 48 EXPUNGE<EOL>
Recv 6/25/2016 4:08:04 PM: * 48 EXPUNGE<EOL>
Recv 6/25/2016 4:08:04 PM: * 48 EXPUNGE<EOL>
Recv 6/25/2016 4:08:04 PM: * 49 EXPUNGE<EOL>
Recv 6/25/2016 4:08:04 PM: * 49 EXPUNGE<EOL>
Recv 6/25/2016 4:08:04 PM: * 54 EXPUNGE<EOL>
Recv 6/25/2016 4:08:04 PM: * 54 EXPUNGE<EOL>
Recv 6/25/2016 4:08:04 PM: * 53 EXISTS<EOL>
Recv 6/25/2016 4:08:04 PM: C246 OK [COPYUID 2 179:181,183:184,198:199 80,79,78,77,76,75,74] (Success)<EOL>

so here I'm seeing untagged responses of "EXPUNGE" and "EXISTS" and apparently "OK" could be sent as well, before the resulting "OK".

So I'm a little fuzzy on whether what actually belongs in AExpectedResponses is [EXPUNGE, EXISTS, OK], nothing [], the results [OK, NO, BAD] or something else entirely. Thank you.


Solution

  • When parsing the lines of a response, any line that does not begin with a word in the AExpectedResponses list is not treated as part of the response itself (unless the line begins with the same tag as the command, of course, since that terminates the response). The line is stored in the TIdReplyIMAP4(LastCmdResult).Extra property instead of the LastCmdResult.Text property, if stored at all.

    In your UID MOVE example response:

    If you include 'OK' in the AExpectedResponses list then the * OK [COPYUID 432432 42:69 1202:1229] line (if received) will be saved in the LastCmdResult.Text property, otherwise it will be saved in the TIdReplyIMAP4(LastCmdResult).Extra property instead.

    If you include 'EXPUNGE' in the AExpectedResponses list then the * <msgid> EXPUNGE lines (if received) will be saved in the LastCmdResult.Text property, otherwise they will be saved in the TIdReplyIMAP4(LastCmdResult).Extra property instead.

    If you include 'EXISTS' in the AExpectedResponses list then the * <msgid> EXISTS lines (if received) will be saved in the LastCmdResult.Text property, otherwise they will be saved in the TIdReplyIMAP4(LastCmdResult).Extra property instead.

    Basically, whatever you specify in AExpectedResponses will be saved in TIdReplyIMAP4.Text, and anything else will be either discarded or saved in TIdReplyIMAP4.Extra instead.

    Or at least that is a simplified explanation. TIdIMAP4 is a very complex component, mainly because IMAP is actually an asynchronous protocol, but TIdIMAP4 is a synchronous component, so its response parser employs several rules to handle cases when unexpected unsolicited responses arrive when not expected, and it doesn't want to just discard them. So you kind of have to pay attention to the Extra property (which TIdIMAP4 doesn't really do internally, though it probably should). Maybe in Indy 11, TIdIMAP4 will be redesigned to separate response handling to a separate thread or an event-based model, but that is not likely to happen in Indy 10.