Fix IMAP race condition around idle()

`IMAPFolder.idle()` by default keeps idle-ing after each response.
We don't need that, because we want to fetch the new mails immediately (over the same connection).
To make `idle()` not keep on going, we called
`folder.isOpen()` which in most cases makes `idle()` stop by calling `noop()`
internally (to keep the connection alive) which leads to the current
`idle()`-call being canceled.

The problem this commits addresses is that the call to `noop()` only
happens if there were no calls in the last second.
There is a check for that in `com.sun.mail.imap.IMAPFolder.keepConnectionAlive`.
So if a new message appears less then a second after idle started, we will miss it.

This new way interrupts `idle()` more often than before, e.g. when there
is an expunge-message (i.e. a message was deleted), which we don't care about.
But the subsequent `receive()` in IdleTask will simply get no
messages and then turn around and start idle-ing again.

**Cherry-pick to `5.3.x` & `master`**
This commit is contained in:
Alexander Pinske
2021-04-04 21:54:18 +02:00
committed by Artem Bilan
parent 3f0c57894b
commit 07a6fb3a9a
2 changed files with 7 additions and 31 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -91,6 +91,7 @@ import com.sun.mail.imap.IMAPFolder;
* @author Oleg Zhurakousky
* @author Gary Russell
* @author Artem Bilan
* @author Alexander Pinske
*/
@SpringJUnitConfig
@ContextConfiguration(
@@ -607,7 +608,7 @@ public class ImapMailReceiverTests {
Thread.sleep(300);
shouldFindMessagesCounter.set(1);
return null;
}).given(folder).idle();
}).given(folder).idle(true);
adapter.start();
@@ -667,7 +668,7 @@ public class ImapMailReceiverTests {
idles.countDown();
Thread.sleep(500);
return null;
}).given(folder).idle();
}).given(folder).idle(true);
adapter.start();