From 8b8ba1bf90687a54dceb24800eb4b8c69da04c67 Mon Sep 17 00:00:00 2001 From: Fahim Salam Chowdhury Date: Mon, 25 Jul 2022 12:50:58 +0600 Subject: [PATCH 1/6] 5356-fix_mail_sync_issue issue: https://gitlab.e.foundation/e/backlog/-/issues/5356 add internet available check on MailSyncWorker. WorkManager constrain only check network availability. If internet not available, worker shows notification saying authentication issue. Adding internet check by trying to retrieve ip address for murena.io, we can block mail sync when internet not available. --- .../java/com/fsck/k9/job/MailSyncWorker.kt | 7 ++++ .../java/com/fsck/k9/network/NetworkUtil.kt | 35 +++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 app/core/src/main/java/com/fsck/k9/network/NetworkUtil.kt diff --git a/app/core/src/main/java/com/fsck/k9/job/MailSyncWorker.kt b/app/core/src/main/java/com/fsck/k9/job/MailSyncWorker.kt index b9f01eb336..028f190a8e 100644 --- a/app/core/src/main/java/com/fsck/k9/job/MailSyncWorker.kt +++ b/app/core/src/main/java/com/fsck/k9/job/MailSyncWorker.kt @@ -9,6 +9,7 @@ import com.fsck.k9.K9 import com.fsck.k9.Preferences import com.fsck.k9.controller.MessagingController import com.fsck.k9.mail.AuthType +import com.fsck.k9.network.NetworkUtil import com.fsck.k9.setup.EeloAccountHelper import timber.log.Timber @@ -30,6 +31,7 @@ class MailSyncWorker( return Result.success() } + val account = preferences.getAccount(accountUuid) if (account == null) { Timber.e("Account %s not found. Can't perform mail sync.", accountUuid) @@ -52,6 +54,11 @@ class MailSyncWorker( return Result.success() } + if(!NetworkUtil.isInternetAvailable()) { + Timber.d("Internet not available. Retrying mail sync.") + return Result.retry() + } + return messagingController.performPeriodicMailSync(account) } diff --git a/app/core/src/main/java/com/fsck/k9/network/NetworkUtil.kt b/app/core/src/main/java/com/fsck/k9/network/NetworkUtil.kt new file mode 100644 index 0000000000..45158f2430 --- /dev/null +++ b/app/core/src/main/java/com/fsck/k9/network/NetworkUtil.kt @@ -0,0 +1,35 @@ +/* + * Copyright ECORP SAS 2022 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.fsck.k9.network + +import java.net.InetAddress +import java.net.UnknownHostException +import timber.log.Timber + +object NetworkUtil { + + fun isInternetAvailable(): Boolean { + return try { + val ipAddress = InetAddress.getByName("murena.io") + !ipAddress.equals("") + } catch (e: UnknownHostException) { + Timber.e(e, "Internet not available, unknown host detected.") + false + } + } + +} \ No newline at end of file -- GitLab From 63cb66e93be03e8cdfab5040ea0df2f9e8b82e06 Mon Sep 17 00:00:00 2001 From: Fahim Salam Chowdhury Date: Tue, 26 Jul 2022 19:09:09 +0600 Subject: [PATCH 2/6] Revert "5356-fix_mail_sync_issue" This reverts commit 8b8ba1bf90687a54dceb24800eb4b8c69da04c67. --- .../java/com/fsck/k9/job/MailSyncWorker.kt | 7 ---- .../java/com/fsck/k9/network/NetworkUtil.kt | 35 ------------------- 2 files changed, 42 deletions(-) delete mode 100644 app/core/src/main/java/com/fsck/k9/network/NetworkUtil.kt diff --git a/app/core/src/main/java/com/fsck/k9/job/MailSyncWorker.kt b/app/core/src/main/java/com/fsck/k9/job/MailSyncWorker.kt index 028f190a8e..b9f01eb336 100644 --- a/app/core/src/main/java/com/fsck/k9/job/MailSyncWorker.kt +++ b/app/core/src/main/java/com/fsck/k9/job/MailSyncWorker.kt @@ -9,7 +9,6 @@ import com.fsck.k9.K9 import com.fsck.k9.Preferences import com.fsck.k9.controller.MessagingController import com.fsck.k9.mail.AuthType -import com.fsck.k9.network.NetworkUtil import com.fsck.k9.setup.EeloAccountHelper import timber.log.Timber @@ -31,7 +30,6 @@ class MailSyncWorker( return Result.success() } - val account = preferences.getAccount(accountUuid) if (account == null) { Timber.e("Account %s not found. Can't perform mail sync.", accountUuid) @@ -54,11 +52,6 @@ class MailSyncWorker( return Result.success() } - if(!NetworkUtil.isInternetAvailable()) { - Timber.d("Internet not available. Retrying mail sync.") - return Result.retry() - } - return messagingController.performPeriodicMailSync(account) } diff --git a/app/core/src/main/java/com/fsck/k9/network/NetworkUtil.kt b/app/core/src/main/java/com/fsck/k9/network/NetworkUtil.kt deleted file mode 100644 index 45158f2430..0000000000 --- a/app/core/src/main/java/com/fsck/k9/network/NetworkUtil.kt +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright ECORP SAS 2022 - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.fsck.k9.network - -import java.net.InetAddress -import java.net.UnknownHostException -import timber.log.Timber - -object NetworkUtil { - - fun isInternetAvailable(): Boolean { - return try { - val ipAddress = InetAddress.getByName("murena.io") - !ipAddress.equals("") - } catch (e: UnknownHostException) { - Timber.e(e, "Internet not available, unknown host detected.") - false - } - } - -} \ No newline at end of file -- GitLab From 84dd8aa03941f98cf1c40f93c62a09c48fe5650a Mon Sep 17 00:00:00 2001 From: Fahim Salam Chowdhury Date: Tue, 26 Jul 2022 19:13:34 +0600 Subject: [PATCH 3/6] update oAuthState for google accounts always. --- .../com/fsck/k9/controller/MessagingController.java | 2 +- .../src/main/java/com/fsck/k9/job/MailSyncWorker.kt | 2 +- .../main/java/com/fsck/k9/setup/EeloAccountHelper.kt | 12 ++++-------- .../com/fsck/k9/backends/RealOAuth2TokenProvider.kt | 2 +- 4 files changed, 7 insertions(+), 11 deletions(-) diff --git a/app/core/src/main/java/com/fsck/k9/controller/MessagingController.java b/app/core/src/main/java/com/fsck/k9/controller/MessagingController.java index e654e6d066..63ec65eff5 100644 --- a/app/core/src/main/java/com/fsck/k9/controller/MessagingController.java +++ b/app/core/src/main/java/com/fsck/k9/controller/MessagingController.java @@ -2578,7 +2578,7 @@ public class MessagingController { return true; } - EeloAccountHelper.INSTANCE.updateOAuthStateIfMissing(context, preferences, account); + EeloAccountHelper.INSTANCE.updateOAuthState(context, preferences, account); return serverSettings.authenticationType == AuthType.XOAUTH2 && account.getOAuthState() == null; } diff --git a/app/core/src/main/java/com/fsck/k9/job/MailSyncWorker.kt b/app/core/src/main/java/com/fsck/k9/job/MailSyncWorker.kt index b9f01eb336..3b317628df 100644 --- a/app/core/src/main/java/com/fsck/k9/job/MailSyncWorker.kt +++ b/app/core/src/main/java/com/fsck/k9/job/MailSyncWorker.kt @@ -46,7 +46,7 @@ class MailSyncWorker( return Result.success() } - EeloAccountHelper.updateOAuthStateIfMissing(context, preferences, account) + EeloAccountHelper.updateOAuthState(context, preferences, account) if (account.incomingServerSettings.authenticationType == AuthType.XOAUTH2 && account.oAuthState == null) { Timber.d("Account requires sign-in. Skipping mail sync.") return Result.success() diff --git a/app/core/src/main/java/com/fsck/k9/setup/EeloAccountHelper.kt b/app/core/src/main/java/com/fsck/k9/setup/EeloAccountHelper.kt index 2af9c11552..97b33bb00f 100644 --- a/app/core/src/main/java/com/fsck/k9/setup/EeloAccountHelper.kt +++ b/app/core/src/main/java/com/fsck/k9/setup/EeloAccountHelper.kt @@ -27,11 +27,9 @@ import timber.log.Timber object EeloAccountHelper { /** - * to support backward-compatibility. - * In previous versions google accounts loaded from accountManager doesn't store oAuthState in the db. - * This method check if the oAuthState is missing or not, if missing, update the oAuthState + * Update oAuthState for google accounts which is logged in using accountManager */ - fun updateOAuthStateIfMissing(context: Context, accountManager: AccountManager, account: Account?) { + fun updateOAuthState(context: Context, accountManager: AccountManager, account: Account?) { // check params if (account == null) { Timber.w("updating OAuthState failed, account is null") @@ -39,7 +37,7 @@ object EeloAccountHelper { } // validation - if (account.incomingServerSettings.authenticationType != AuthType.XOAUTH2 || account.oAuthState != null) { + if (account.incomingServerSettings.authenticationType != AuthType.XOAUTH2) { Timber.w("updating oAuthState failed, not oauth2 authType") return } @@ -47,9 +45,7 @@ object EeloAccountHelper { val osAccountManager = OsAccountManager.get(context) val googleAccount = retrieveGoogleAccountFromAccountManager(osAccountManager, account.email) ?: return account.oAuthState = osAccountManager.getUserData(googleAccount, AccountManagerConstants.KEY_AUTH_STATE) - if (account.oAuthState != null) { - accountManager.saveAccount(account) - } + accountManager.saveAccount(account) } // If token is updated by mail, also update the accountManager diff --git a/app/k9mail/src/main/java/com/fsck/k9/backends/RealOAuth2TokenProvider.kt b/app/k9mail/src/main/java/com/fsck/k9/backends/RealOAuth2TokenProvider.kt index f57748eb3c..ab2c2652b5 100644 --- a/app/k9mail/src/main/java/com/fsck/k9/backends/RealOAuth2TokenProvider.kt +++ b/app/k9mail/src/main/java/com/fsck/k9/backends/RealOAuth2TokenProvider.kt @@ -26,7 +26,7 @@ class RealOAuth2TokenProvider( override fun getToken(email: String, timeoutMillis: Long): String { val accountManagerAccount = EeloAccountHelper.retrieveGoogleAccountFromAccountManager(context, email) - EeloAccountHelper.updateOAuthStateIfMissing(context, accountManager, account) + EeloAccountHelper.updateOAuthState(context, accountManager, account) val latch = CountDownLatch(1) var token: String? = null -- GitLab From 745a4608065e12bec5738d1d677ba827537b90fb Mon Sep 17 00:00:00 2001 From: Fahim Salam Chowdhury Date: Mon, 8 Aug 2022 11:17:46 +0600 Subject: [PATCH 4/6] remove token refresh condition for accountManager accounts --- .../com/fsck/k9/setup/EeloAccountHelper.kt | 21 ++++++++++++------- .../k9/backends/RealOAuth2TokenProvider.kt | 7 ++++++- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/app/core/src/main/java/com/fsck/k9/setup/EeloAccountHelper.kt b/app/core/src/main/java/com/fsck/k9/setup/EeloAccountHelper.kt index 97b33bb00f..10b69fbe9e 100644 --- a/app/core/src/main/java/com/fsck/k9/setup/EeloAccountHelper.kt +++ b/app/core/src/main/java/com/fsck/k9/setup/EeloAccountHelper.kt @@ -16,40 +16,47 @@ 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 android.accounts.AccountManager as OsAccountManager -import android.accounts.Account as OsAccount import timber.log.Timber object EeloAccountHelper { /** * Update oAuthState for google accounts which is logged in using accountManager + * @return is the update operation successful or not */ - fun updateOAuthState(context: Context, accountManager: AccountManager, account: Account?) { + fun updateOAuthState(context: Context, accountManager: AccountManager, account: Account?): Boolean { // check params if (account == null) { Timber.w("updating OAuthState failed, account is null") - return + return false } // validation if (account.incomingServerSettings.authenticationType != AuthType.XOAUTH2) { Timber.w("updating oAuthState failed, not oauth2 authType") - return + return false } val osAccountManager = OsAccountManager.get(context) - val googleAccount = retrieveGoogleAccountFromAccountManager(osAccountManager, account.email) ?: return + val googleAccount = retrieveGoogleAccountFromAccountManager(osAccountManager, account.email) ?: return false account.oAuthState = osAccountManager.getUserData(googleAccount, AccountManagerConstants.KEY_AUTH_STATE) accountManager.saveAccount(account) + return true } // If token is updated by mail, also update the accountManager - fun updateAccountInAccountManager(context: Context?, account: OsAccount?, authState: String?, accessToken: String?) { + fun updateAccountInAccountManager( + context: Context?, + account: OsAccount?, + authState: String?, + accessToken: String? + ) { if (context == null || account == null || authState == null || accessToken == null) { Timber.w("updating account for accountManager failed, invalid param.") return diff --git a/app/k9mail/src/main/java/com/fsck/k9/backends/RealOAuth2TokenProvider.kt b/app/k9mail/src/main/java/com/fsck/k9/backends/RealOAuth2TokenProvider.kt index ab2c2652b5..aafea74f4c 100644 --- a/app/k9mail/src/main/java/com/fsck/k9/backends/RealOAuth2TokenProvider.kt +++ b/app/k9mail/src/main/java/com/fsck/k9/backends/RealOAuth2TokenProvider.kt @@ -25,8 +25,13 @@ class RealOAuth2TokenProvider( private var requestFreshToken = false override fun getToken(email: String, timeoutMillis: Long): String { + // if the authState is retrieved from accountManager, then return it. Refresh will be handled by accountManager. + if (EeloAccountHelper.updateOAuthState(context, accountManager, account)) { + return account.oAuthState?.let { AuthState.jsonDeserialize(it) }?.accessToken + ?: throw AuthenticationFailedException("Login required") + } + val accountManagerAccount = EeloAccountHelper.retrieveGoogleAccountFromAccountManager(context, email) - EeloAccountHelper.updateOAuthState(context, accountManager, account) val latch = CountDownLatch(1) var token: String? = null -- GitLab From 486ed90b42694687c912d0b0c769728c70f96636 Mon Sep 17 00:00:00 2001 From: Fahim Salam Chowdhury Date: Tue, 9 Aug 2022 12:49:48 +0600 Subject: [PATCH 5/6] WIP: implement copy exception on syncFail functionality for test purpose --- .../k9/controller/MessagingController.java | 39 ++++++++++------- ...thenticationErrorNotificationController.kt | 8 ++-- .../notification/NotificationActionCreator.kt | 3 ++ .../k9/notification/NotificationController.kt | 4 +- .../controller/MessagingControllerTest.java | 2 +- ...ticationErrorNotificationControllerTest.kt | 4 +- app/k9mail/src/main/AndroidManifest.xml | 4 ++ .../K9NotificationActionCreator.kt | 7 ++++ .../misc/TestExceptionCopyActivity.java | 42 +++++++++++++++++++ .../main/res/layout/test_exception_copy.xml | 35 ++++++++++++++++ 10 files changed, 125 insertions(+), 23 deletions(-) create mode 100644 app/ui/legacy/src/main/java/com/fsck/k9/activity/misc/TestExceptionCopyActivity.java create mode 100644 app/ui/legacy/src/main/res/layout/test_exception_copy.xml diff --git a/app/core/src/main/java/com/fsck/k9/controller/MessagingController.java b/app/core/src/main/java/com/fsck/k9/controller/MessagingController.java index 63ec65eff5..83545681b4 100644 --- a/app/core/src/main/java/com/fsck/k9/controller/MessagingController.java +++ b/app/core/src/main/java/com/fsck/k9/controller/MessagingController.java @@ -381,9 +381,10 @@ public class MessagingController { public void refreshFolderListSynchronous(Account account) { try { - if (isAuthenticationProblem(account, true)) { + Exception exception = isAuthenticationProblem(account, true); + if (exception != null) { Timber.d("Authentication will fail. Skip refreshing the folder list."); - handleAuthenticationFailure(account, true); + handleAuthenticationFailure(account, true, exception); return; } @@ -600,9 +601,10 @@ public class MessagingController { private void syncFolder(Account account, long folderId, boolean notify, MessagingListener listener, Backend backend, NotificationState notificationState) { - if (isAuthenticationProblem(account, true)) { + Exception exception = isAuthenticationProblem(account, true); + if (exception != null) { Timber.d("Authentication will fail. Skip synchronizing folder %d.", folderId); - handleAuthenticationFailure(account, true); + handleAuthenticationFailure(account, true, exception); return; } @@ -673,12 +675,12 @@ public class MessagingController { } } - public void handleAuthenticationFailure(Account account, boolean incoming) { + public void handleAuthenticationFailure(Account account, boolean incoming, Exception exception) { if (account.shouldMigrateToOAuth()) { migrateAccountToOAuth(account); } - notificationController.showAuthenticationErrorNotification(account, incoming); + notificationController.showAuthenticationErrorNotification(account, incoming, exception); } private void migrateAccountToOAuth(Account account) { @@ -691,7 +693,7 @@ public class MessagingController { public void handleException(Account account, Exception exception) { if (exception instanceof AuthenticationFailedException) { - handleAuthenticationFailure(account, true); + handleAuthenticationFailure(account, true, exception); } else { notifyUserIfCertificateProblem(account, exception, true); } @@ -1502,9 +1504,10 @@ public class MessagingController { Exception lastFailure = null; boolean wasPermanentFailure = false; try { - if (isAuthenticationProblem(account, false)) { + Exception exception = isAuthenticationProblem(account, false); + if (exception != null) { Timber.d("Authentication will fail. Skip sending messages."); - handleAuthenticationFailure(account, false); + handleAuthenticationFailure(account, false, exception); return; } @@ -1592,7 +1595,7 @@ public class MessagingController { lastFailure = e; wasPermanentFailure = false; - handleAuthenticationFailure(account, false); + handleAuthenticationFailure(account, false, e); handleSendFailure(account, localFolder, message, e); } catch (CertificateValidationException e) { outboxStateRepository.decrementSendAttempts(messageId); @@ -2570,16 +2573,24 @@ public class MessagingController { notificationController.showCertificateErrorNotification(account, incoming); } - private boolean isAuthenticationProblem(Account account, boolean incoming) { + private Exception isAuthenticationProblem(Account account, boolean incoming) { ServerSettings serverSettings = incoming ? account.getIncomingServerSettings() : account.getOutgoingServerSettings(); if (serverSettings.isMissingCredentials()) { Timber.w("account authenticationProblem detected, missing credentials"); - return true; + return new Exception("Missing Credentials. serverSettings incoming: " + incoming + + ", AuthType: " + serverSettings.authenticationType + + ", clientCertificateAlias: " + serverSettings.clientCertificateAlias + + ", username: " + serverSettings.username + + ", password: " + serverSettings.password); } EeloAccountHelper.INSTANCE.updateOAuthState(context, preferences, account); - return serverSettings.authenticationType == AuthType.XOAUTH2 && account.getOAuthState() == null; + if (serverSettings.authenticationType == AuthType.XOAUTH2 && account.getOAuthState() == null) { + return new Exception("XOAUTH2 empty OAuthState. serverSettings incoming: " + incoming); + } + + return null; } private void actOnMessagesGroupedByAccountAndFolder(List messages, MessageActor actor) { @@ -2772,7 +2783,7 @@ public class MessagingController { syncFailed = true; if (exception instanceof AuthenticationFailedException) { - handleAuthenticationFailure(account, true); + handleAuthenticationFailure(account, true, exception); } else { notifyUserIfCertificateProblem(account, exception, true); } diff --git a/app/core/src/main/java/com/fsck/k9/notification/AuthenticationErrorNotificationController.kt b/app/core/src/main/java/com/fsck/k9/notification/AuthenticationErrorNotificationController.kt index 332c7dbb42..ad2aea2653 100644 --- a/app/core/src/main/java/com/fsck/k9/notification/AuthenticationErrorNotificationController.kt +++ b/app/core/src/main/java/com/fsck/k9/notification/AuthenticationErrorNotificationController.kt @@ -11,11 +11,11 @@ internal open class AuthenticationErrorNotificationController( private val actionCreator: NotificationActionCreator, private val resourceProvider: NotificationResourceProvider ) { - fun showAuthenticationErrorNotification(account: Account, incoming: Boolean) { + fun showAuthenticationErrorNotification(account: Account, incoming: Boolean, exception: Exception) { val notificationId = NotificationIds.getAuthenticationErrorNotificationId(account, incoming) - val editServerSettingsPendingIntent = createContentIntent(account, incoming) - val title = resourceProvider.authenticationErrorTitle() - val text = resourceProvider.authenticationErrorBody(account.displayName) + val editServerSettingsPendingIntent = actionCreator.getTestExceptionCopyPendingIntent(exception)//createContentIntent(account, incoming) + val title = "Account: " + account.displayName//resourceProvider.authenticationErrorTitle() + val text = exception.toString()//resourceProvider.authenticationErrorBody(account.displayName) val notificationBuilder = notificationHelper .createNotificationBuilder(account, NotificationChannelManager.ChannelType.MISCELLANEOUS) diff --git a/app/core/src/main/java/com/fsck/k9/notification/NotificationActionCreator.kt b/app/core/src/main/java/com/fsck/k9/notification/NotificationActionCreator.kt index d7e403b8c3..a2fb69d7e9 100644 --- a/app/core/src/main/java/com/fsck/k9/notification/NotificationActionCreator.kt +++ b/app/core/src/main/java/com/fsck/k9/notification/NotificationActionCreator.kt @@ -3,6 +3,7 @@ package com.fsck.k9.notification import android.app.PendingIntent import com.fsck.k9.Account import com.fsck.k9.controller.MessageReference +import java.lang.Exception interface NotificationActionCreator { fun createViewMessagePendingIntent(messageReference: MessageReference, notificationId: Int): PendingIntent @@ -38,6 +39,8 @@ interface NotificationActionCreator { fun getEditOutgoingServerSettingsIntent(account: Account): PendingIntent + fun getTestExceptionCopyPendingIntent(exception: Exception): PendingIntent + fun createDeleteMessagePendingIntent(messageReference: MessageReference, notificationId: Int): PendingIntent fun createDeleteAllPendingIntent( diff --git a/app/core/src/main/java/com/fsck/k9/notification/NotificationController.kt b/app/core/src/main/java/com/fsck/k9/notification/NotificationController.kt index fe0144108e..7248f63765 100644 --- a/app/core/src/main/java/com/fsck/k9/notification/NotificationController.kt +++ b/app/core/src/main/java/com/fsck/k9/notification/NotificationController.kt @@ -20,8 +20,8 @@ class NotificationController internal constructor( certificateErrorNotificationController.clearCertificateErrorNotifications(account, incoming) } - fun showAuthenticationErrorNotification(account: Account, incoming: Boolean) { - authenticationErrorNotificationController.showAuthenticationErrorNotification(account, incoming) + fun showAuthenticationErrorNotification(account: Account, incoming: Boolean, exception: Exception) { + authenticationErrorNotificationController.showAuthenticationErrorNotification(account, incoming, exception) } fun clearAuthenticationErrorNotification(account: Account, incoming: Boolean) { diff --git a/app/core/src/test/java/com/fsck/k9/controller/MessagingControllerTest.java b/app/core/src/test/java/com/fsck/k9/controller/MessagingControllerTest.java index 978788b78a..904e418ddd 100644 --- a/app/core/src/test/java/com/fsck/k9/controller/MessagingControllerTest.java +++ b/app/core/src/test/java/com/fsck/k9/controller/MessagingControllerTest.java @@ -386,7 +386,7 @@ public class MessagingControllerTest extends K9RobolectricTest { controller.sendPendingMessagesSynchronous(account); - verify(notificationController).showAuthenticationErrorNotification(account, false); + verify(notificationController).showAuthenticationErrorNotification(account, false, new Exception()); } @Test diff --git a/app/core/src/test/java/com/fsck/k9/notification/AuthenticationErrorNotificationControllerTest.kt b/app/core/src/test/java/com/fsck/k9/notification/AuthenticationErrorNotificationControllerTest.kt index aed171f238..ae5aa4e426 100644 --- a/app/core/src/test/java/com/fsck/k9/notification/AuthenticationErrorNotificationControllerTest.kt +++ b/app/core/src/test/java/com/fsck/k9/notification/AuthenticationErrorNotificationControllerTest.kt @@ -40,7 +40,7 @@ class AuthenticationErrorNotificationControllerTest : RobolectricTest() { fun showAuthenticationErrorNotification_withIncomingServer_shouldCreateNotification() { val notificationId = NotificationIds.getAuthenticationErrorNotificationId(account, INCOMING) - controller.showAuthenticationErrorNotification(account, INCOMING) + controller.showAuthenticationErrorNotification(account, INCOMING, Exception()) verify(notificationManager).notify(notificationId, notification) assertAuthenticationErrorNotificationContents() @@ -59,7 +59,7 @@ class AuthenticationErrorNotificationControllerTest : RobolectricTest() { fun showAuthenticationErrorNotification_withOutgoingServer_shouldCreateNotification() { val notificationId = NotificationIds.getAuthenticationErrorNotificationId(account, OUTGOING) - controller.showAuthenticationErrorNotification(account, OUTGOING) + controller.showAuthenticationErrorNotification(account, OUTGOING, java.lang.Exception()) verify(notificationManager).notify(notificationId, notification) assertAuthenticationErrorNotificationContents() diff --git a/app/k9mail/src/main/AndroidManifest.xml b/app/k9mail/src/main/AndroidManifest.xml index 8da6282696..7707c6fcba 100644 --- a/app/k9mail/src/main/AndroidManifest.xml +++ b/app/k9mail/src/main/AndroidManifest.xml @@ -93,6 +93,10 @@ android:configChanges="locale" android:label="@string/account_setup_incoming_title"/> + + { + ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); + ClipData clip = ClipData.newPlainText("exceptionLabel", exception); + clipboard.setPrimaryClip(clip); + }); + } +} diff --git a/app/ui/legacy/src/main/res/layout/test_exception_copy.xml b/app/ui/legacy/src/main/res/layout/test_exception_copy.xml new file mode 100644 index 0000000000..5158ea4e0a --- /dev/null +++ b/app/ui/legacy/src/main/res/layout/test_exception_copy.xml @@ -0,0 +1,35 @@ + + + +