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

Commit b2eb9fbb authored by cketti's avatar cketti
Browse files

Add `ReplyActionStrategy` to figure out which reply actions are available to the user

parent 6be40510
Loading
Loading
Loading
Loading
+36 −0
Original line number Diff line number Diff line
package com.fsck.k9.message

import com.fsck.k9.Account
import com.fsck.k9.helper.ReplyToParser
import com.fsck.k9.mail.Message

/**
 * Figures out which reply actions are available to the user.
 */
class ReplyActionStrategy(private val replyRoParser: ReplyToParser) {
    fun getReplyActions(account: Account, message: Message): ReplyActions {
        val recipientsToReplyTo = replyRoParser.getRecipientsToReplyTo(message, account)
        val recipientsToReplyAllTo = replyRoParser.getRecipientsToReplyAllTo(message, account)

        val replyToAllCount = recipientsToReplyAllTo.to.size + recipientsToReplyAllTo.cc.size
        return if (replyToAllCount <= 1) {
            if (recipientsToReplyTo.to.isEmpty()) {
                ReplyActions(defaultAction = null)
            } else {
                ReplyActions(defaultAction = ReplyAction.REPLY)
            }
        } else {
            ReplyActions(defaultAction = ReplyAction.REPLY_ALL, additionalActions = listOf(ReplyAction.REPLY))
        }
    }
}

data class ReplyActions(
    val defaultAction: ReplyAction?,
    val additionalActions: List<ReplyAction> = emptyList()
)

enum class ReplyAction {
    REPLY,
    REPLY_ALL
}
+111 −0
Original line number Diff line number Diff line
package com.fsck.k9.message

import com.fsck.k9.Account
import com.fsck.k9.Identity
import com.fsck.k9.helper.ReplyToParser
import com.fsck.k9.mail.buildMessage
import com.google.common.truth.Truth.assertThat
import org.junit.Test

private const val IDENTITY_EMAIL_ADDRESS = "myself@domain.example"

class ReplyActionStrategyTest {
    private val account = createAccount()
    private val replyActionStrategy = ReplyActionStrategy(ReplyToParser())

    @Test
    fun `message sent to only our identity`() {
        val message = buildMessage {
            header("From", "sender@domain.example")
            header("To", IDENTITY_EMAIL_ADDRESS)
        }

        val replyActions = replyActionStrategy.getReplyActions(account, message)

        assertThat(replyActions.defaultAction).isEqualTo(ReplyAction.REPLY)
        assertThat(replyActions.additionalActions).isEmpty()
    }

    @Test
    fun `message sent to our identity and others`() {
        val message = buildMessage {
            header("From", "sender@domain.example")
            header("To", "$IDENTITY_EMAIL_ADDRESS, other@domain.example")
        }

        val replyActions = replyActionStrategy.getReplyActions(account, message)

        assertThat(replyActions.defaultAction).isEqualTo(ReplyAction.REPLY_ALL)
        assertThat(replyActions.additionalActions).containsExactly(ReplyAction.REPLY)
    }

    @Test
    fun `message sent to our identity and others (CC)`() {
        val message = buildMessage {
            header("From", "sender@domain.example")
            header("Cc", "$IDENTITY_EMAIL_ADDRESS, other@domain.example")
        }

        val replyActions = replyActionStrategy.getReplyActions(account, message)

        assertThat(replyActions.defaultAction).isEqualTo(ReplyAction.REPLY_ALL)
        assertThat(replyActions.additionalActions).containsExactly(ReplyAction.REPLY)
    }

    @Test
    fun `message sent to our identity and others (To+CC)`() {
        val message = buildMessage {
            header("From", "sender@domain.example")
            header("To", IDENTITY_EMAIL_ADDRESS)
            header("Cc", "other@domain.example")
        }

        val replyActions = replyActionStrategy.getReplyActions(account, message)

        assertThat(replyActions.defaultAction).isEqualTo(ReplyAction.REPLY_ALL)
        assertThat(replyActions.additionalActions).containsExactly(ReplyAction.REPLY)
    }

    @Test
    fun `message sent to our identity and others (CC+To)`() {
        val message = buildMessage {
            header("From", "sender@domain.example")
            header("To", "other@domain.example")
            header("Cc", IDENTITY_EMAIL_ADDRESS)
        }

        val replyActions = replyActionStrategy.getReplyActions(account, message)

        assertThat(replyActions.defaultAction).isEqualTo(ReplyAction.REPLY_ALL)
        assertThat(replyActions.additionalActions).containsExactly(ReplyAction.REPLY)
    }

    @Test
    fun `message where neither sender nor recipient addresses belong to account`() {
        val message = buildMessage {
            header("From", "sender@domain.example")
            header("To", "recipient@domain.example")
        }

        val replyActions = replyActionStrategy.getReplyActions(account, message)

        assertThat(replyActions.defaultAction).isEqualTo(ReplyAction.REPLY_ALL)
        assertThat(replyActions.additionalActions).containsExactly(ReplyAction.REPLY)
    }

    @Test
    fun `message without any sender or recipient headers`() {
        val message = buildMessage {}

        val replyActions = replyActionStrategy.getReplyActions(account, message)

        assertThat(replyActions.defaultAction).isNull()
        assertThat(replyActions.additionalActions).isEmpty()
    }

    private fun createAccount(): Account {
        return Account("00000000-0000-4000-0000-000000000000").apply {
            identities += Identity(name = "Myself", email = IDENTITY_EMAIL_ADDRESS)
        }
    }
}