Using the ImapIdleChannelAdapter with a GMail account will only receive and process the first email. When I send the second email it will not be received. For testing purposes I've reproduced this behaviour with the Spring Integration basic mail sample.
Steps to reproduce:
- Create GMail account, activate IMAP access, delete all messages (to start with an empty inbox)
- Clone Spring Integration sample from git://git.springsource.org/spring-integration/samples.git
- Use sample project "basic/mail"
- Modify gmail-imap-idle-config.xml to contain the correct IMAP username/password
- Start GmailInboundImapIdleAdapterTestApp
- Send first test mail
- Watch console output which shows that the test mail is received
- Send second test mail
- Watch console which shows nothing :-(
Here ist the console output:
Code:
DEBUG: org.springframework.integration.mail.ImapIdleChannelAdapter - waiting for mail
INFO : org.springframework.integration.mail.ImapIdleChannelAdapter - started customAdapter
DEBUG: org.springframework.integration.mail.ImapMailReceiver - connecting to store [imaps://xxx@yyy.de:*****@imap.gmail.com:993/inbox]
DEBUG: org.springframework.integration.mail.ImapMailReceiver - opening folder [imaps://xxx@yyy.de:*****@imap.gmail.com:993/inbox]
INFO : org.springframework.integration.mail.ImapMailReceiver - attempting to receive mail from folder [INBOX]
DEBUG: org.springframework.integration.mail.ImapMailReceiver - This email server does not support RECENT flag, but it does support USER flags which will be used to prevent duplicates during email fetch.
DEBUG: org.springframework.integration.mail.ImapMailReceiver - found 1 new messages
DEBUG: org.springframework.integration.mail.ImapMailReceiver - Recieved 1 messages
DEBUG: org.springframework.integration.mail.ImapMailReceiver - USER flags are supported by this mail server. Flagging message with 'spring-integration-mail-adapter' user flag
DEBUG: org.springframework.integration.mail.ImapIdleChannelAdapter - received 1 mail messages
INFO : org.springframework.integration.samples.mail.imapidle.GmailInboundImapIdleAdapterTestApp - Message: [Payload=javax.mail.internet.MimeMessage@435a3a][Headers={timestamp=1314963028427, id=ca7f2b38-ee03-4321-b237-a704a29b5c6f}]
I've analyzed this a little bit further. What I can see is the following.
When GmailInboundImapIdleAdapterTestApp starts there are 4 threads running:
- task-scheduler-1
- task-scheduler-2
- SimpleAsyncTaskExecutor-1
- DestroyJavaVM
Using the debugger I can see that the SimpleAsyncTaskExecutor-1 is doing the IMAP IDLE command. Inside ImapMailReceiver.waitForNewMessages() it's calling imapFolder.idle(). When the first mail arrives the idle() call returns and the mail is received and further processed. Everything is fine up to here.
But afterwards there are only 3 threads remaining:
- task-scheduler-1
- task-scheduler-2
- DestroyJavaVM
Using the debugger I can see that there is no thread waiting in the idle() call anymore!?
I've tried to understand the logic behind this and from my understanding the idea is, that the task which does the IMAP IDLE should receive the mail and afterwards schedules itself to run again. The code for this is inside ImapIdleChannelAdapter.doStart()
Code:
...
public void run() {
try {
idleTask.run();
if (mailReceiver.getFolder().isOpen()){
if (logger.isDebugEnabled()){
logger.debug("Task completed successfully. Re-scheduling it again right away");
}
scheduler.schedule(this, new Date());
}
}
catch (IllegalStateException e) { //run again after a delay
logger.warn("Failed to execute IDLE task. Will atempt to resubmit in " + reconnectDelay + " milliseconds", e);
scheduler.schedule(this, new Date(System.currentTimeMillis() + reconnectDelay));
}
}
...
But after receiving the first mail the check for mailReceiver.getFolder().isOpen() returns false and so re-scheduling is stopped.
Is this a bug or a misconfiguration?
Thanks.
Greetings
Olli