JMAP: Add support for deleting messages

This commit is contained in:
cketti 2020-02-18 02:18:50 +01:00
parent 94ce631f7d
commit a2f1487ba5
3 changed files with 75 additions and 3 deletions

View file

@ -2126,7 +2126,7 @@ public class MessagingController {
String trashFolderServerId = account.getTrashFolder();
backend.deleteAllMessages(trashFolderServerId);
if (account.getExpungePolicy() == Expunge.EXPUNGE_IMMEDIATELY) {
if (account.getExpungePolicy() == Expunge.EXPUNGE_IMMEDIATELY && backend.getSupportsExpunge()) {
backend.expunge(trashFolderServerId);
}

View file

@ -0,0 +1,71 @@
package com.fsck.k9.backend.jmap
import rs.ltt.jmap.client.JmapClient
import rs.ltt.jmap.common.Request.Invocation.ResultReference
import rs.ltt.jmap.common.entity.filter.EmailFilterCondition
import rs.ltt.jmap.common.method.call.email.QueryEmailMethodCall
import rs.ltt.jmap.common.method.call.email.SetEmailMethodCall
import rs.ltt.jmap.common.method.response.email.QueryEmailMethodResponse
import rs.ltt.jmap.common.method.response.email.SetEmailMethodResponse
import timber.log.Timber
class CommandDelete(
private val jmapClient: JmapClient,
private val accountId: String
) {
fun deleteMessages(messageServerIds: List<String>) {
Timber.v("Deleting messages %s", messageServerIds)
val session = jmapClient.session.get()
val maxObjectsInSet = session.maxObjectsInSet
messageServerIds.chunked(maxObjectsInSet).forEach { emailIds ->
val setEmailCall = jmapClient.call(
SetEmailMethodCall.builder()
.accountId(accountId)
.destroy(emailIds.toTypedArray())
.build()
)
setEmailCall.getMainResponseBlocking<SetEmailMethodResponse>()
}
}
fun deleteAllMessages(folderServerId: String) {
Timber.d("Deleting all messages from %s", folderServerId)
val session = jmapClient.session.get()
val limit = session.maxObjectsInSet.coerceAtMost(MAX_CHUNK_SIZE).toLong()
do {
Timber.v("Trying to delete up to %d messages from %s", limit, folderServerId)
val multiCall = jmapClient.newMultiCall()
val queryEmailCall = multiCall.call(
QueryEmailMethodCall.builder()
.accountId(accountId)
.filter(EmailFilterCondition.builder().inMailbox(folderServerId).build())
.calculateTotal(true)
.limit(limit)
.build()
)
val setEmailCall = multiCall.call(
SetEmailMethodCall.builder()
.accountId(accountId)
.destroyReference(queryEmailCall.createResultReference(ResultReference.Path.IDS))
.build()
)
multiCall.execute()
val queryEmailResponse = queryEmailCall.getMainResponseBlocking<QueryEmailMethodResponse>()
val numberOfReturnedEmails = queryEmailResponse.ids.size
val totalNumberOfEmails = queryEmailResponse.total ?: error("Server didn't return property 'total'")
setEmailCall.getMainResponseBlocking<SetEmailMethodResponse>()
Timber.v("Deleted %d messages from %s", numberOfReturnedEmails, folderServerId)
} while (totalNumberOfEmails > numberOfReturnedEmails)
}
}

View file

@ -29,6 +29,7 @@ class JmapBackend(
private val commandRefreshFolderList = CommandRefreshFolderList(backendStorage, jmapClient, accountId)
private val commandSync = CommandSync(backendStorage, jmapClient, okHttpClient, accountId, httpAuthentication)
private val commandSetFlag = CommandSetFlag(jmapClient, accountId)
private val commandDelete = CommandDelete(jmapClient, accountId)
override val supportsSeenFlag = true
override val supportsExpunge = false
override val supportsMove = true
@ -68,11 +69,11 @@ class JmapBackend(
}
override fun deleteMessages(folderServerId: String, messageServerIds: List<String>) {
throw UnsupportedOperationException("not implemented")
commandDelete.deleteMessages(messageServerIds)
}
override fun deleteAllMessages(folderServerId: String) {
throw UnsupportedOperationException("not implemented")
commandDelete.deleteAllMessages(folderServerId)
}
override fun moveMessages(sourceFolderServerId: String, targetFolderServerId: String, messageServerIds: List<String>): Map<String, String>? {