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

Commit b186304a authored by Fahim Salam Chowdhury's avatar Fahim Salam Chowdhury 👽
Browse files

Merge branch '6584-Add_yahoo_account_support' into 'main'

6584-Add_yahoo_account_support in Mail app

See merge request !146
parents 3f161e2f fa44d63c
Loading
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -2,6 +2,12 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission
        android:name="android.permission.AUTHENTICATE_ACCOUNTS"
        android:maxSdkVersion="22" />
    <uses-permission
        android:name="android.permission.GET_ACCOUNTS"
        android:maxSdkVersion="22" />
    <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />

</manifest>
+18 −13
Original line number Diff line number Diff line
@@ -32,30 +32,35 @@ object OsAccountManagerUtil {
    fun isSyncEnable(context: Context, email: String): Boolean {
        val accountManager = AccountManager.get(context)

        val murenaAccounts = accountManager.getAccountsByType(AccountManagerConstants.EELO_ACCOUNT_TYPE)
        var syncEnable = isSyncEnable(accountManager, murenaAccounts, email)
        if (syncEnable.isAccountFound()) {
            return syncEnable.getStatus()
        }
        var syncStatus = true

        val googleAccounts = accountManager.getAccountsByType(AccountManagerConstants.GOOGLE_ACCOUNT_TYPE)
        syncEnable = isSyncEnable(accountManager, googleAccounts, email)
        AccountManagerConstants.ALL_ACCOUNT_TYPES.forEach {
            val accounts = accountManager.getAccountsByType(it)
            val syncEnable = isSyncEnable(accountManager, accounts, email)
            if (syncEnable.isAccountFound()) {
            return syncEnable.getStatus()
                syncStatus = syncEnable.getStatus()
                return@forEach
            }
        }

        return true
        return syncStatus
    }

    private fun isSyncEnable(accountManager: AccountManager, accounts: Array<out Account>, email: String): Syncable {
        accounts.forEach {
            try {
                val accountEmail: String = accountManager.getUserData(it, AccountManagerConstants.ACCOUNT_EMAIL_ADDRESS_KEY)
                val accountEmail: String =
                    accountManager.getUserData(it, AccountManagerConstants.ACCOUNT_EMAIL_ADDRESS_KEY)
                if (accountEmail == email) {
                    // if master sync disable, then account sync is disable
                    return if (!ContentResolver.getMasterSyncAutomatically()) {
                        Syncable.NOT_SYNCABLE
                    } else Syncable.getSyncable(ContentResolver.getSyncAutomatically(it, AccountManagerConstants.MAIL_CONTENT_AUTHORITY))
                    } else Syncable.getSyncable(
                        ContentResolver.getSyncAutomatically(
                            it,
                            AccountManagerConstants.MAIL_CONTENT_AUTHORITY,
                        ),
                    )
                }
            } catch (e: Throwable) {
                Timber.e(e)
+12 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.fsck.k9.setup
object AccountManagerConstants {
    const val EELO_ACCOUNT_TYPE = "e.foundation.webdav.eelo"
    const val GOOGLE_ACCOUNT_TYPE = "e.foundation.webdav.google"
    const val YAHOO_ACCOUNT_TYPE = "e.foundation.webdav.yahoo"
    const val ACCOUNT_EMAIL_ADDRESS_KEY = "email_address"
    const val MAIL_CONTENT_AUTHORITY = "foundation.e.mail.provider.AppContentProvider"
    const val AUTH_TOKEN_TYPE = "oauth2-access-token"
@@ -28,4 +29,15 @@ object AccountManagerConstants {
    const val OPEN_APP_ACTIVITY_AFTER_AUTH = "open_app_activity_after_auth"

    const val IGNORE_ACCOUNT_SETUP = "ignore_account_setup"

    val OPENID_ACCOUNT_TYPES = listOf(GOOGLE_ACCOUNT_TYPE, YAHOO_ACCOUNT_TYPE)
    val ALL_ACCOUNT_TYPES = listOf(EELO_ACCOUNT_TYPE, GOOGLE_ACCOUNT_TYPE, YAHOO_ACCOUNT_TYPE)

    fun getOpenIdAccountTypeByHostName(hostname: String): String? {
        return when(hostname) {
            in listOf("imap.gmail.com", "imap.googlemail.com", "smtp.gmail.com", "smtp.googlemail.com") -> GOOGLE_ACCOUNT_TYPE
            in listOf("imap.mail.yahoo.com", "smtp.mail.yahoo.com") -> YAHOO_ACCOUNT_TYPE
            else -> null
        }
    }
}
+47 −15
Original line number Diff line number Diff line
@@ -16,13 +16,13 @@

package com.fsck.k9.setup

import android.accounts.Account as OsAccount
import android.accounts.AccountManager as OsAccountManager
import android.content.Context
import com.fsck.k9.Account
import com.fsck.k9.mail.AuthType
import com.fsck.k9.preferences.AccountManager
import timber.log.Timber
import android.accounts.Account as OsAccount
import android.accounts.AccountManager as OsAccountManager

object EeloAccountHelper {

@@ -44,10 +44,28 @@ object EeloAccountHelper {
        }

        val osAccountManager = OsAccountManager.get(context)
        val googleAccount = retrieveGoogleAccountFromAccountManager(osAccountManager, account.email) ?: return false

        var result = false
        AccountManagerConstants.OPENID_ACCOUNT_TYPES.forEach {
            val openIdAccount = retrieveOpenIdAccountFromAccountManager(osAccountManager, it, account.email)
            if (openIdAccount != null) {
                updateOAuthState(account, osAccountManager, openIdAccount, accountManager)
                result = true
                return@forEach
            }
        }

        return result
    }

    private fun updateOAuthState(
        account: Account,
        osAccountManager: android.accounts.AccountManager,
        googleAccount: android.accounts.Account?,
        accountManager: AccountManager,
    ) {
        account.oAuthState = osAccountManager.getUserData(googleAccount, AccountManagerConstants.KEY_AUTH_STATE)
        accountManager.saveAccount(account)
        return true
    }

    // If token is updated by mail, also update the accountManager
@@ -55,7 +73,7 @@ object EeloAccountHelper {
        context: Context?,
        account: OsAccount?,
        authState: String?,
        accessToken: String?
        accessToken: String?,
    ) {
        if (context == null || account == null || authState == null || accessToken == null) {
            Timber.w("updating account for accountManager failed, invalid param.")
@@ -67,27 +85,41 @@ object EeloAccountHelper {
        accountManager.setUserData(account, AccountManagerConstants.KEY_AUTH_STATE, authState)
    }

    fun retrieveGoogleAccountFromAccountManager(context: Context?, email: String?): OsAccount? {
    fun retrieveOpenIdAccountFromAccountManager(context: Context?, email: String?): OsAccount? {
        if (context == null) {
            Timber.w("retrieve google accounts from accountManager failed, null context.")
            return null
        }

        val accountManager = OsAccountManager.get(context)
        return retrieveGoogleAccountFromAccountManager(accountManager, email)

        var resultAccount: OsAccount? = null

        AccountManagerConstants.OPENID_ACCOUNT_TYPES.forEach {
            resultAccount = retrieveOpenIdAccountFromAccountManager(accountManager, it, email)
            if (resultAccount != null) {
                return@forEach
            }
        }

        return resultAccount
    }

    private fun retrieveGoogleAccountFromAccountManager(accountManager: OsAccountManager?, email: String?): OsAccount? {
        if (accountManager == null || email == null || email.isEmpty()) {
            Timber.w("retrieve google account from accountManager failed, invalid param")
    private fun retrieveOpenIdAccountFromAccountManager(
        accountManager: OsAccountManager?,
        accountType: String,
        email: String?,
    ): OsAccount? {
        if (accountManager == null || email.isNullOrEmpty()) {
            Timber.w("retrieve $accountType account from accountManager failed, invalid param")
            return null
        }

        val googleAccounts = accountManager.getAccountsByType(AccountManagerConstants.GOOGLE_ACCOUNT_TYPE)
        for (googleAccount in googleAccounts) {
            val emailId = accountManager.getUserData(googleAccount, AccountManagerConstants.ACCOUNT_EMAIL_ADDRESS_KEY)
        val openIdAccounts = accountManager.getAccountsByType(accountType)
        for (openIdAccount in openIdAccounts) {
            val emailId = accountManager.getUserData(openIdAccount, AccountManagerConstants.ACCOUNT_EMAIL_ADDRESS_KEY)
            if (email.equals(emailId, ignoreCase = true)) {
                return googleAccount
                return openIdAccount
            }
        }

+1 −1
Original line number Diff line number Diff line
@@ -31,7 +31,7 @@ class RealOAuth2TokenProvider(
                ?: throw AuthenticationFailedException("Login required")
        }

        val accountManagerAccount = EeloAccountHelper.retrieveGoogleAccountFromAccountManager(context, email)
        val accountManagerAccount = EeloAccountHelper.retrieveOpenIdAccountFromAccountManager(context, email)

        val latch = CountDownLatch(1)
        var token: String? = null
Loading