Repository: thundernest/k-9
Issue: Push folder configuration setting not accepted / persisted

I'm using v5.802 with two IMAP accounts on two different servers. Both servers support IMAP IDLE.
With the first account, Push is working perfectly. But with the second account, Push is not working, and the configuration always resets itself automatically.

Here are the steps to reproduce (I'm using the German UI):
1. Choose menu..Einstellungen
2. Choose the affected account for "Kontoeinstellungen"
3. Choose "E-Mails abrufen"
4. Choose "Push-Ordner" - it was set to "Keine Ordner" - select "Nur Hauptordner"
   Result: In the menu, it now shows correctly "Push-Ordner" "Nur Hauptordner"
5. Exit the menu
6. Choose again "E-Mails abrufen"
   Result: "Push-Ordner" has been reset to "Keine Ordner"

**Environment (please complete the following information):**
 - K-9 Mail version: v5.802
 - Android version: 8.0.0
 - Device: Samsung Galaxy A5 (2017)
 - Account type: IMAP (twice)


Changed files:
mail/protocols/imap/src/main/java/com/fsck/k9/mail/store/imap/RealImapFolderIdler.kt
mail/protocols/imap/src/test/java/com/fsck/k9/mail/store/imap/RealImapFolderIdlerTest.kt

diff --git a/mail/protocols/imap/src/main/java/com/fsck/k9/mail/store/imap/RealImapFolderIdler.kt b/mail/protocols/imap/src/main/java/com/fsck/k9/mail/store/imap/RealImapFolderIdler.kt
index 629c33724..c1c6d711a 100644
--- a/mail/protocols/imap/src/main/java/com/fsck/k9/mail/store/imap/RealImapFolderIdler.kt
+++ b/mail/protocols/imap/src/main/java/com/fsck/k9/mail/store/imap/RealImapFolderIdler.kt
@@ -91,13 +91,25 @@ internal class RealImapFolderIdler(
                 idleSent = true
             }
 
-            val initialResponse = connection.readResponse()
-            if (!initialResponse.isContinuationRequested) {
-                Timber.w("%s.idle(): Received something other than a continuation response", logTag)
-                return IdleResult.NOT_SUPPORTED
-            }
+            var receivedRelevantResponse = false
+            do {
+                val response = connection.readResponse()
+                if (response.tag == tag) {
+                    Timber.w("%s.idle(): IDLE command completed without a continuation request response", logTag)
+                    return IdleResult.NOT_SUPPORTED
+                } else if (response.isRelevant) {
+                    receivedRelevantResponse = true
+                }
+            } while (!response.isContinuationRequested)
 
-            connection.setSocketIdleReadTimeout()
+            if (receivedRelevantResponse) {
+                Timber.v("%s.idle(): Received a relevant untagged response right after sending IDLE command", logTag)
+                result = IdleResult.SYNC
+                stopIdle = true
+                sendDone()
+            } else {
+                connection.setSocketIdleReadTimeout()
+            }
 
             var response: ImapResponse
             do {
diff --git a/mail/protocols/imap/src/test/java/com/fsck/k9/mail/store/imap/RealImapFolderIdlerTest.kt b/mail/protocols/imap/src/test/java/com/fsck/k9/mail/store/imap/RealImapFolderIdlerTest.kt
index 871c58491..fc13a7a5f 100644
--- a/mail/protocols/imap/src/test/java/com/fsck/k9/mail/store/imap/RealImapFolderIdlerTest.kt
+++ b/mail/protocols/imap/src/test/java/com/fsck/k9/mail/store/imap/RealImapFolderIdlerTest.kt
@@ -294,6 +294,47 @@ class RealImapFolderIdlerTest {
         latch.awaitWithTimeout()
         assertThat(imapFolder.isOpen).isFalse()
     }
+
+    @Test
+    fun `irrelevant untagged response to IDLE command before continuation request`() {
+        val latch = CountDownLatch(1)
+
+        thread {
+            val idleResult = idler.idle()
+
+            assertThat(idleResult).isEqualTo(IdleResult.STOPPED)
+            latch.countDown()
+        }
+
+        imapConnection.waitForCommand("IDLE")
+        imapConnection.enqueueUntaggedServerResponse("OK irrelevant")
+        imapConnection.enqueueContinuationServerResponse()
+
+        wakeLock.waitForRelease()
+        idler.stop()
+        imapConnection.waitForCommand("DONE")
+        imapConnection.enqueueTaggedServerResponse("OK")
+        latch.awaitWithTimeout()
+    }
+
+    @Test
+    fun `relevant untagged response to IDLE command before continuation request`() {
+        val latch = CountDownLatch(1)
+
+        thread {
+            val idleResult = idler.idle()
+
+            assertThat(idleResult).isEqualTo(IdleResult.SYNC)
+            latch.countDown()
+        }
+
+        imapConnection.waitForCommand("IDLE")
+        imapConnection.enqueueUntaggedServerResponse("1 EXISTS")
+        imapConnection.enqueueContinuationServerResponse()
+        imapConnection.waitForCommand("DONE")
+        imapConnection.enqueueTaggedServerResponse("OK")
+        latch.awaitWithTimeout()
+    }
 }
 
 private fun CountDownLatch.awaitWithTimeout() {