spring-integrationexchange-serverimap

Exchange server doesn't accept store command without explictely selecting the inbox


I have a ImapMailReceiver implementation to receive the emails from remote IMAP server, which works fine with any IMAP servers we tested so far. Nevertheless, one of the Exchange (2016) servers we have for our tests seems to not like the IMAP commands being sent to it while fetching the emails. Here is the list of commands, according to debug log, which are sent (without the auth part):

A3 LIST "" INBOX
* LIST (\Marked \HasChildren) "/" INBOX
A3 OK LIST completed.
A4 EXAMINE INBOX
* 15 EXISTS
* 0 RECENT
* FLAGS (\Seen \Answered \Flagged \Deleted \Draft $MDNSent)
* OK [PERMANENTFLAGS ()] Permanent flags
* OK [UIDVALIDITY 14] UIDVALIDITY value
* OK [UIDNEXT 33765] The next unique identifier value
A4 OK [READ-ONLY] EXAMINE completed.
A5 SEARCH NOT (FLAGGED) ALL
* SEARCH 1 6 7 9 10 11 13 14 15
A5 OK SEARCH completed.
A6 FETCH 1,6:7,9:11,13:15 (ENVELOPE INTERNALDATE RFC822.SIZE FLAGS BODYSTRUCTURE)
...
A6 OK FETCH completed.
A7 STORE 1 +FLAGS (\Flagged)
A7 NO Command received in Invalid state

As you can see it fails on the last command while setting the flag. Now, if I add the

SELECT INBOX

and then

A7 STORE 1 +FLAGS (\Flagged)

Everything works as expected. Apparently it's a weird Exchange server behaviour, but I wonder how can we fix the issue, by maybe somehow defining the list of commands being sent to server?


Solution

  • The AbstractMailReceiver has to be registered in the application context as a bean. It has a logic in its onInit():

    @Override
    protected void onInit() {
        super.onInit();
        this.folderOpenMode = Folder.READ_WRITE;
        this.evaluationContext = ExpressionUtils.createStandardEvaluationContext(getBeanFactory());
    }
    

    This one is called by the BeanFactory for the InitializingBean hook. I'm not sure why the logic is like that, but I probably will into making this option modifiable from the target project.

    Plus it looks like there is indeed a bug in Java DSL for mail where we don't initialize internally created ImapMailReceiver:

    public static ImapIdleChannelAdapterSpec imapIdleAdapter() {
        return new ImapIdleChannelAdapterSpec(new ImapMailReceiver());
    }
    

    in opposed to:

    public static ImapIdleChannelAdapterSpec imapIdleAdapter(ImapMailReceiver imapMailReceiver) {
        return new ImapIdleChannelAdapterSpec(imapMailReceiver, true);
    }
    

    where it's up to you to register it as a bean.