Skip to content

Commit e274bdf

Browse files
authored
Merge pull request thunderbird#9792 from wmontwe/uplift-beta-9772-fix-imap-prefix-handling
uplift(beta): fix imap prefix handling
2 parents da4f8fe + 2221ab6 commit e274bdf

File tree

55 files changed

+644
-87
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+644
-87
lines changed

backend/api/src/main/java/com/fsck/k9/backend/api/Backend.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import com.fsck.k9.mail.Flag
55
import com.fsck.k9.mail.Message
66
import com.fsck.k9.mail.Part
77
import net.thunderbird.core.common.exception.MessagingException
8+
import net.thunderbird.feature.mail.folder.api.FolderPathDelimiter
89

910
interface Backend {
1011
val supportsFlags: Boolean
@@ -18,7 +19,7 @@ interface Backend {
1819
val isPushCapable: Boolean
1920

2021
@Throws(MessagingException::class)
21-
fun refreshFolderList()
22+
fun refreshFolderList(): FolderPathDelimiter?
2223

2324
// TODO: Add a way to cancel the sync process
2425
fun sync(folderServerId: String, syncConfig: SyncConfig, listener: SyncListener)
Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
package com.fsck.k9.backend.api
22

33
import com.fsck.k9.mail.FolderType
4+
import net.thunderbird.feature.mail.folder.api.FolderPathDelimiter
45

5-
data class FolderInfo(val serverId: String, val name: String, val type: FolderType)
6+
data class FolderInfo(
7+
val serverId: String,
8+
val name: String,
9+
val type: FolderType,
10+
val folderPathDelimiter: FolderPathDelimiter? = null,
11+
)

backend/demo/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ plugins {
66

77
dependencies {
88
api(projects.backend.api)
9+
implementation(projects.feature.mail.folder.api)
910

1011
implementation(libs.kotlinx.serialization.json)
1112

backend/demo/src/main/kotlin/app/k9mail/backend/demo/CommandRefreshFolderList.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@ package app.k9mail.backend.demo
33
import com.fsck.k9.backend.api.BackendStorage
44
import com.fsck.k9.backend.api.FolderInfo
55
import com.fsck.k9.backend.api.updateFolders
6+
import net.thunderbird.feature.mail.folder.api.FOLDER_DEFAULT_PATH_DELIMITER
7+
import net.thunderbird.feature.mail.folder.api.FolderPathDelimiter
68

79
internal class CommandRefreshFolderList(
810
private val backendStorage: BackendStorage,
911
private val demoStore: DemoStore,
1012
) {
1113

12-
fun refreshFolderList() {
14+
fun refreshFolderList(): FolderPathDelimiter? {
1315
val localFolderServerIds = backendStorage.getFolderServerIds().toSet()
1416

1517
backendStorage.updateFolders {
@@ -25,5 +27,7 @@ internal class CommandRefreshFolderList(
2527
val folderServerIdsToRemove = (localFolderServerIds - remoteFolderServerIds).toList()
2628
deleteFolders(folderServerIdsToRemove)
2729
}
30+
31+
return FOLDER_DEFAULT_PATH_DELIMITER
2832
}
2933
}

backend/demo/src/main/kotlin/app/k9mail/backend/demo/DemoBackend.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import com.fsck.k9.mail.BodyFactory
1111
import com.fsck.k9.mail.Flag
1212
import com.fsck.k9.mail.Message
1313
import com.fsck.k9.mail.Part
14+
import net.thunderbird.feature.mail.folder.api.FolderPathDelimiter
1415

1516
class DemoBackend(
1617
private val backendStorage: BackendStorage,
@@ -31,8 +32,8 @@ class DemoBackend(
3132
override val supportsFolderSubscriptions: Boolean = false
3233
override val isPushCapable: Boolean = false
3334

34-
override fun refreshFolderList() {
35-
commandRefreshFolderList.refreshFolderList()
35+
override fun refreshFolderList(): FolderPathDelimiter? {
36+
return commandRefreshFolderList.refreshFolderList()
3637
}
3738

3839
override fun sync(folderServerId: String, syncConfig: SyncConfig, listener: SyncListener) {

backend/imap/build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ dependencies {
1313
api(projects.mail.protocols.imap)
1414
api(projects.mail.protocols.smtp)
1515

16+
implementation(projects.feature.mail.folder.api)
17+
1618
implementation(libs.kotlinx.coroutines.core)
1719

1820
testImplementation(projects.core.logging.testing)

backend/imap/src/main/java/com/fsck/k9/backend/imap/CommandRefreshFolderList.kt

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,32 +6,49 @@ import com.fsck.k9.backend.api.updateFolders
66
import com.fsck.k9.mail.FolderType
77
import com.fsck.k9.mail.store.imap.FolderListItem
88
import com.fsck.k9.mail.store.imap.ImapStore
9+
import net.thunderbird.core.logging.Logger
10+
import net.thunderbird.core.logging.legacy.Log
11+
import net.thunderbird.feature.mail.folder.api.FolderPathDelimiter
12+
13+
private const val TAG = "CommandRefreshFolderList"
914

1015
internal class CommandRefreshFolderList(
1116
private val backendStorage: BackendStorage,
1217
private val imapStore: ImapStore,
18+
private val logger: Logger = Log,
1319
) {
14-
fun refreshFolderList() {
15-
// TODO: Start using the proper server ID.
16-
// For now we still use the old server ID format (decoded, with prefix removed).
17-
val foldersOnServer = imapStore.getFolders().toLegacyFolderList()
20+
21+
private val LegacyFolderListItem.normalizedServerId: String
22+
get() = imapStore.combinedPrefix?.let {
23+
serverId.removePrefix(prefix = it)
24+
} ?: serverId
25+
26+
fun refreshFolderList(): FolderPathDelimiter? {
27+
logger.verbose(TAG) { "refreshFolderList() called" }
28+
val folders = imapStore.getFolders()
29+
val folderPathDelimiter = folders.firstOrNull { it.folderPathDelimiter != null }?.folderPathDelimiter
30+
val foldersOnServer = folders.toLegacyFolderList()
1831
val oldFolderServerIds = backendStorage.getFolderServerIds()
1932

2033
backendStorage.updateFolders {
2134
val foldersToCreate = mutableListOf<FolderInfo>()
2235
for (folder in foldersOnServer) {
23-
if (folder.serverId !in oldFolderServerIds) {
24-
foldersToCreate.add(FolderInfo(folder.serverId, folder.name, folder.type))
36+
if (folder.normalizedServerId !in oldFolderServerIds) {
37+
foldersToCreate.add(FolderInfo(folder.normalizedServerId, folder.name, folder.type))
2538
} else {
26-
changeFolder(folder.serverId, folder.name, folder.type)
39+
changeFolder(folder.normalizedServerId, folder.name, folder.type)
2740
}
2841
}
42+
43+
logger.verbose(TAG) { "refreshFolderList: foldersToCreate = $foldersToCreate" }
2944
createFolders(foldersToCreate)
3045

31-
val newFolderServerIds = foldersOnServer.map { it.serverId }
46+
val newFolderServerIds = foldersOnServer.map { it.normalizedServerId }
3247
val removedFolderServerIds = oldFolderServerIds - newFolderServerIds
48+
logger.verbose(TAG) { "refreshFolderList: folders to remove = $removedFolderServerIds" }
3349
deleteFolders(removedFolderServerIds)
3450
}
51+
return folderPathDelimiter
3552
}
3653
}
3754

backend/imap/src/main/java/com/fsck/k9/backend/imap/ImapBackend.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import com.fsck.k9.mail.power.PowerManager
1414
import com.fsck.k9.mail.store.imap.IdleRefreshManager
1515
import com.fsck.k9.mail.store.imap.ImapStore
1616
import com.fsck.k9.mail.transport.smtp.SmtpTransport
17+
import net.thunderbird.feature.mail.folder.api.FolderPathDelimiter
1718

1819
class ImapBackend(
1920
private val accountName: String,
@@ -48,8 +49,8 @@ class ImapBackend(
4849
override val supportsFolderSubscriptions = true
4950
override val isPushCapable = true
5051

51-
override fun refreshFolderList() {
52-
commandRefreshFolderList.refreshFolderList()
52+
override fun refreshFolderList(): FolderPathDelimiter? {
53+
return commandRefreshFolderList.refreshFolderList()
5354
}
5455

5556
override fun sync(folderServerId: String, syncConfig: SyncConfig, listener: SyncListener) {

backend/imap/src/test/java/com/fsck/k9/backend/imap/TestImapStore.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ import com.fsck.k9.mail.store.imap.ImapStore
88
class TestImapStore : ImapStore {
99
private val folders = mutableMapOf<String, ImapFolder>()
1010

11+
override val combinedPrefix: String?
12+
get() = throw UnsupportedOperationException("not implemented")
13+
1114
fun addFolder(serverId: String): TestImapFolder {
1215
require(!folders.containsKey(serverId)) { "Folder '$serverId' already exists" }
1316

@@ -44,4 +47,8 @@ class TestImapStore : ImapStore {
4447
override fun closeAllConnections() {
4548
throw UnsupportedOperationException("not implemented")
4649
}
50+
51+
override fun fetchImapPrefix() {
52+
throw UnsupportedOperationException("not implemented")
53+
}
4754
}

backend/imap/src/test/kotlin/net/thunderbird/backend/imap/ImapRemoteFolderCreatorTest.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,9 @@ class ImapRemoteFolderCreatorTest {
122122
private class FakeImapStore(
123123
private val folder: TestImapFolder,
124124
) : ImapStore {
125+
override val combinedPrefix: String?
126+
get() = throw NotImplementedError("combinedPrefix not implemented")
127+
125128
override fun checkSettings() {
126129
throw NotImplementedError("checkSettings not implemented")
127130
}
@@ -135,4 +138,8 @@ private class FakeImapStore(
135138
override fun closeAllConnections() {
136139
throw NotImplementedError("closeAllConnections not implemented")
137140
}
141+
142+
override fun fetchImapPrefix() {
143+
throw NotImplementedError("fetchImapPrefix not implemented")
144+
}
138145
}

0 commit comments

Comments
 (0)