Search code examples
spring-integrationjakarta-mailimap

ImapIdleChannelAdapter doesn't reconnect to IDLE after timeout


I use ImapIdleChannelAdapter (6.1.0) for retrieving messages from exchange v4 email service and have noticed that after some period of time approximately 30m probably because IDLE connection lasts 30m usually, my channel loses connection as expected and doesn't reconnnect properly. I have very similar to defaults settings with .shouldReconnectAutomatically(true) which is actually default true also though. I thought this is enough to rely on framework to reconnect or I'm missing the point somewhere? Not much information have found on it.

Spec and flow intialization:

...
       private IntegrationFlowContext flowContext; 
...
        ImapIdleChannelAdapterSpec imapIdleChannelAdapterSpec = Mail.imapIdleAdapter(url)
            .javaMailProperties(javaMailProperties)
            .javaMailAuthenticator(new Authenticator() {
                @Override
                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication(username, password);
                }
            })
            .shouldReconnectAutomatically(true)
            .shouldMarkMessagesAsRead(false)
            .autoCloseFolder(false)
            .shouldDeleteMessages(false);

        StandardIntegrationFlow integrationFlow = IntegrationFlow.from(imapIdleChannelAdapterSpec)
            .log(LoggingHandler.Level.DEBUG)
            .handle(...)
            .get();

        flowContext.registration(integrationFlow)
            .id("ImapFor" + imap.getUsername())
            .useFlowIdAsPrefix()
            .register();

Solution

  • I could reproduce the problem against GMail, but I didn't get any lost connection. Perhaps GMail just doesn't time it out.

    My problem was about a race condition with TaskScheduler and its single thread in the pool of an auto-configured by Spring Boot ThreadPoolTaskScheduler: the ImapIdleChannelAdapter schedules a ReceivingTask which enters into an IDLE state and blocked. That ReceivingTask calls a ImapMailReceiver which schedules an IdleCanceler task. And since we are blocked in the idle() state, we don't let another task to be performed in the scheduler.

    I fixed it like this in the application.properties:

    spring.task.scheduling.pool.size=10 
    

    It is not clear, thought, from your question if you use Spring Boot or not.