Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 107d123d authored by cketti's avatar cketti
Browse files

Properly set delete policy when importing account from QR code

parent 31bd3c61
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -9,6 +9,8 @@ android {

dependencies {
    implementation(projects.core.common)
    implementation(projects.legacy.account)
    implementation(projects.legacy.common)
    implementation(projects.legacy.ui.base)
    implementation(projects.core.ui.compose.designsystem)

+6 −1
Original line number Diff line number Diff line
@@ -25,7 +25,12 @@ val qrCodeModule = module {
    factory { QrCodePayloadAdapter() }
    factory { QrCodePayloadParser(qrCodePayloadAdapter = get()) }
    factory { QrCodePayloadValidator() }
    factory { QrCodePayloadMapper(qrCodePayloadValidator = get()) }
    factory {
        QrCodePayloadMapper(
            qrCodePayloadValidator = get(),
            deletePolicyProvider = get(),
        )
    }

    factory<UseCase.QrCodePayloadReader> {
        QrCodePayloadReader(
+3 −0
Original line number Diff line number Diff line
@@ -3,6 +3,8 @@ package app.k9mail.feature.migration.qrcode.domain.entity
import app.k9mail.core.common.mail.EmailAddress
import app.k9mail.core.common.net.Hostname
import app.k9mail.core.common.net.Port
import app.k9mail.legacy.account.Account
import app.k9mail.legacy.account.Account.DeletePolicy

internal data class AccountData(
    val sequenceNumber: Int,
@@ -11,6 +13,7 @@ internal data class AccountData(
) {
    data class Account(
        val accountName: String,
        val deletePolicy: DeletePolicy,
        val incomingServer: IncomingServer,
        val outgoingServerGroups: List<OutgoingServerGroup>,
    )
+16 −0
Original line number Diff line number Diff line
package app.k9mail.feature.migration.qrcode.payload

import app.k9mail.core.common.mail.Protocols
import app.k9mail.core.common.mail.toUserEmailAddress
import app.k9mail.core.common.net.toHostname
import app.k9mail.core.common.net.toPort
import app.k9mail.feature.migration.qrcode.domain.entity.AccountData
import app.k9mail.feature.migration.qrcode.domain.entity.AccountData.IncomingServerProtocol
import app.k9mail.legacy.account.Account.DeletePolicy
import com.fsck.k9.account.DeletePolicyProvider

internal class QrCodePayloadMapper(
    private val qrCodePayloadValidator: QrCodePayloadValidator,
    private val deletePolicyProvider: DeletePolicyProvider,
) {
    fun toAccountData(data: QrCodeData): AccountData? {
        return if (qrCodePayloadValidator.isValid(data)) {
@@ -31,9 +36,11 @@ internal class QrCodePayloadMapper(
            accountName = account.incomingServer.accountName,
            identity = outgoingServerGroups.first().identities.first(),
        )
        val deletePolicy = getDeletePolicy(incomingServer.protocol)

        return AccountData.Account(
            accountName = accountName,
            deletePolicy = deletePolicy,
            incomingServer = incomingServer,
            outgoingServerGroups = outgoingServerGroups,
        )
@@ -92,4 +99,13 @@ internal class QrCodePayloadMapper(
            displayName = identity.displayName,
        )
    }

    private fun getDeletePolicy(protocol: IncomingServerProtocol): DeletePolicy {
        val accountType = when (protocol) {
            IncomingServerProtocol.Imap -> Protocols.IMAP
            IncomingServerProtocol.Pop3 -> Protocols.POP3
        }

        return deletePolicyProvider.getDeletePolicy(accountType)
    }
}
+30 −0
Original line number Diff line number Diff line
@@ -6,11 +6,13 @@ import app.k9mail.feature.migration.qrcode.domain.entity.AccountData.Identity
import app.k9mail.feature.migration.qrcode.domain.entity.AccountData.IncomingServer
import app.k9mail.feature.migration.qrcode.domain.entity.AccountData.OutgoingServer
import app.k9mail.feature.migration.qrcode.domain.entity.AccountData.OutgoingServerGroup
import app.k9mail.legacy.account.Account.DeletePolicy
import java.io.OutputStream
import org.xmlpull.v1.XmlSerializer

// TODO: This duplicates much of the code in SettingsExporter. Add an abstraction layer for the input data, so we can
//  use a single XML writer class for exporting accounts and writing QR code payloads to a settings file.
@Suppress("TooManyFunctions")
internal class XmlSettingWriter(
    private val uuidGenerator: UuidGenerator,
) {
@@ -56,12 +58,28 @@ internal class XmlSettingWriter(
        attribute(null, UUID_ATTRIBUTE, accountUuid)

        writeElement(NAME_ELEMENT, account.accountName)
        writeSettings(account)
        writeIncomingServer(account.incomingServer)
        writeOutgoingServers(account.outgoingServerGroups)

        endTag(null, ACCOUNT_ELEMENT)
    }

    private fun XmlSerializer.writeSettings(account: Account) {
        startTag(null, SETTINGS_ELEMENT)
        writeKeyValue("deletePolicy", account.deletePolicy.toSettingsFileValue())
        endTag(null, SETTINGS_ELEMENT)
    }

    private fun XmlSerializer.writeKeyValue(key: String, value: String?) {
        startTag(null, VALUE_ELEMENT)
        attribute(null, KEY_ATTRIBUTE, key)
        if (value != null) {
            text(value)
        }
        endTag(null, VALUE_ELEMENT)
    }

    private fun XmlSerializer.writeIncomingServer(incomingServer: IncomingServer) {
        startTag(null, INCOMING_SERVER_ELEMENT)
        attribute(null, TYPE_ATTRIBUTE, incomingServer.protocol.mapToSettingsString())
@@ -139,6 +157,9 @@ internal class XmlSettingWriter(
        private const val ACCOUNTS_ELEMENT = "accounts"
        private const val ACCOUNT_ELEMENT = "account"
        private const val UUID_ATTRIBUTE = "uuid"
        private const val SETTINGS_ELEMENT = "settings"
        private const val VALUE_ELEMENT = "value"
        private const val KEY_ATTRIBUTE = "key"
        private const val INCOMING_SERVER_ELEMENT = "incoming-server"
        private const val OUTGOING_SERVER_ELEMENT = "outgoing-server"
        private const val TYPE_ATTRIBUTE = "type"
@@ -154,3 +175,12 @@ internal class XmlSettingWriter(
        private const val EMAIL_ELEMENT = "email"
    }
}

private fun DeletePolicy.toSettingsFileValue(): String {
    return when (this) {
        DeletePolicy.NEVER -> "NEVER"
        DeletePolicy.SEVEN_DAYS -> error("Unsupported value")
        DeletePolicy.ON_DELETE -> "DELETE"
        DeletePolicy.MARK_AS_READ -> "MARK_AS_READ"
    }
}
Loading