Repository: thunderbird/thunderbird-android (language: kotlin)

Issue:
Migrate K9.isDebugLoggingEnabled to PreferenceDataStore
Goal of this issue is to migrate `isDebugLoggingEnabled ` to `PreferenceDataStore` and replace all direct usage of `K9.isDebugLoggingEnabled` with it throught the application.


Discussion hints:
nan

Pull request: Migrate K9.isDebugLoggingEnabled to PreferenceDataStore
 - Fixes #9456 
###  Implementation Highlights
 - Implemented buildFeature in `core.preference` module and shared BuildConfig's `DEBUG` flag through `expect-actual` pattern in `commonMain`. 
 - Migrate `K9.isDebugLoggingEnabled` to `PreferenceDataStore`.

Test command: ./gradlew :legacy:core:testDebugUnitTest --tests "com.fsck.k9.preferences.SettingsUpgradeHelperTest" --tests "com.fsck.k9.preferences.AccountSettingsUpgraderTest" --tests "com.fsck.k9.mailstore.LocalStoreTest" --tests "com.fsck.k9.message.TextBodyBuilderTest" :legacy:ui:legacy:testDebugUnitTest --tests "com.fsck.k9.ui.messageview.ViewIntentFinderTest" :legacy:storage:testDebugUnitTest --tests "com.fsck.k9.storage.messages.SaveMessageOperationsTest" --tests "com.fsck.k9.storage.messages.CopyMessageOperationsTest" --tests "com.fsck.k9.storage.messages.DeleteFolderOperationsTest" --tests "com.fsck.k9.storage.messages.DeleteMessageOperationsTest"

Fix patch:
diff --git a/core/logging/impl-legacy/build.gradle.kts b/core/logging/impl-legacy/build.gradle.kts
index 07efd269856..50d80fc1b10 100644
--- a/core/logging/impl-legacy/build.gradle.kts
+++ b/core/logging/impl-legacy/build.gradle.kts
@@ -8,6 +8,10 @@ android {
 
 kotlin {
     sourceSets {
+        androidMain.dependencies {
+            implementation(libs.timber)
+        }
+
         commonMain.dependencies {
             api(projects.core.logging.api)
             api(libs.androidx.annotation)
diff --git a/core/logging/impl-legacy/src/androidMain/kotlin/net/thunderbird/core/logging/legacy/DebugLogConfigurator.kt b/core/logging/impl-legacy/src/androidMain/kotlin/net/thunderbird/core/logging/legacy/DebugLogConfigurator.kt
new file mode 100644
index 00000000000..715aa8fc8e3
--- /dev/null
+++ b/core/logging/impl-legacy/src/androidMain/kotlin/net/thunderbird/core/logging/legacy/DebugLogConfigurator.kt
@@ -0,0 +1,14 @@
+package net.thunderbird.core.logging.legacy
+
+import timber.log.Timber
+
+// TODO: Implementation https://github.com/thunderbird/thunderbird-android/issues/9573
+class DebugLogConfigurator {
+
+    fun updateLoggingStatus(isDebugLoggingEnabled: Boolean) {
+        Timber.uprootAll()
+        if (isDebugLoggingEnabled) {
+            Timber.plant(Timber.DebugTree())
+        }
+    }
+}
diff --git a/core/preference/api/build.gradle.kts b/core/preference/api/build.gradle.kts
index 11dbb25c658..60d40f11fb0 100644
--- a/core/preference/api/build.gradle.kts
+++ b/core/preference/api/build.gradle.kts
@@ -4,4 +4,7 @@ plugins {
 
 android {
     namespace = "net.thunderbird.core.preference"
+    buildFeatures {
+        buildConfig = true
+    }
 }
diff --git a/core/preference/api/src/androidMain/kotlin/net/thunderbird/core/preference/debugging/BuildInfo.kt b/core/preference/api/src/androidMain/kotlin/net/thunderbird/core/preference/debugging/BuildInfo.kt
new file mode 100644
index 00000000000..07be4d5c7b5
--- /dev/null
+++ b/core/preference/api/src/androidMain/kotlin/net/thunderbird/core/preference/debugging/BuildInfo.kt
@@ -0,0 +1,5 @@
+package net.thunderbird.core.preference.debugging
+
+import net.thunderbird.core.preference.BuildConfig
+
+actual val isDebug: Boolean = BuildConfig.DEBUG
diff --git a/core/preference/api/src/commonMain/kotlin/net/thunderbird/core/preference/GeneralSettings.kt b/core/preference/api/src/commonMain/kotlin/net/thunderbird/core/preference/GeneralSettings.kt
index cb1d9de57e9..3425a69cec6 100644
--- a/core/preference/api/src/commonMain/kotlin/net/thunderbird/core/preference/GeneralSettings.kt
+++ b/core/preference/api/src/commonMain/kotlin/net/thunderbird/core/preference/GeneralSettings.kt
@@ -1,5 +1,6 @@
 package net.thunderbird.core.preference
 
+import net.thunderbird.core.preference.debugging.DebuggingSettings
 import net.thunderbird.core.preference.display.DisplaySettings
 import net.thunderbird.core.preference.network.NetworkSettings
 import net.thunderbird.core.preference.notification.NotificationPreference
@@ -18,6 +19,7 @@ data class GeneralSettings(
     val notification: NotificationPreference = NotificationPreference(),
     val display: DisplaySettings = DisplaySettings(),
     val privacy: PrivacySettings = PrivacySettings(),
+    val debugging: DebuggingSettings = DebuggingSettings(),
 )
 
 enum class BackgroundSync {
diff --git a/core/preference/api/src/commonMain/kotlin/net/thunderbird/core/preference/debugging/BuildInfo.kt b/core/preference/api/src/commonMain/kotlin/net/thunderbird/core/preference/debugging/BuildInfo.kt
new file mode 100644
index 00000000000..8d59874aae5
--- /dev/null
+++ b/core/preference/api/src/commonMain/kotlin/net/thunderbird/core/preference/debugging/BuildInfo.kt
@@ -0,0 +1,3 @@
+package net.thunderbird.core.preference.debugging
+
+expect val isDebug: Boolean
diff --git a/core/preference/api/src/commonMain/kotlin/net/thunderbird/core/preference/debugging/DebuggingSettings.kt b/core/preference/api/src/commonMain/kotlin/net/thunderbird/core/preference/debugging/DebuggingSettings.kt
new file mode 100644
index 00000000000..410f7a95b81
--- /dev/null
+++ b/core/preference/api/src/commonMain/kotlin/net/thunderbird/core/preference/debugging/DebuggingSettings.kt
@@ -0,0 +1,7 @@
+package net.thunderbird.core.preference.debugging
+
+val DEBUGGING_SETTINGS_DEFAULT_IS_DEBUGGING_LOGGING_ENABLED = isDebug
+
+data class DebuggingSettings(
+    val isDebugLoggingEnabled: Boolean = DEBUGGING_SETTINGS_DEFAULT_IS_DEBUGGING_LOGGING_ENABLED,
+)
diff --git a/core/preference/api/src/commonMain/kotlin/net/thunderbird/core/preference/debugging/DebuggingSettingsPreferenceManager.kt b/core/preference/api/src/commonMain/kotlin/net/thunderbird/core/preference/debugging/DebuggingSettingsPreferenceManager.kt
new file mode 100644
index 00000000000..244f5b36427
--- /dev/null
+++ b/core/preference/api/src/commonMain/kotlin/net/thunderbird/core/preference/debugging/DebuggingSettingsPreferenceManager.kt
@@ -0,0 +1,7 @@
+package net.thunderbird.core.preference.debugging
+
+import net.thunderbird.core.preference.PreferenceManager
+
+const val KEY_ENABLE_DEBUG_LOGGING = "enableDebugLogging"
+
+interface DebuggingSettingsPreferenceManager : PreferenceManager<DebuggingSettings>
diff --git a/core/preference/api/src/jvmMain/kotlin/net/thunderbird/core/preference/debugging/BuildInfo.kt b/core/preference/api/src/jvmMain/kotlin/net/thunderbird/core/preference/debugging/BuildInfo.kt
new file mode 100644
index 00000000000..c9e699006d2
--- /dev/null
+++ b/core/preference/api/src/jvmMain/kotlin/net/thunderbird/core/preference/debugging/BuildInfo.kt
@@ -0,0 +1,3 @@
+package net.thunderbird.core.preference.debugging
+
+actual val isDebug: Boolean = false
diff --git a/core/preference/impl/src/commonMain/kotlin/net/thunderbird/core/preference/debugging/DefaultDebuggingSettingsPreferenceManager.kt b/core/preference/impl/src/commonMain/kotlin/net/thunderbird/core/preference/debugging/DefaultDebuggingSettingsPreferenceManager.kt
new file mode 100644
index 00000000000..0139a168d69
--- /dev/null
+++ b/core/preference/impl/src/commonMain/kotlin/net/thunderbird/core/preference/debugging/DefaultDebuggingSettingsPreferenceManager.kt
@@ -0,0 +1,56 @@
+package net.thunderbird.core.preference.debugging
+
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.SupervisorJob
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.update
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.sync.Mutex
+import kotlinx.coroutines.sync.withLock
+import net.thunderbird.core.logging.Logger
+import net.thunderbird.core.preference.storage.Storage
+import net.thunderbird.core.preference.storage.StorageEditor
+
+private const val TAG = "DefaultDebuggingSettingsPreferenceManager"
+
+class DefaultDebuggingSettingsPreferenceManager(
+    private val logger: Logger,
+    private val storage: Storage,
+    private val storageEditor: StorageEditor,
+    private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO,
+    private var scope: CoroutineScope = CoroutineScope(SupervisorJob()),
+) : DebuggingSettingsPreferenceManager {
+    private val configState: MutableStateFlow<DebuggingSettings> = MutableStateFlow(value = loadConfig())
+    private val mutex = Mutex()
+
+    override fun getConfig(): DebuggingSettings = configState.value
+    override fun getConfigFlow(): Flow<DebuggingSettings> = configState
+
+    override fun save(config: DebuggingSettings) {
+        logger.debug(TAG) { "save() called with: config = $config" }
+        writeConfig(config)
+        configState.update { config }
+    }
+
+    private fun loadConfig(): DebuggingSettings = DebuggingSettings(
+        isDebugLoggingEnabled = storage.getBoolean(
+            KEY_ENABLE_DEBUG_LOGGING,
+            DEBUGGING_SETTINGS_DEFAULT_IS_DEBUGGING_LOGGING_ENABLED,
+        ),
+    )
+
+    private fun writeConfig(config: DebuggingSettings) {
+        logger.debug(TAG) { "writeConfig() called with: config = $config" }
+        scope.launch(ioDispatcher) {
+            mutex.withLock {
+                storageEditor.putBoolean(KEY_ENABLE_DEBUG_LOGGING, config.isDebugLoggingEnabled)
+                storageEditor.commit().also { commited ->
+                    logger.verbose(TAG) { "writeConfig: storageEditor.commit() resulted in: $commited" }
+                }
+            }
+        }
+    }
+}
diff --git a/legacy/core/src/main/java/com/fsck/k9/Core.kt b/legacy/core/src/main/java/com/fsck/k9/Core.kt
index 2ad12d8fc3c..31230cdb11a 100644
--- a/legacy/core/src/main/java/com/fsck/k9/Core.kt
+++ b/legacy/core/src/main/java/com/fsck/k9/Core.kt
@@ -3,6 +3,7 @@ package com.fsck.k9
 import android.content.ComponentName
 import android.content.Context
 import android.content.pm.PackageManager
+import com.fsck.k9.core.BuildConfig
 import com.fsck.k9.job.K9JobManager
 import com.fsck.k9.mail.internet.BinaryTempFileBody
 import com.fsck.k9.notification.NotificationController
@@ -27,7 +28,7 @@ object Core : KoinComponent {
      * injection library.
      */
     fun earlyInit() {
-        if (K9.DEVELOPER_MODE) {
+        if (BuildConfig.DEBUG) {
             enableStrictMode()
         }
     }
diff --git a/legacy/core/src/main/java/com/fsck/k9/K9.kt b/legacy/core/src/main/java/com/fsck/k9/K9.kt
index a9480c0625d..c3982f7f4b4 100644
--- a/legacy/core/src/main/java/com/fsck/k9/K9.kt
+++ b/legacy/core/src/main/java/com/fsck/k9/K9.kt
@@ -7,7 +7,6 @@ import com.fsck.k9.K9.DATABASE_VERSION_CACHE
 import com.fsck.k9.K9.areDatabasesUpToDate
 import com.fsck.k9.K9.checkCachedDatabaseVersion
 import com.fsck.k9.K9.setDatabasesUpToDate
-import com.fsck.k9.core.BuildConfig
 import com.fsck.k9.mail.K9MailLib
 import com.fsck.k9.mailstore.LocalStore
 import com.fsck.k9.preferences.DefaultGeneralSettingsManager
@@ -26,7 +25,6 @@ import org.koin.core.component.KoinComponent
 import org.koin.core.component.inject
 import org.koin.core.qualifier.named
 import timber.log.Timber
-import timber.log.Timber.DebugTree
 
 // TODO "Use GeneralSettingsManager and GeneralSettings instead"
 object K9 : KoinComponent {
@@ -36,12 +34,6 @@ object K9 : KoinComponent {
     private val syncDebugCompositeSink: CompositeLogSink by inject(named("syncDebug"))
     private val syncDebugFileLogSink: FileLogSink by inject(named("syncDebug"))
 
-    /**
-     * If this is `true`, various development settings will be enabled.
-     */
-    @JvmField
-    val DEVELOPER_MODE = BuildConfig.DEBUG
-
     /**
      * Name of the [SharedPreferences] file used to store the last known version of the
      * accounts' databases.
@@ -126,13 +118,6 @@ object K9 : KoinComponent {
         }
     }
 
-    @JvmStatic
-    var isDebugLoggingEnabled: Boolean = DEVELOPER_MODE
-        set(debug) {
-            field = debug
-            updateLoggingStatus()
-        }
-
     @JvmStatic
     var isSyncLoggingEnabled: Boolean = false
         set(debug) {
@@ -262,7 +247,7 @@ object K9 : KoinComponent {
     fun init(context: Context) {
         K9MailLib.setDebugStatus(
             object : K9MailLib.DebugStatus {
-                override fun enabled(): Boolean = isDebugLoggingEnabled
+                override fun enabled(): Boolean = generalSettingsManager.getConfig().debugging.isDebugLoggingEnabled
 
                 override fun debugSensitive(): Boolean = isSensitiveDebugLoggingEnabled
             },
@@ -276,7 +261,6 @@ object K9 : KoinComponent {
     @JvmStatic
     @Suppress("LongMethod")
     fun loadPrefs(storage: Storage) {
-        isDebugLoggingEnabled = storage.getBoolean("enableDebugLogging", DEVELOPER_MODE)
         isSyncLoggingEnabled = storage.getBoolean("enableSyncDebugLogging", false)
         isSensitiveDebugLoggingEnabled = storage.getBoolean("enableSensitiveLogging", false)
         isUseVolumeKeysForNavigation = storage.getBoolean("useVolumeKeysForNavigation", false)
@@ -346,7 +330,6 @@ object K9 : KoinComponent {
 
     @Suppress("LongMethod")
     internal fun save(editor: StorageEditor) {
-        editor.putBoolean("enableDebugLogging", isDebugLoggingEnabled)
         editor.putBoolean("enableSyncDebugLogging", isSyncLoggingEnabled)
         editor.putBoolean("enableSensitiveLogging", isSensitiveDebugLoggingEnabled)
         editor.putBoolean("useVolumeKeysForNavigation", isUseVolumeKeysForNavigation)
@@ -396,13 +379,6 @@ object K9 : KoinComponent {
         fontSizes.save(editor)
     }
 
-    private fun updateLoggingStatus() {
-        Timber.uprootAll()
-        if (isDebugLoggingEnabled) {
-            Timber.plant(DebugTree())
-        }
-    }
-
     private fun updateSyncLogging() {
         if (isSyncLoggingEnabled) {
             syncDebugCompositeSink.manager.add(syncDebugFileLogSink)
diff --git a/legacy/core/src/main/java/com/fsck/k9/controller/MessagingController.java b/legacy/core/src/main/java/com/fsck/k9/controller/MessagingController.java
index 3167216e774..1c9c001d2c0 100644
--- a/legacy/core/src/main/java/com/fsck/k9/controller/MessagingController.java
+++ b/legacy/core/src/main/java/com/fsck/k9/controller/MessagingController.java
@@ -28,6 +28,10 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.VisibleForTesting;
 import app.k9mail.legacy.di.DI;
+import app.k9mail.legacy.mailstore.FolderDetailsAccessor;
+import app.k9mail.legacy.mailstore.MessageStore;
+import app.k9mail.legacy.mailstore.MessageStoreManager;
+import app.k9mail.legacy.mailstore.SaveMessageData;
 import app.k9mail.legacy.message.controller.MessageReference;
 import app.k9mail.legacy.message.controller.MessagingControllerMailChecker;
 import app.k9mail.legacy.message.controller.MessagingControllerRegistry;
@@ -66,17 +70,13 @@
 import com.fsck.k9.mail.ServerSettings;
 import com.fsck.k9.mail.power.PowerManager;
 import com.fsck.k9.mail.power.WakeLock;
-import app.k9mail.legacy.mailstore.FolderDetailsAccessor;
 import com.fsck.k9.mailstore.LocalFolder;
 import com.fsck.k9.mailstore.LocalMessage;
 import com.fsck.k9.mailstore.LocalStore;
 import com.fsck.k9.mailstore.LocalStoreProvider;
 import com.fsck.k9.mailstore.MessageListCache;
-import app.k9mail.legacy.mailstore.MessageStore;
-import app.k9mail.legacy.mailstore.MessageStoreManager;
 import com.fsck.k9.mailstore.OutboxState;
 import com.fsck.k9.mailstore.OutboxStateRepository;
-import app.k9mail.legacy.mailstore.SaveMessageData;
 import com.fsck.k9.mailstore.SaveMessageDataCreator;
 import com.fsck.k9.mailstore.SendState;
 import com.fsck.k9.mailstore.SpecialLocalFoldersCreator;
@@ -85,11 +85,11 @@
 import net.thunderbird.core.android.account.DeletePolicy;
 import net.thunderbird.core.android.account.LegacyAccount;
 import net.thunderbird.core.featureflag.FeatureFlagProvider;
-import net.thunderbird.feature.search.legacy.LocalMessageSearch;
 import net.thunderbird.core.logging.Logger;
+import net.thunderbird.core.logging.legacy.Log;
+import net.thunderbird.feature.search.legacy.LocalMessageSearch;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
-import net.thunderbird.core.logging.legacy.Log;
 
 import static com.fsck.k9.K9.MAX_SEND_ATTEMPTS;
 import static com.fsck.k9.controller.Preconditions.requireNotNull;
@@ -765,7 +765,7 @@ public void processPendingCommandsSynchronous(LegacyAccount account) throws Mess
                     Log.e(e, "Unexpected exception with command '%s', removing command from queue", commandName);
                     localStore.removePendingCommand(processingCommand);
 
-                    if (K9.DEVELOPER_MODE) {
+                    if (BuildConfig.DEBUG) {
                         throw new AssertionError("Unexpected exception while processing pending command", e);
                     }
                 }
diff --git a/legacy/core/src/main/java/com/fsck/k9/mailstore/LocalFolder.java b/legacy/core/src/main/java/com/fsck/k9/mailstore/LocalFolder.java
index 8e8d5625fe2..afc8bd2febe 100644
--- a/legacy/core/src/main/java/com/fsck/k9/mailstore/LocalFolder.java
+++ b/legacy/core/src/main/java/com/fsck/k9/mailstore/LocalFolder.java
@@ -33,6 +33,7 @@
 import com.fsck.k9.message.extractors.AttachmentInfoExtractor;
 
 import net.thunderbird.core.android.account.LegacyAccount;
+import net.thunderbird.core.preference.GeneralSettingsManager;
 import org.apache.commons.io.IOUtils;
 import org.apache.james.mime4j.util.MimeUtil;
 
@@ -62,6 +63,7 @@ public class LocalFolder {
 
     private final LocalStore localStore;
     private final AttachmentInfoExtractor attachmentInfoExtractor;
+    private GeneralSettingsManager generalSettingsManager;
 
 
     private String status = null;
@@ -83,23 +85,24 @@ public class LocalFolder {
     private boolean localOnly = false;
 
 
-    public LocalFolder(LocalStore localStore, String serverId) {
-        this(localStore, serverId, null);
+    public LocalFolder(LocalStore localStore, String serverId, GeneralSettingsManager generalSettingsManager) {
+        this(localStore, serverId, null, generalSettingsManager);
     }
 
-    public LocalFolder(LocalStore localStore, String serverId, String name) {
-        this(localStore, serverId, name, FolderType.REGULAR);
+    public LocalFolder(LocalStore localStore, String serverId, String name, GeneralSettingsManager generalSettingsManager) {
+        this(localStore, serverId, name, FolderType.REGULAR, generalSettingsManager);
     }
 
-    public LocalFolder(LocalStore localStore, String serverId, String name, FolderType type) {
+    public LocalFolder(LocalStore localStore, String serverId, String name, FolderType type, GeneralSettingsManager generalSettingsManager) {
         this.localStore = localStore;
         this.serverId = serverId;
         this.name = name;
         this.type = type;
+        this.generalSettingsManager = generalSettingsManager;
         attachmentInfoExtractor = localStore.getAttachmentInfoExtractor();
     }
 
-    public LocalFolder(LocalStore localStore, long databaseId) {
+    public LocalFolder(LocalStore localStore, long databaseId, GeneralSettingsManager generalSettingsManager) {
         super();
         this.localStore = localStore;
         this.databaseId = databaseId;
@@ -476,7 +479,7 @@ public LocalMessage getMessage(final String uid) throws MessagingException {
             @Override
             public LocalMessage doDbWork(final SQLiteDatabase db) throws MessagingException {
                 open();
-                LocalMessage message = new LocalMessage(LocalFolder.this.localStore, uid, LocalFolder.this);
+                LocalMessage message = new LocalMessage(LocalFolder.this.localStore, uid, LocalFolder.this, generalSettingsManager);
                 Cursor cursor = null;
 
                 try {
@@ -505,7 +508,7 @@ public LocalMessage doDbWork(final SQLiteDatabase db) throws MessagingException
     public LocalMessage getMessage(long messageId) throws MessagingException {
         return localStore.getDatabase().execute(false, db -> {
             open();
-            LocalMessage message = new LocalMessage(localStore, messageId, LocalFolder.this);
+            LocalMessage message = new LocalMessage(localStore, messageId, LocalFolder.this, generalSettingsManager);
 
             Cursor cursor = db.rawQuery(
                     "SELECT " +
@@ -1107,7 +1110,7 @@ private void deleteMessagePartsFromDisk(SQLiteDatabase db, long rootMessagePartI
                 String messagePartId = cursor.getString(0);
                 File file = localStore.getAttachmentFile(messagePartId);
                 if (file.exists()) {
-                    if (!file.delete() && K9.isDebugLoggingEnabled()) {
+                    if (!file.delete() && generalSettingsManager.getConfig().getDebugging().isDebugLoggingEnabled()) {
                         Log.d("Couldn't delete message part file: %s", file.getAbsolutePath());
                     }
                 }
diff --git a/legacy/core/src/main/java/com/fsck/k9/mailstore/LocalMessage.java b/legacy/core/src/main/java/com/fsck/k9/mailstore/LocalMessage.java
index 6d63162e587..8edab23a8a4 100644
--- a/legacy/core/src/main/java/com/fsck/k9/mailstore/LocalMessage.java
+++ b/legacy/core/src/main/java/com/fsck/k9/mailstore/LocalMessage.java
@@ -12,6 +12,7 @@
 import androidx.annotation.VisibleForTesting;
 import com.fsck.k9.K9;
 import app.k9mail.legacy.message.controller.MessageReference;
+import com.fsck.k9.core.BuildConfig;
 import com.fsck.k9.mail.Address;
 import com.fsck.k9.mail.Flag;
 import com.fsck.k9.mail.MessagingException;
@@ -23,6 +24,7 @@
 import app.k9mail.legacy.message.extractors.PreviewResult.PreviewType;
 import net.thunderbird.core.android.account.LegacyAccount;
 import net.thunderbird.core.logging.legacy.Log;
+import net.thunderbird.core.preference.GeneralSettingsManager;
 
 
 public class LocalMessage extends MimeMessage {
@@ -40,18 +42,20 @@ public class LocalMessage extends MimeMessage {
     private PreviewType previewType;
     private boolean headerNeedsUpdating = false;
     private LocalFolder mFolder;
+    private GeneralSettingsManager generalSettingsManager;
 
-
-    LocalMessage(LocalStore localStore, String uid, LocalFolder folder) {
+    LocalMessage(LocalStore localStore, String uid, LocalFolder folder, GeneralSettingsManager generalSettingsManager) {
         this.localStore = localStore;
         this.mUid = uid;
         this.mFolder = folder;
+        this.generalSettingsManager = generalSettingsManager;
     }
 
-    LocalMessage(LocalStore localStore, long databaseId, LocalFolder folder) {
+    LocalMessage(LocalStore localStore, long databaseId, LocalFolder folder, GeneralSettingsManager generalSettingsManager) {
         this.localStore = localStore;
         this.databaseId = databaseId;
         this.mFolder = folder;
+        this.generalSettingsManager = generalSettingsManager;
     }
 
 
@@ -102,7 +106,7 @@ void populateFromGetMessageCursor(Cursor cursor) throws MessagingException {
         }
 
         if (this.mFolder == null) {
-            LocalFolder f = new LocalFolder(this.localStore, cursor.getInt(LocalStore.MSG_INDEX_FOLDER_ID));
+            LocalFolder f = new LocalFolder(this.localStore, cursor.getInt(LocalStore.MSG_INDEX_FOLDER_ID), generalSettingsManager);
             f.open();
             this.mFolder = f;
         }
@@ -323,7 +327,7 @@ public Void doDbWork(final SQLiteDatabase db) throws MessagingException {
     }
 
     public void debugClearLocalData() throws MessagingException {
-        if (!K9.DEVELOPER_MODE) {
+        if (!BuildConfig.DEBUG) {
             throw new AssertionError("method must only be used in developer mode!");
         }
 
diff --git a/legacy/core/src/main/java/com/fsck/k9/mailstore/LocalStore.java b/legacy/core/src/main/java/com/fsck/k9/mailstore/LocalStore.java
index bf3e83c3ca5..4272ab2388a 100644
--- a/legacy/core/src/main/java/com/fsck/k9/mailstore/LocalStore.java
+++ b/legacy/core/src/main/java/com/fsck/k9/mailstore/LocalStore.java
@@ -47,6 +47,7 @@
 import com.fsck.k9.message.extractors.AttachmentInfoExtractor;
 import kotlin.time.Clock;
 import net.thunderbird.core.android.account.LegacyAccount;
+import net.thunderbird.core.preference.GeneralSettingsManager;
 import net.thunderbird.feature.search.legacy.LocalMessageSearch;
 import net.thunderbird.feature.search.legacy.api.SearchAttribute;
 import net.thunderbird.feature.search.legacy.api.MessageSearchField;
@@ -165,28 +166,30 @@ public class LocalStore {
     private final LegacyAccount account;
     private final LockableDatabase database;
     private final OutboxStateRepository outboxStateRepository;
+    private GeneralSettingsManager generalSettingsManager;
 
-    static LocalStore createInstance(LegacyAccount account, Context context) throws MessagingException {
-        return new LocalStore(account, context);
+    static LocalStore createInstance(LegacyAccount account, Context context, GeneralSettingsManager generalSettingsManager) throws MessagingException {
+        return new LocalStore(account, context, generalSettingsManager);
     }
 
     /**
      * local://localhost/path/to/database/uuid.db
-     * This constructor is only used by {@link LocalStoreProvider#getInstance(LegacyAccount)}
+     * This constructor is only used by {@link LocalStoreProvider#getInstance(LegacyAccount,GeneralSettingsManager)}
      */
-    private LocalStore(final LegacyAccount account, final Context context) throws MessagingException {
+    private LocalStore(final LegacyAccount account, final Context context, final GeneralSettingsManager generalSettingsManager) throws MessagingException {
         pendingCommandSerializer = PendingCommandSerializer.getInstance();
         attachmentInfoExtractor = DI.get(AttachmentInfoExtractor.class);
         StorageFilesProviderFactory storageFilesProviderFactory = DI.get(StorageFilesProviderFactory.class);
         storageFilesProvider = storageFilesProviderFactory.createStorageFilesProvider(account.getUuid());
 
         this.account = account;
+        this.generalSettingsManager = generalSettingsManager;
 
         SchemaDefinitionFactory schemaDefinitionFactory = DI.get(SchemaDefinitionFactory.class);
         RealMigrationsHelper migrationsHelper = new RealMigrationsHelper();
         SchemaDefinition schemaDefinition = schemaDefinitionFactory.createSchemaDefinition(migrationsHelper);
 
-        database = new LockableDatabase(context, storageFilesProvider, schemaDefinition);
+        database = new LockableDatabase(context, storageFilesProvider, schemaDefinition, generalSettingsManager);
         database.open();
 
         Clock clock = DI.get(Clock.class);
@@ -211,15 +214,15 @@ public OutboxStateRepository getOutboxStateRepository() {
     }
 
     public LocalFolder getFolder(String serverId) {
-        return new LocalFolder(this, serverId);
+        return new LocalFolder(this, serverId, generalSettingsManager);
     }
 
     public LocalFolder getFolder(long folderId) {
-        return new LocalFolder(this, folderId);
+        return new LocalFolder(this, folderId, generalSettingsManager);
     }
 
     public LocalFolder getFolder(String serverId, String name, FolderType type) {
-        return new LocalFolder(this, serverId, name, type);
+        return new LocalFolder(this, serverId, name, type, generalSettingsManager);
     }
 
     // TODO this takes about 260-300ms, seems slow.
@@ -239,7 +242,7 @@ public List<LocalFolder> doDbWork(final SQLiteDatabase db) throws MessagingExcep
                             continue;
                         }
                         long folderId = cursor.getLong(FOLDER_ID_INDEX);
-                        LocalFolder folder = new LocalFolder(LocalStore.this, folderId);
+                        LocalFolder folder = new LocalFolder(LocalStore.this, folderId, generalSettingsManager);
                         folder.open(cursor);
 
                         folders.add(folder);
@@ -373,7 +376,7 @@ public Void doDbWork(final SQLiteDatabase db) {
                     cursor = db.rawQuery(queryString + " LIMIT 10", placeHolders);
 
                     while (cursor.moveToNext()) {
-                        LocalMessage message = new LocalMessage(LocalStore.this, null, folder);
+                        LocalMessage message = new LocalMessage(LocalStore.this, null, folder, generalSettingsManager);
                         message.populateFromGetMessageCursor(cursor);
 
                         messages.add(message);
@@ -382,7 +385,7 @@ public Void doDbWork(final SQLiteDatabase db) {
                     cursor = db.rawQuery(queryString + " LIMIT -1 OFFSET 10", placeHolders);
 
                     while (cursor.moveToNext()) {
-                        LocalMessage message = new LocalMessage(LocalStore.this, null, folder);
+                        LocalMessage message = new LocalMessage(LocalStore.this, null, folder, generalSettingsManager);
                         message.populateFromGetMessageCursor(cursor);
 
                         messages.add(message);
@@ -1000,7 +1003,7 @@ public List<NotificationMessage> getNotificationMessages() throws MessagingExcep
                 while (cursor.moveToNext()) {
                     long folderId = cursor.getLong(MSG_INDEX_FOLDER_ID);
                     LocalFolder folder = getFolder(folderId);
-                    LocalMessage message = new LocalMessage(LocalStore.this, null, folder);
+                    LocalMessage message = new LocalMessage(LocalStore.this, null, folder, generalSettingsManager);
                     message.populateFromGetMessageCursor(cursor);
 
                     Integer notificationId = CursorKt.getIntOrNull(cursor, MSG_INDEX_NOTIFICATION_ID);
diff --git a/legacy/core/src/main/java/com/fsck/k9/mailstore/LocalStoreProvider.kt b/legacy/core/src/main/java/com/fsck/k9/mailstore/LocalStoreProvider.kt
index 800dfe15d3f..c068e1aee78 100644
--- a/legacy/core/src/main/java/com/fsck/k9/mailstore/LocalStoreProvider.kt
+++ b/legacy/core/src/main/java/com/fsck/k9/mailstore/LocalStoreProvider.kt
@@ -5,6 +5,7 @@ import app.k9mail.legacy.di.DI
 import com.fsck.k9.mail.MessagingException
 import java.util.concurrent.ConcurrentHashMap
 import net.thunderbird.core.android.account.LegacyAccount
+import net.thunderbird.core.preference.GeneralSettingsManager
 
 class LocalStoreProvider {
     private val localStores = ConcurrentHashMap<String, LocalStore>()
@@ -13,13 +14,16 @@ class LocalStoreProvider {
     @Throws(MessagingException::class)
     fun getInstance(account: LegacyAccount): LocalStore {
         val context = DI.get(Context::class.java)
+        val generalSettingsManager = DI.get(GeneralSettingsManager::class.java)
         val accountUuid = account.uuid
 
         // Use per-account locks so DatabaseUpgradeService always knows which account database is currently upgraded.
         synchronized(accountLocks.getOrPut(accountUuid) { Any() }) {
             // Creating a LocalStore instance will create or upgrade the database if
             // necessary. This could take some time.
-            return localStores.getOrPut(accountUuid) { LocalStore.createInstance(account, context) }
+            return localStores.getOrPut(accountUuid) {
+                LocalStore.createInstance(account, context, generalSettingsManager)
+            }
         }
     }
 
diff --git a/legacy/core/src/main/java/com/fsck/k9/mailstore/LockableDatabase.java b/legacy/core/src/main/java/com/fsck/k9/mailstore/LockableDatabase.java
index 94ae087f5a1..1497fccc023 100644
--- a/legacy/core/src/main/java/com/fsck/k9/mailstore/LockableDatabase.java
+++ b/legacy/core/src/main/java/com/fsck/k9/mailstore/LockableDatabase.java
@@ -14,6 +14,7 @@
 import com.fsck.k9.helper.FileHelper;
 import com.fsck.k9.mail.MessagingException;
 import net.thunderbird.core.logging.legacy.Log;
+import net.thunderbird.core.preference.GeneralSettingsManager;
 
 import static java.lang.System.currentTimeMillis;
 
@@ -75,12 +76,14 @@ public interface SchemaDefinition {
     private ThreadLocal<Boolean> inTransaction = new ThreadLocal<>();
 
     private SchemaDefinition mSchemaDefinition;
+    private GeneralSettingsManager generalSettingsManager;
 
     public LockableDatabase(Context context, StorageFilesProvider storageFilesProvider,
-            SchemaDefinition schemaDefinition) {
+            SchemaDefinition schemaDefinition, GeneralSettingsManager generalSettingsManager) {
         this.context = context;
         this.storageFilesProvider = storageFilesProvider;
         this.mSchemaDefinition = schemaDefinition;
+        this.generalSettingsManager = generalSettingsManager;
     }
 
     /**
@@ -138,7 +141,7 @@ public <T> T execute(final boolean transactional, final DbCallback<T> callback)
         lockRead();
         final boolean doTransaction = transactional && inTransaction.get() == null;
         try {
-            final boolean debug = K9.isDebugLoggingEnabled();
+            final boolean debug = generalSettingsManager.getConfig().getDebugging().isDebugLoggingEnabled();
             if (doTransaction) {
                 inTransaction.set(Boolean.TRUE);
                 mDb.beginTransaction();
diff --git a/legacy/core/src/main/java/com/fsck/k9/message/MessageBuilder.java b/legacy/core/src/main/java/com/fsck/k9/message/MessageBuilder.java
index 0d81aa46294..037b7af5cab 100644
--- a/legacy/core/src/main/java/com/fsck/k9/message/MessageBuilder.java
+++ b/legacy/core/src/main/java/com/fsck/k9/message/MessageBuilder.java
@@ -317,7 +317,7 @@ private TextBody buildText(boolean isDraft) {
      *         original message.
      */
     private TextBody buildText(boolean isDraft, SimpleMessageFormat simpleMessageFormat) {
-        TextBodyBuilder textBodyBuilder = new TextBodyBuilder(text);
+        TextBodyBuilder textBodyBuilder = new TextBodyBuilder(text, settingsManager);
 
         /*
          * Find out if we need to include the original message as quoted text.
diff --git a/legacy/core/src/main/java/com/fsck/k9/message/TextBodyBuilder.java b/legacy/core/src/main/java/com/fsck/k9/message/TextBodyBuilder.java
index a25dbb3b786..5e066631263 100644
--- a/legacy/core/src/main/java/com/fsck/k9/message/TextBodyBuilder.java
+++ b/legacy/core/src/main/java/com/fsck/k9/message/TextBodyBuilder.java
@@ -8,6 +8,7 @@
 import com.fsck.k9.mail.Body;
 import com.fsck.k9.mail.internet.TextBody;
 import com.fsck.k9.message.quote.InsertableHtmlContent;
+import net.thunderbird.core.preference.GeneralSettingsManager;
 
 
 class TextBodyBuilder {
@@ -24,9 +25,11 @@ class TextBodyBuilder {
     private String mSignature;
     private String mQuotedText;
     private InsertableHtmlContent mQuotedTextHtml;
+    private GeneralSettingsManager generalSettingsManager;
 
-    public TextBodyBuilder(String messageContent) {
+    public TextBodyBuilder(String messageContent, GeneralSettingsManager generalSettingsManager) {
         mMessageContent = messageContent;
+        this.generalSettingsManager = generalSettingsManager;
     }
 
     /**
@@ -49,7 +52,7 @@ public TextBody buildTextHtml() {
         if (mIncludeQuotedText) {
             InsertableHtmlContent quotedHtmlContent = getQuotedTextHtml();
 
-            if (K9.isDebugLoggingEnabled()) {
+            if (generalSettingsManager.getConfig().getDebugging().isDebugLoggingEnabled()) {
                 Log.d("insertable: %s", quotedHtmlContent.toDebugString());
             }
 
diff --git a/legacy/core/src/main/java/com/fsck/k9/preferences/AccountSettingsUpgrader.kt b/legacy/core/src/main/java/com/fsck/k9/preferences/AccountSettingsUpgrader.kt
index 475f5a0171e..50aeeb0463f 100644
--- a/legacy/core/src/main/java/com/fsck/k9/preferences/AccountSettingsUpgrader.kt
+++ b/legacy/core/src/main/java/com/fsck/k9/preferences/AccountSettingsUpgrader.kt
@@ -1,5 +1,7 @@
 package com.fsck.k9.preferences
 
+import net.thunderbird.core.preference.GeneralSettingsManager
+
 internal class AccountSettingsUpgrader(
     private val identitySettingsUpgrader: IdentitySettingsUpgrader,
     private val folderSettingsUpgrader: FolderSettingsUpgrader,
@@ -8,6 +10,7 @@ internal class AccountSettingsUpgrader(
     private val settingsDescriptions: SettingsDescriptions = AccountSettingsDescriptions.SETTINGS,
     private val upgraders: Map<Int, SettingsUpgrader> = AccountSettingsDescriptions.UPGRADERS,
     private val combinedUpgraders: Map<Int, CombinedSettingsUpgraderFactory> = CombinedSettingsUpgraders.UPGRADERS,
+    private val generalSettingsManager: GeneralSettingsManager,
 ) {
 
     fun upgrade(contentVersion: Int, account: ValidatedSettings.Account): ValidatedSettings.Account {
@@ -60,6 +63,7 @@ internal class AccountSettingsUpgrader(
             upgraders,
             settingsDescriptions,
             settings,
+            generalSettingsManager,
         )
     }
 
diff --git a/legacy/core/src/main/java/com/fsck/k9/preferences/AccountSettingsWriter.kt b/legacy/core/src/main/java/com/fsck/k9/preferences/AccountSettingsWriter.kt
index 7b2c1c561f1..fcf53a856e4 100644
--- a/legacy/core/src/main/java/com/fsck/k9/preferences/AccountSettingsWriter.kt
+++ b/legacy/core/src/main/java/com/fsck/k9/preferences/AccountSettingsWriter.kt
@@ -8,6 +8,7 @@ import java.util.UUID
 import kotlin.time.Clock
 import kotlin.time.ExperimentalTime
 import net.thunderbird.core.android.account.LegacyAccount
+import net.thunderbird.core.preference.GeneralSettingsManager
 import net.thunderbird.core.preference.storage.StorageEditor
 import net.thunderbird.feature.account.storage.legacy.LegacyAccountStorageHandler.Companion.ACCOUNT_DESCRIPTION_KEY
 import net.thunderbird.feature.account.storage.legacy.LegacyAccountStorageHandler.Companion.INCOMING_SERVER_SETTINGS_KEY
@@ -20,12 +21,13 @@ constructor(
     private val preferences: Preferences,
     private val localFoldersCreator: SpecialLocalFoldersCreator,
     private val clock: Clock,
+    private val generalSettingsManager: GeneralSettingsManager,
     serverSettingsDtoSerializer: ServerSettingsDtoSerializer,
     private val context: Context,
 ) {
-    private val identitySettingsWriter = IdentitySettingsWriter()
-    private val folderSettingsWriter = FolderSettingsWriter()
-    private val serverSettingsWriter = ServerSettingsWriter(serverSettingsDtoSerializer)
+    private val identitySettingsWriter = IdentitySettingsWriter(generalSettingsManager)
+    private val folderSettingsWriter = FolderSettingsWriter(generalSettingsManager)
+    private val serverSettingsWriter = ServerSettingsWriter(serverSettingsDtoSerializer, generalSettingsManager)
 
     fun write(account: ValidatedSettings.Account): Pair<AccountDescription, AccountDescription> {
         val editor = preferences.createStorageEditor()
@@ -38,17 +40,29 @@ constructor(
         val accountName = getUniqueAccountName(originalAccountName)
         val writtenAccount = AccountDescription(accountName, accountUuid)
 
-        editor.putStringWithLogging("$accountUuid.$ACCOUNT_DESCRIPTION_KEY", accountName)
+        editor.putStringWithLogging(
+            "$accountUuid.$ACCOUNT_DESCRIPTION_KEY",
+            accountName,
+            generalSettingsManager.getConfig().debugging.isDebugLoggingEnabled,
+        )
 
         // Convert account settings to the string representation used in preference storage
         val stringSettings = AccountSettingsDescriptions.convert(account.settings)
 
         for ((accountKey, value) in stringSettings) {
-            editor.putStringWithLogging("$accountUuid.$accountKey", value)
+            editor.putStringWithLogging(
+                "$accountUuid.$accountKey",
+                value,
+                generalSettingsManager.getConfig().debugging.isDebugLoggingEnabled,
+            )
         }
 
         val newAccountNumber = preferences.generateAccountNumber().toString()
-        editor.putStringWithLogging("$accountUuid.accountNumber", newAccountNumber)
+        editor.putStringWithLogging(
+            "$accountUuid.accountNumber",
+            newAccountNumber,
+            generalSettingsManager.getConfig().debugging.isDebugLoggingEnabled,
+        )
 
         // When deleting an account and then restoring it using settings import, the same account UUID will be used.
         // To avoid reusing a previously existing notification channel ID, we need to make sure to use a unique value
@@ -58,6 +72,7 @@ constructor(
         editor.putStringWithLogging(
             key = "$accountUuid.messagesNotificationChannelVersion",
             value = messageNotificationChannelVersion,
+            isDebugLoggingEnabled = generalSettingsManager.getConfig().debugging.isDebugLoggingEnabled,
         )
 
         serverSettingsWriter.writeServerSettings(
@@ -98,7 +113,11 @@ constructor(
         val newAccountUuids = oldAccountUuids + accountUuid
 
         val newAccountUuidString = newAccountUuids.joinToString(separator = ",")
-        editor.putStringWithLogging("accountUuids", newAccountUuidString)
+        editor.putStringWithLogging(
+            "accountUuids",
+            newAccountUuidString,
+            generalSettingsManager.getConfig().debugging.isDebugLoggingEnabled,
+        )
     }
 
     private fun writeIdentities(
diff --git a/legacy/core/src/main/java/com/fsck/k9/preferences/DefaultGeneralSettingsManager.kt b/legacy/core/src/main/java/com/fsck/k9/preferences/DefaultGeneralSettingsManager.kt
index bc1a128ed9b..7253f6b4de5 100644
--- a/legacy/core/src/main/java/com/fsck/k9/preferences/DefaultGeneralSettingsManager.kt
+++ b/legacy/core/src/main/java/com/fsck/k9/preferences/DefaultGeneralSettingsManager.kt
@@ -13,9 +13,11 @@ import kotlinx.coroutines.flow.stateIn
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.sync.Mutex
 import kotlinx.coroutines.sync.withLock
+import net.thunderbird.core.logging.legacy.DebugLogConfigurator
 import net.thunderbird.core.preference.GeneralSettings
 import net.thunderbird.core.preference.GeneralSettingsManager
 import net.thunderbird.core.preference.PreferenceChangePublisher
+import net.thunderbird.core.preference.debugging.DebuggingSettingsPreferenceManager
 import net.thunderbird.core.preference.display.DisplaySettingsPreferenceManager
 import net.thunderbird.core.preference.network.NetworkSettingsPreferenceManager
 import net.thunderbird.core.preference.notification.NotificationPreferenceManager
@@ -31,6 +33,7 @@ import net.thunderbird.core.preference.storage.Storage
  * The [GeneralSettings] instance managed by this class is updated with state from [K9] when [K9.saveSettingsAsync] is
  * called.
  */
+@Suppress("LongParameterList")
 internal class DefaultGeneralSettingsManager(
     private val preferences: Preferences,
     private val coroutineScope: CoroutineScope,
@@ -39,6 +42,8 @@ internal class DefaultGeneralSettingsManager(
     private val notificationPreferenceManager: NotificationPreferenceManager,
     private val displaySettingsSettingsPreferenceManager: DisplaySettingsPreferenceManager,
     private val networkSettingsPreferenceManager: NetworkSettingsPreferenceManager,
+    private val debuggingSettingsPreferenceManager: DebuggingSettingsPreferenceManager,
+    private val debugLogConfigurator: DebugLogConfigurator,
     private val backgroundDispatcher: CoroutineDispatcher = Dispatchers.IO,
 ) : GeneralSettingsManager {
     val mutex = Mutex()
@@ -66,6 +71,13 @@ internal class DefaultGeneralSettingsManager(
                 network = networkSettings,
             )
         }
+        .combine(debuggingSettingsPreferenceManager.getConfigFlow()) { generalSettings, debuggingSettings ->
+            generalSettings.copy(
+                debugging = debuggingSettings,
+            ).also {
+                debugLogConfigurator.updateLoggingStatus(debuggingSettings.isDebugLoggingEnabled)
+            }
+        }
         .stateIn(
             scope = coroutineScope,
             started = SharingStarted.WhileSubscribed(),
@@ -113,6 +125,7 @@ internal class DefaultGeneralSettingsManager(
                 notificationPreferenceManager.save(config.notification)
                 displaySettingsSettingsPreferenceManager.save(config.display)
                 networkSettingsPreferenceManager.save(config.network)
+                debuggingSettingsPreferenceManager.save(config.debugging)
             }
         }
     }
diff --git a/legacy/core/src/main/java/com/fsck/k9/preferences/FolderSettingsUpgrader.kt b/legacy/core/src/main/java/com/fsck/k9/preferences/FolderSettingsUpgrader.kt
index 119ff56e355..7e712efdf30 100644
--- a/legacy/core/src/main/java/com/fsck/k9/preferences/FolderSettingsUpgrader.kt
+++ b/legacy/core/src/main/java/com/fsck/k9/preferences/FolderSettingsUpgrader.kt
@@ -1,8 +1,11 @@
 package com.fsck.k9.preferences
 
+import net.thunderbird.core.preference.GeneralSettingsManager
+
 internal class FolderSettingsUpgrader(
     private val settingsDescriptions: SettingsDescriptions = FolderSettingsDescriptions.SETTINGS,
     private val upgraders: Map<Int, SettingsUpgrader> = FolderSettingsDescriptions.UPGRADERS,
+    private val generalSettingsManager: GeneralSettingsManager,
 ) {
     fun upgrade(targetVersion: Int, contentVersion: Int, folder: ValidatedSettings.Folder): ValidatedSettings.Folder {
         if (contentVersion == targetVersion) {
@@ -15,6 +18,7 @@ internal class FolderSettingsUpgrader(
             upgraders,
             settingsDescriptions,
             folder.settings,
+            generalSettingsManager,
         )
 
         return folder.copy(settings = upgradedSettings)
diff --git a/legacy/core/src/main/java/com/fsck/k9/preferences/FolderSettingsWriter.kt b/legacy/core/src/main/java/com/fsck/k9/preferences/FolderSettingsWriter.kt
index 5e6b88a36ff..b32d7d29a29 100644
--- a/legacy/core/src/main/java/com/fsck/k9/preferences/FolderSettingsWriter.kt
+++ b/legacy/core/src/main/java/com/fsck/k9/preferences/FolderSettingsWriter.kt
@@ -1,8 +1,9 @@
 package com.fsck.k9.preferences
 
+import net.thunderbird.core.preference.GeneralSettingsManager
 import net.thunderbird.core.preference.storage.StorageEditor
 
-internal class FolderSettingsWriter {
+internal class FolderSettingsWriter(private val generalSettingsManager: GeneralSettingsManager) {
     fun write(editor: StorageEditor, accountUuid: String, folder: ValidatedSettings.Folder) {
         // Convert folder settings to the string representation used in preference storage
         val stringSettings = FolderSettingsDescriptions.convert(folder.settings)
@@ -11,7 +12,7 @@ internal class FolderSettingsWriter {
         val prefix = "$accountUuid.${folder.name}."
         for ((folderKey, value) in stringSettings) {
             val key = prefix + folderKey
-            editor.putStringWithLogging(key, value)
+            editor.putStringWithLogging(key, value, generalSettingsManager.getConfig().debugging.isDebugLoggingEnabled)
         }
     }
 }
diff --git a/legacy/core/src/main/java/com/fsck/k9/preferences/GeneralSettingsDescriptions.java b/legacy/core/src/main/java/com/fsck/k9/preferences/GeneralSettingsDescriptions.java
index 9d56fd29289..5e9a42472e5 100644
--- a/legacy/core/src/main/java/com/fsck/k9/preferences/GeneralSettingsDescriptions.java
+++ b/legacy/core/src/main/java/com/fsck/k9/preferences/GeneralSettingsDescriptions.java
@@ -39,6 +39,7 @@
 import net.thunderbird.core.common.action.SwipeAction;
 import net.thunderbird.core.preference.AppTheme;
 import net.thunderbird.core.preference.BackgroundOps;
+import net.thunderbird.core.preference.GeneralSettingsManager;
 import net.thunderbird.core.preference.SubTheme;
 import net.thunderbird.core.preference.display.DisplaySettingsKt;
 import net.thunderbird.core.preference.network.NetworkSettingsKt;
@@ -60,37 +61,11 @@
 import static net.thunderbird.core.preference.display.DisplaySettingsKt.DISPLAY_SETTINGS_DEFAULT_IS_USE_MESSAGE_VIEW_FIXED_WIDTH_FONT;
 import static net.thunderbird.core.preference.display.DisplaySettingsKt.DISPLAY_SETTINGS_DEFAULT_SHOULD_SHOW_SETUP_ARCHIVE_FOLDER_DIALOG;
 import static net.thunderbird.core.preference.display.DisplaySettingsKt.DISPLAY_SETTINGS_DEFAULT_SHOW_RECENT_CHANGES;
-import static net.thunderbird.core.preference.display.DisplaySettingsPreferenceManagerKt.KEY_ANIMATION;
-import static net.thunderbird.core.preference.display.DisplaySettingsPreferenceManagerKt.KEY_APP_LANGUAGE;
-import static net.thunderbird.core.preference.display.DisplaySettingsPreferenceManagerKt.KEY_AUTO_FIT_WIDTH;
-import static net.thunderbird.core.preference.display.DisplaySettingsPreferenceManagerKt.KEY_CHANGE_REGISTERED_NAME_COLOR;
-import static net.thunderbird.core.preference.display.DisplaySettingsPreferenceManagerKt.KEY_COLORIZE_MISSING_CONTACT_PICTURE;
-import static net.thunderbird.core.preference.display.DisplaySettingsPreferenceManagerKt.KEY_FIXED_MESSAGE_VIEW_THEME;
-import static net.thunderbird.core.preference.display.DisplaySettingsPreferenceManagerKt.KEY_MESSAGE_COMPOSE_THEME;
-import static net.thunderbird.core.preference.display.DisplaySettingsPreferenceManagerKt.KEY_MESSAGE_LIST_SENDER_ABOVE_SUBJECT;
-import static net.thunderbird.core.preference.display.DisplaySettingsPreferenceManagerKt.KEY_MESSAGE_VIEW_FIXED_WIDTH_FONT;
-import static net.thunderbird.core.preference.display.DisplaySettingsPreferenceManagerKt.KEY_MESSAGE_VIEW_THEME;
-import static net.thunderbird.core.preference.display.DisplaySettingsPreferenceManagerKt.KEY_SHOULD_SHOW_SETUP_ARCHIVE_FOLDER_DIALOG;
-import static net.thunderbird.core.preference.display.DisplaySettingsPreferenceManagerKt.KEY_SHOW_COMPOSE_BUTTON_ON_MESSAGE_LIST;
-import static net.thunderbird.core.preference.display.DisplaySettingsPreferenceManagerKt.KEY_SHOW_CONTACT_NAME;
-import static net.thunderbird.core.preference.display.DisplaySettingsPreferenceManagerKt.KEY_SHOW_CONTACT_PICTURE;
-import static net.thunderbird.core.preference.display.DisplaySettingsPreferenceManagerKt.KEY_SHOW_CORRESPONDENT_NAMES;
-import static net.thunderbird.core.preference.display.DisplaySettingsPreferenceManagerKt.KEY_SHOW_MESSAGE_LIST_STARS;
-import static net.thunderbird.core.preference.display.DisplaySettingsPreferenceManagerKt.KEY_SHOW_RECENT_CHANGES;
-import static net.thunderbird.core.preference.display.DisplaySettingsPreferenceManagerKt.KEY_SHOW_STAR_COUNT;
-import static net.thunderbird.core.preference.display.DisplaySettingsPreferenceManagerKt.KEY_SHOW_UNIFIED_INBOX;
-import static net.thunderbird.core.preference.display.DisplaySettingsPreferenceManagerKt.KEY_THEME;
-import static net.thunderbird.core.preference.network.NetworkSettingsPreferenceManagerKt.KEY_BG_OPS;
 import static net.thunderbird.core.preference.notification.NotificationPreferenceKt.NOTIFICATION_PREFERENCE_DEFAULT_IS_QUIET_TIME_ENABLED;
 import static net.thunderbird.core.preference.notification.NotificationPreferenceKt.NOTIFICATION_PREFERENCE_DEFAULT_QUIET_TIME_END;
 import static net.thunderbird.core.preference.notification.NotificationPreferenceKt.NOTIFICATION_PREFERENCE_DEFAULT_QUIET_TIME_STARTS;
-import static net.thunderbird.core.preference.notification.NotificationPreferenceManagerKt.KEY_QUIET_TIME_ENABLED;
-import static net.thunderbird.core.preference.notification.NotificationPreferenceManagerKt.KEY_QUIET_TIME_ENDS;
-import static net.thunderbird.core.preference.notification.NotificationPreferenceManagerKt.KEY_QUIET_TIME_STARTS;
 import static net.thunderbird.core.preference.privacy.PrivacySettingsKt.PRIVACY_SETTINGS_DEFAULT_HIDE_TIME_ZONE;
 import static net.thunderbird.core.preference.privacy.PrivacySettingsKt.PRIVACY_SETTINGS_DEFAULT_HIDE_USER_AGENT;
-import static net.thunderbird.core.preference.privacy.PrivacySettingsPreferenceManagerKt.KEY_HIDE_TIME_ZONE;
-import static net.thunderbird.core.preference.privacy.PrivacySettingsPreferenceManagerKt.KEY_HIDE_USER_AGENT;
 
 
 class GeneralSettingsDescriptions {
@@ -98,6 +73,7 @@ class GeneralSettingsDescriptions {
     private static final Map<Integer, SettingsUpgrader> UPGRADERS;
 
     private static final TelemetryManager telemetryManager = DI.get(TelemetryManager.class);
+    private static final GeneralSettingsManager generalSettingManager = DI.get(GeneralSettingsManager.class);
 
     static {
         Map<String, TreeMap<Integer, SettingsDescription<?>>> s = new LinkedHashMap<>();
@@ -384,7 +360,7 @@ static Map<String, Object> validate(int version, Map<String, String> importedSet
     }
 
     public static Map<String, Object> upgrade(int version, Map<String, Object> validatedSettings) {
-        return SettingsUpgradeHelper.upgrade(version, UPGRADERS, SETTINGS, validatedSettings);
+        return SettingsUpgradeHelper.upgrade(version, UPGRADERS, SETTINGS, validatedSettings, generalSettingManager);
     }
 
     public static Map<String, String> convert(Map<String, Object> settings) {
diff --git a/legacy/core/src/main/java/com/fsck/k9/preferences/GeneralSettingsWriter.kt b/legacy/core/src/main/java/com/fsck/k9/preferences/GeneralSettingsWriter.kt
index 591a11c6a32..040f1861cdd 100644
--- a/legacy/core/src/main/java/com/fsck/k9/preferences/GeneralSettingsWriter.kt
+++ b/legacy/core/src/main/java/com/fsck/k9/preferences/GeneralSettingsWriter.kt
@@ -21,7 +21,7 @@ internal class GeneralSettingsWriter(
         mergedSettings.putAll(stringSettings)
 
         for ((key, value) in mergedSettings) {
-            editor.putStringWithLogging(key, value)
+            editor.putStringWithLogging(key, value, generalSettingsManager.getConfig().debugging.isDebugLoggingEnabled)
         }
 
         return if (editor.commit()) {
@@ -40,8 +40,8 @@ internal class GeneralSettingsWriter(
 /**
  * Write to a [StorageEditor] while logging what is written if debug logging is enabled.
  */
-internal fun StorageEditor.putStringWithLogging(key: String, value: String?) {
-    if (K9.isDebugLoggingEnabled) {
+internal fun StorageEditor.putStringWithLogging(key: String, value: String?, isDebugLoggingEnabled: Boolean) {
+    if (isDebugLoggingEnabled) {
         var outputValue = value
         if (!K9.isSensitiveDebugLoggingEnabled &&
             (
diff --git a/legacy/core/src/main/java/com/fsck/k9/preferences/IdentitySettingsUpgrader.kt b/legacy/core/src/main/java/com/fsck/k9/preferences/IdentitySettingsUpgrader.kt
index 26ee7a8d8bf..6e367aad5fb 100644
--- a/legacy/core/src/main/java/com/fsck/k9/preferences/IdentitySettingsUpgrader.kt
+++ b/legacy/core/src/main/java/com/fsck/k9/preferences/IdentitySettingsUpgrader.kt
@@ -1,8 +1,11 @@
 package com.fsck.k9.preferences
 
+import net.thunderbird.core.preference.GeneralSettingsManager
+
 internal class IdentitySettingsUpgrader(
     private val settingsDescriptions: SettingsDescriptions = IdentitySettingsDescriptions.SETTINGS,
     private val upgraders: Map<Int, SettingsUpgrader> = IdentitySettingsDescriptions.UPGRADERS,
+    private val generalSettingsManager: GeneralSettingsManager,
 ) {
     fun upgrade(
         targetVersion: Int,
@@ -19,6 +22,7 @@ internal class IdentitySettingsUpgrader(
             upgraders,
             settingsDescriptions,
             identity.settings,
+            generalSettingsManager,
         )
 
         return identity.copy(settings = upgradedSettings)
diff --git a/legacy/core/src/main/java/com/fsck/k9/preferences/IdentitySettingsWriter.kt b/legacy/core/src/main/java/com/fsck/k9/preferences/IdentitySettingsWriter.kt
index 5046d9a7976..a8fe78d428f 100644
--- a/legacy/core/src/main/java/com/fsck/k9/preferences/IdentitySettingsWriter.kt
+++ b/legacy/core/src/main/java/com/fsck/k9/preferences/IdentitySettingsWriter.kt
@@ -1,22 +1,35 @@
 package com.fsck.k9.preferences
 
+import net.thunderbird.core.preference.GeneralSettingsManager
 import net.thunderbird.core.preference.storage.StorageEditor
 import net.thunderbird.feature.account.storage.legacy.LegacyAccountStorageHandler.Companion.IDENTITY_DESCRIPTION_KEY
 import net.thunderbird.feature.account.storage.legacy.LegacyAccountStorageHandler.Companion.IDENTITY_EMAIL_KEY
 import net.thunderbird.feature.account.storage.legacy.LegacyAccountStorageHandler.Companion.IDENTITY_NAME_KEY
 
-internal class IdentitySettingsWriter {
+internal class IdentitySettingsWriter(private val generalSettingsManager: GeneralSettingsManager) {
     fun write(editor: StorageEditor, accountUuid: String, index: Int, identity: ValidatedSettings.Identity) {
-        editor.putStringWithLogging("$accountUuid.$IDENTITY_NAME_KEY.$index", identity.name)
-        editor.putStringWithLogging("$accountUuid.$IDENTITY_EMAIL_KEY.$index", identity.email)
-        editor.putStringWithLogging("$accountUuid.$IDENTITY_DESCRIPTION_KEY.$index", identity.description)
+        editor.putStringWithLogging(
+            "$accountUuid.$IDENTITY_NAME_KEY.$index",
+            identity.name,
+            generalSettingsManager.getConfig().debugging.isDebugLoggingEnabled,
+        )
+        editor.putStringWithLogging(
+            "$accountUuid.$IDENTITY_EMAIL_KEY.$index",
+            identity.email,
+            generalSettingsManager.getConfig().debugging.isDebugLoggingEnabled,
+        )
+        editor.putStringWithLogging(
+            "$accountUuid.$IDENTITY_DESCRIPTION_KEY.$index",
+            identity.description,
+            generalSettingsManager.getConfig().debugging.isDebugLoggingEnabled,
+        )
 
         // Convert identity settings to the representation used in preference storage
         val stringSettings = IdentitySettingsDescriptions.convert(identity.settings)
 
         for ((identityKey, value) in stringSettings) {
             val key = "$accountUuid.$identityKey.$index"
-            editor.putStringWithLogging(key, value)
+            editor.putStringWithLogging(key, value, generalSettingsManager.getConfig().debugging.isDebugLoggingEnabled)
         }
     }
 }
diff --git a/legacy/core/src/main/java/com/fsck/k9/preferences/KoinModule.kt b/legacy/core/src/main/java/com/fsck/k9/preferences/KoinModule.kt
index 83ed9f02b60..d03c9d52984 100644
--- a/legacy/core/src/main/java/com/fsck/k9/preferences/KoinModule.kt
+++ b/legacy/core/src/main/java/com/fsck/k9/preferences/KoinModule.kt
@@ -2,10 +2,13 @@ package com.fsck.k9.preferences
 
 import com.fsck.k9.Preferences
 import kotlin.time.ExperimentalTime
+import net.thunderbird.core.logging.legacy.DebugLogConfigurator
 import net.thunderbird.core.preference.DefaultPreferenceChangeBroker
 import net.thunderbird.core.preference.GeneralSettingsManager
 import net.thunderbird.core.preference.PreferenceChangeBroker
 import net.thunderbird.core.preference.PreferenceChangePublisher
+import net.thunderbird.core.preference.debugging.DebuggingSettingsPreferenceManager
+import net.thunderbird.core.preference.debugging.DefaultDebuggingSettingsPreferenceManager
 import net.thunderbird.core.preference.display.DefaultDisplaySettingsPreferenceManager
 import net.thunderbird.core.preference.display.DisplaySettingsPreferenceManager
 import net.thunderbird.core.preference.network.DefaultNetworkSettingsPreferenceManager
@@ -63,6 +66,16 @@ val preferencesModule = module {
             storageEditor = get<Preferences>().createStorageEditor(),
         )
     }
+    single<DebuggingSettingsPreferenceManager> {
+        DefaultDebuggingSettingsPreferenceManager(
+            logger = get(),
+            storage = get<Preferences>().storage,
+            storageEditor = get<Preferences>().createStorageEditor(),
+        )
+    }
+    single<DebugLogConfigurator> {
+        DebugLogConfigurator()
+    }
     single {
         DefaultGeneralSettingsManager(
             preferences = get(),
@@ -72,6 +85,8 @@ val preferencesModule = module {
             notificationPreferenceManager = get(),
             displaySettingsSettingsPreferenceManager = get(),
             networkSettingsPreferenceManager = get(),
+            debuggingSettingsPreferenceManager = get(),
+            debugLogConfigurator = get(),
         )
     } bind GeneralSettingsManager::class
     single {
@@ -90,15 +105,16 @@ val preferencesModule = module {
 
     factory { AccountSettingsValidator() }
 
-    factory { IdentitySettingsUpgrader() }
-    factory { FolderSettingsUpgrader() }
-    factory { ServerSettingsUpgrader() }
+    factory { IdentitySettingsUpgrader(generalSettingsManager = get()) }
+    factory { FolderSettingsUpgrader(generalSettingsManager = get()) }
+    factory { ServerSettingsUpgrader(generalSettingsManager = get()) }
 
     factory {
         AccountSettingsUpgrader(
             identitySettingsUpgrader = get(),
             folderSettingsUpgrader = get(),
             serverSettingsUpgrader = get(),
+            generalSettingsManager = get(),
         )
     }
 
@@ -110,6 +126,7 @@ val preferencesModule = module {
             clock = get(),
             serverSettingsDtoSerializer = get(),
             context = get(),
+            generalSettingsManager = get(),
         )
     }
 
diff --git a/legacy/core/src/main/java/com/fsck/k9/preferences/ServerSettingsUpgrader.kt b/legacy/core/src/main/java/com/fsck/k9/preferences/ServerSettingsUpgrader.kt
index 59a6ae4d4d0..9a9e3cac943 100644
--- a/legacy/core/src/main/java/com/fsck/k9/preferences/ServerSettingsUpgrader.kt
+++ b/legacy/core/src/main/java/com/fsck/k9/preferences/ServerSettingsUpgrader.kt
@@ -1,8 +1,11 @@
 package com.fsck.k9.preferences
 
+import net.thunderbird.core.preference.GeneralSettingsManager
+
 internal class ServerSettingsUpgrader(
     private val settingsDescriptions: SettingsDescriptions = ServerSettingsDescriptions.SETTINGS,
     private val upgraders: Map<Int, SettingsUpgrader> = ServerSettingsDescriptions.UPGRADERS,
+    private val generalSettingsManager: GeneralSettingsManager,
 ) {
     fun upgrade(targetVersion: Int, contentVersion: Int, server: ValidatedSettings.Server): ValidatedSettings.Server {
         if (contentVersion == targetVersion) {
@@ -15,6 +18,7 @@ internal class ServerSettingsUpgrader(
             upgraders,
             settingsDescriptions,
             server.settings,
+            generalSettingsManager,
         )
 
         return server.copy(settings = upgradedSettings)
diff --git a/legacy/core/src/main/java/com/fsck/k9/preferences/ServerSettingsWriter.kt b/legacy/core/src/main/java/com/fsck/k9/preferences/ServerSettingsWriter.kt
index c8257ffa916..76cb5965dd3 100644
--- a/legacy/core/src/main/java/com/fsck/k9/preferences/ServerSettingsWriter.kt
+++ b/legacy/core/src/main/java/com/fsck/k9/preferences/ServerSettingsWriter.kt
@@ -10,11 +10,13 @@ import com.fsck.k9.preferences.ServerSettingsDescriptions.HOST
 import com.fsck.k9.preferences.ServerSettingsDescriptions.PASSWORD
 import com.fsck.k9.preferences.ServerSettingsDescriptions.PORT
 import com.fsck.k9.preferences.ServerSettingsDescriptions.USERNAME
+import net.thunderbird.core.preference.GeneralSettingsManager
 import net.thunderbird.core.preference.storage.StorageEditor
 import net.thunderbird.feature.account.storage.legacy.serializer.ServerSettingsDtoSerializer
 
 internal class ServerSettingsWriter(
     private val serverSettingsDtoSerializer: ServerSettingsDtoSerializer,
+    private val generalSettingsManager: GeneralSettingsManager,
 ) {
     fun writeServerSettings(
         editor: StorageEditor,
@@ -23,7 +25,11 @@ internal class ServerSettingsWriter(
     ) {
         val serverSettings = createServerSettings(server)
         val serverSettingsJson = serverSettingsDtoSerializer.serialize(serverSettings)
-        editor.putStringWithLogging(key, serverSettingsJson)
+        editor.putStringWithLogging(
+            key,
+            serverSettingsJson,
+            generalSettingsManager.getConfig().debugging.isDebugLoggingEnabled,
+        )
     }
 
     private fun createServerSettings(server: ValidatedSettings.Server): ServerSettings {
diff --git a/legacy/core/src/main/java/com/fsck/k9/preferences/SettingsUpgradeHelper.kt b/legacy/core/src/main/java/com/fsck/k9/preferences/SettingsUpgradeHelper.kt
index d2290f93d88..64282034d67 100644
--- a/legacy/core/src/main/java/com/fsck/k9/preferences/SettingsUpgradeHelper.kt
+++ b/legacy/core/src/main/java/com/fsck/k9/preferences/SettingsUpgradeHelper.kt
@@ -1,8 +1,8 @@
 package com.fsck.k9.preferences
 
-import com.fsck.k9.K9
 import com.fsck.k9.preferences.Settings.SettingsDescription
 import net.thunderbird.core.logging.legacy.Log
+import net.thunderbird.core.preference.GeneralSettingsManager
 
 internal object SettingsUpgradeHelper {
     /**
@@ -25,8 +25,16 @@ internal object SettingsUpgradeHelper {
         upgraders: Map<Int, SettingsUpgrader>,
         settingsDescriptions: SettingsDescriptions,
         settings: Map<String, Any?>,
+        generalSettingsManager: GeneralSettingsManager,
     ): Map<String, Any?> {
-        return upgradeToVersion(Settings.VERSION, version, upgraders, settingsDescriptions, settings)
+        return upgradeToVersion(
+            Settings.VERSION,
+            version,
+            upgraders,
+            settingsDescriptions,
+            settings,
+            generalSettingsManager,
+        )
     }
 
     fun upgradeToVersion(
@@ -35,13 +43,14 @@ internal object SettingsUpgradeHelper {
         upgraders: Map<Int, SettingsUpgrader>,
         settingsDescriptions: SettingsDescriptions,
         settings: Map<String, Any?>,
+        generalSettingsManager: GeneralSettingsManager,
     ): Map<String, Any?> {
         val upgradedSettings = settings.toMutableMap()
 
         for (toVersion in version + 1..targetVersion) {
             upgraders[toVersion]?.upgrade(upgradedSettings)
 
-            upgradeSettingsGeneric(settingsDescriptions, upgradedSettings, toVersion)
+            upgradeSettingsGeneric(settingsDescriptions, upgradedSettings, toVersion, generalSettingsManager)
         }
 
         return upgradedSettings
@@ -51,6 +60,7 @@ internal object SettingsUpgradeHelper {
         settingsDescriptions: SettingsDescriptions,
         mutableSettings: MutableMap<String, Any?>,
         toVersion: Int,
+        generalSettingsManager: GeneralSettingsManager,
     ) {
         for ((settingName, versionedSettingsDescriptions) in settingsDescriptions) {
             val isNewlyAddedSetting = versionedSettingsDescriptions.firstKey() == toVersion
@@ -63,7 +73,7 @@ internal object SettingsUpgradeHelper {
                 val settingDescription = versionedSettingsDescriptions[toVersion]
                     ?: throw AssertionError("First version of a setting must be non-null!")
 
-                upgradeSettingInsertDefault(mutableSettings, settingName, settingDescription)
+                upgradeSettingInsertDefault(mutableSettings, settingName, settingDescription, generalSettingsManager)
             }
 
             val highestVersion = versionedSettingsDescriptions.lastKey()
@@ -81,11 +91,12 @@ internal object SettingsUpgradeHelper {
         mutableSettings: MutableMap<String, Any?>,
         settingName: String,
         settingDescription: SettingsDescription<T>,
+        generalSettingsManager: GeneralSettingsManager,
     ) {
         val defaultValue = settingDescription.getDefaultValue()
         mutableSettings[settingName] = defaultValue
 
-        if (K9.isDebugLoggingEnabled) {
+        if (generalSettingsManager.getConfig().debugging.isDebugLoggingEnabled) {
             val prettyValue = settingDescription.toPrettyString(defaultValue)
             Log.v("Added new setting '%s' with default value '%s'", settingName, prettyValue)
         }
diff --git a/legacy/core/src/main/java/com/fsck/k9/provider/AttachmentTempFileProvider.java b/legacy/core/src/main/java/com/fsck/k9/provider/AttachmentTempFileProvider.java
index fbb82e6c1f3..c765b4aa635 100644
--- a/legacy/core/src/main/java/com/fsck/k9/provider/AttachmentTempFileProvider.java
+++ b/legacy/core/src/main/java/com/fsck/k9/provider/AttachmentTempFileProvider.java
@@ -18,9 +18,11 @@
 import androidx.annotation.WorkerThread;
 import androidx.core.content.ContextCompat;
 import androidx.core.content.FileProvider;
+import app.k9mail.legacy.di.DI;
 import net.thunderbird.core.logging.legacy.Log;
 
 import com.fsck.k9.K9;
+import net.thunderbird.core.preference.GeneralSettingsManager;
 import okio.ByteString;
 import org.apache.commons.io.IOUtils;
 
@@ -30,6 +32,7 @@ public class AttachmentTempFileProvider extends FileProvider {
     private static final long FILE_DELETE_THRESHOLD_MILLISECONDS = 3 * 60 * 1000;
     private static final Object tempFileWriteMonitor = new Object();
     private static final Object cleanupReceiverMonitor = new Object();
+    private static final GeneralSettingsManager generalSettingsManager = DI.get(GeneralSettingsManager.class);
 
     private static String AUTHORITY;
     private static AttachmentTempFileProviderCleanupReceiver cleanupReceiver = null;
@@ -111,7 +114,7 @@ public static boolean deleteOldTemporaryFiles(Context context) {
                     allFilesDeleted = false;
                 }
             } else {
-                if (K9.isDebugLoggingEnabled()) {
+                if (generalSettingsManager.getConfig().getDebugging().isDebugLoggingEnabled()) {
                     String timeLeftStr = String.format(
                             Locale.ENGLISH, "%.2f", (lastModified - deletionThreshold) / 1000 / 60.0);
                     Log.e("Not deleting temp file (for another %s minutes)", timeLeftStr);
diff --git a/legacy/core/src/main/java/com/fsck/k9/provider/DecryptedFileProvider.java b/legacy/core/src/main/java/com/fsck/k9/provider/DecryptedFileProvider.java
index f8afce7b8c1..15faf13c9cb 100644
--- a/legacy/core/src/main/java/com/fsck/k9/provider/DecryptedFileProvider.java
+++ b/legacy/core/src/main/java/com/fsck/k9/provider/DecryptedFileProvider.java
@@ -20,10 +20,13 @@
 import androidx.core.content.ContextCompat;
 import androidx.core.content.FileProvider;
 import android.text.TextUtils;
+
+import app.k9mail.legacy.di.DI;
 import net.thunderbird.core.logging.legacy.Log;
 
 import com.fsck.k9.K9;
 import com.fsck.k9.mailstore.util.FileFactory;
+import net.thunderbird.core.preference.GeneralSettingsManager;
 import org.apache.james.mime4j.codec.Base64InputStream;
 import org.apache.james.mime4j.codec.QuotedPrintableInputStream;
 import org.apache.james.mime4j.util.MimeUtil;
@@ -37,6 +40,7 @@ public class DecryptedFileProvider extends FileProvider {
 
     private static String AUTHORITY;
     private static DecryptedFileProviderCleanupReceiver cleanupReceiver = null;
+    private static final GeneralSettingsManager generalSettingManager = DI.get(GeneralSettingsManager.class);
 
 
     @Override
@@ -90,7 +94,7 @@ public static boolean deleteOldTemporaryFiles(Context context) {
                     allFilesDeleted = false;
                 }
             } else {
-                if (K9.isDebugLoggingEnabled()) {
+                if (generalSettingManager.getConfig().getDebugging().isDebugLoggingEnabled()) {
                     String timeLeftStr = String.format(
                             Locale.ENGLISH, "%.2f", (lastModified - deletionThreshold) / 1000 / 60.0);
                     Log.e("Not deleting temp file (for another %s minutes)", timeLeftStr);
diff --git a/legacy/storage/src/main/java/com/fsck/k9/storage/KoinModule.kt b/legacy/storage/src/main/java/com/fsck/k9/storage/KoinModule.kt
index d1a8b4e2aa5..c5a5955ead8 100644
--- a/legacy/storage/src/main/java/com/fsck/k9/storage/KoinModule.kt
+++ b/legacy/storage/src/main/java/com/fsck/k9/storage/KoinModule.kt
@@ -14,6 +14,7 @@ val storageModule = module {
             localStoreProvider = get(),
             storageFilesProviderFactory = get(),
             basicPartInfoExtractor = get(),
+            generalSettingsManager = get(),
         )
     }
     single<NotificationStoreProvider> {
diff --git a/legacy/storage/src/main/java/com/fsck/k9/storage/StoreSchemaDefinition.java b/legacy/storage/src/main/java/com/fsck/k9/storage/StoreSchemaDefinition.java
index 559ce412161..3bab948f1a6 100644
--- a/legacy/storage/src/main/java/com/fsck/k9/storage/StoreSchemaDefinition.java
+++ b/legacy/storage/src/main/java/com/fsck/k9/storage/StoreSchemaDefinition.java
@@ -4,6 +4,7 @@
 import android.database.sqlite.SQLiteDatabase;
 
 import com.fsck.k9.K9;
+import com.fsck.k9.core.BuildConfig;
 import com.fsck.k9.mailstore.LockableDatabase.SchemaDefinition;
 import com.fsck.k9.mailstore.MigrationsHelper;
 import com.fsck.k9.storage.migrations.Migrations;
@@ -30,7 +31,7 @@ public void doDbUpgrade(final SQLiteDatabase db) {
         try {
             upgradeDatabase(db);
         } catch (Exception e) {
-            if (K9.DEVELOPER_MODE) {
+            if (BuildConfig.DEBUG) {
                 throw new Error("Exception while upgrading database", e);
             }
 
diff --git a/legacy/storage/src/main/java/com/fsck/k9/storage/messages/AttachmentFileManager.kt b/legacy/storage/src/main/java/com/fsck/k9/storage/messages/AttachmentFileManager.kt
index 64e1ccfcc37..781baace33a 100644
--- a/legacy/storage/src/main/java/com/fsck/k9/storage/messages/AttachmentFileManager.kt
+++ b/legacy/storage/src/main/java/com/fsck/k9/storage/messages/AttachmentFileManager.kt
@@ -1,17 +1,18 @@
 package com.fsck.k9.storage.messages
 
-import com.fsck.k9.K9
 import com.fsck.k9.helper.FileHelper
 import com.fsck.k9.mailstore.StorageFilesProvider
 import java.io.File
 import net.thunderbird.core.logging.legacy.Log
+import net.thunderbird.core.preference.GeneralSettingsManager
 
 internal class AttachmentFileManager(
     private val storageFilesProvider: StorageFilesProvider,
+    private val generalSettingsManager: GeneralSettingsManager,
 ) {
     fun deleteFile(messagePartId: Long) {
         val file = getAttachmentFile(messagePartId)
-        if (file.exists() && !file.delete() && K9.isDebugLoggingEnabled) {
+        if (file.exists() && !file.delete() && generalSettingsManager.getConfig().debugging.isDebugLoggingEnabled) {
             Log.w("Couldn't delete message part file: %s", file.absolutePath)
         }
     }
diff --git a/legacy/storage/src/main/java/com/fsck/k9/storage/messages/K9MessageStore.kt b/legacy/storage/src/main/java/com/fsck/k9/storage/messages/K9MessageStore.kt
index 03678fe9869..17c11355ca2 100644
--- a/legacy/storage/src/main/java/com/fsck/k9/storage/messages/K9MessageStore.kt
+++ b/legacy/storage/src/main/java/com/fsck/k9/storage/messages/K9MessageStore.kt
@@ -14,6 +14,7 @@ import com.fsck.k9.mailstore.LockableDatabase
 import com.fsck.k9.mailstore.StorageFilesProvider
 import com.fsck.k9.message.extractors.BasicPartInfoExtractor
 import java.util.Date
+import net.thunderbird.core.preference.GeneralSettingsManager
 import net.thunderbird.feature.mail.folder.api.FolderDetails
 import net.thunderbird.feature.search.legacy.SearchConditionTreeNode
 
@@ -21,8 +22,9 @@ class K9MessageStore(
     database: LockableDatabase,
     storageFilesProvider: StorageFilesProvider,
     basicPartInfoExtractor: BasicPartInfoExtractor,
+    generalSettingsManager: GeneralSettingsManager,
 ) : MessageStore {
-    private val attachmentFileManager = AttachmentFileManager(storageFilesProvider)
+    private val attachmentFileManager = AttachmentFileManager(storageFilesProvider, generalSettingsManager)
     private val threadMessageOperations = ThreadMessageOperations()
     private val saveMessageOperations = SaveMessageOperations(
         database,
diff --git a/legacy/storage/src/main/java/com/fsck/k9/storage/messages/K9MessageStoreFactory.kt b/legacy/storage/src/main/java/com/fsck/k9/storage/messages/K9MessageStoreFactory.kt
index cae4a4cf93d..202813c7631 100644
--- a/legacy/storage/src/main/java/com/fsck/k9/storage/messages/K9MessageStoreFactory.kt
+++ b/legacy/storage/src/main/java/com/fsck/k9/storage/messages/K9MessageStoreFactory.kt
@@ -7,11 +7,13 @@ import com.fsck.k9.mailstore.NotifierMessageStore
 import com.fsck.k9.mailstore.StorageFilesProviderFactory
 import com.fsck.k9.message.extractors.BasicPartInfoExtractor
 import net.thunderbird.core.android.account.LegacyAccount
+import net.thunderbird.core.preference.GeneralSettingsManager
 
 class K9MessageStoreFactory(
     private val localStoreProvider: LocalStoreProvider,
     private val storageFilesProviderFactory: StorageFilesProviderFactory,
     private val basicPartInfoExtractor: BasicPartInfoExtractor,
+    private val generalSettingsManager: GeneralSettingsManager,
 ) : MessageStoreFactory {
 
     override fun create(account: LegacyAccount): ListenableMessageStore {
@@ -27,6 +29,7 @@ class K9MessageStoreFactory(
             localStore.database,
             storageFilesProvider,
             basicPartInfoExtractor,
+            generalSettingsManager,
         )
         val notifierMessageStore = NotifierMessageStore(messageStore, localStore)
         return ListenableMessageStore(notifierMessageStore)
diff --git a/legacy/ui/legacy/src/main/java/com/fsck/k9/ui/settings/general/GeneralSettingsDataStore.kt b/legacy/ui/legacy/src/main/java/com/fsck/k9/ui/settings/general/GeneralSettingsDataStore.kt
index 42c3466ef81..6f9094ea8fa 100644
--- a/legacy/ui/legacy/src/main/java/com/fsck/k9/ui/settings/general/GeneralSettingsDataStore.kt
+++ b/legacy/ui/legacy/src/main/java/com/fsck/k9/ui/settings/general/GeneralSettingsDataStore.kt
@@ -33,33 +33,44 @@ class GeneralSettingsDataStore(
             "messagelist_stars" -> generalSettingsManager.getConfig().display.isShowMessageListStars
             "messagelist_show_correspondent_names" -> generalSettingsManager.getConfig()
                 .display.isShowCorrespondentNames
+
             "messagelist_sender_above_subject" -> generalSettingsManager.getConfig()
                 .display.isMessageListSenderAboveSubject
+
             "messagelist_show_contact_name" -> generalSettingsManager.getConfig()
                 .display.isShowContactName
+
             "messagelist_change_contact_name_color" -> generalSettingsManager.getConfig()
                 .display.isChangeContactNameColor
+
             "messagelist_show_contact_picture" -> generalSettingsManager.getConfig()
                 .display.isShowContactPicture
+
             "messagelist_colorize_missing_contact_pictures" -> generalSettingsManager.getConfig()
                 .display.isColorizeMissingContactPictures
 
             "messagelist_background_as_unread_indicator" -> generalSettingsManager.getConfig()
                 .display.isUseBackgroundAsUnreadIndicator
+
             "show_compose_button" -> generalSettingsManager.getConfig()
                 .display.isShowComposeButtonOnMessageList
+
             "threaded_view" -> generalSettingsManager.getConfig()
                 .display.isThreadedViewEnabled
+
             "messageview_fixedwidth_font" -> generalSettingsManager.getConfig()
                 .display.isUseMessageViewFixedWidthFont
+
             "messageview_autofit_width" -> generalSettingsManager.getConfig()
                 .display.isAutoFitWidth
+
             "quiet_time_enabled" -> generalSettingsManager.getConfig()
                 .notification.isQuietTimeEnabled
+
             "disable_notifications_during_quiet_time" -> !K9.isNotificationDuringQuietTimeEnabled
             "privacy_hide_useragent" -> generalSettingsManager.getConfig().privacy.isHideUserAgent
             "privacy_hide_timezone" -> generalSettingsManager.getConfig().privacy.isHideTimeZone
-            "debug_logging" -> K9.isDebugLoggingEnabled
+            "debug_logging" -> generalSettingsManager.getConfig().debugging.isDebugLoggingEnabled
             "sync_debug_logging" -> K9.isSyncLoggingEnabled
             "sensitive_logging" -> K9.isSensitiveDebugLoggingEnabled
             "volume_navigation" -> K9.isUseVolumeKeysForNavigation
@@ -99,7 +110,7 @@ class GeneralSettingsDataStore(
             "disable_notifications_during_quiet_time" -> K9.isNotificationDuringQuietTimeEnabled = !value
             "privacy_hide_useragent" -> setIsHideUserAgent(isHideUserAgent = value)
             "privacy_hide_timezone" -> setIsHideTimeZone(isHideTimeZone = value)
-            "debug_logging" -> K9.isDebugLoggingEnabled = value
+            "debug_logging" -> setIsDebugLoggingEnabled(isDebugLoggingEnabled = value)
             "sync_debug_logging" -> K9.isSyncLoggingEnabled = value
             "sensitive_logging" -> K9.isSensitiveDebugLoggingEnabled = value
             "volume_navigation" -> K9.isUseVolumeKeysForNavigation = value
@@ -168,6 +179,7 @@ class GeneralSettingsDataStore(
                 skipSaveSettings = true
                 appLanguageManager.setAppLanguage(value)
             }
+
             "theme" -> setTheme(value)
             "message_compose_theme" -> setMessageComposeTheme(value)
             "messageViewTheme" -> setMessageViewTheme(value)
@@ -456,6 +468,17 @@ class GeneralSettingsDataStore(
         }
     }
 
+    private fun setIsDebugLoggingEnabled(isDebugLoggingEnabled: Boolean) {
+        skipSaveSettings = true
+        generalSettingsManager.update { settings ->
+            settings.copy(
+                debugging = settings.debugging.copy(
+                    isDebugLoggingEnabled = isDebugLoggingEnabled,
+                ),
+            )
+        }
+    }
+
     private fun setIsHideUserAgent(isHideUserAgent: Boolean) {
         skipSaveSettings = true
         generalSettingsManager.update { settings ->


Test patch:
diff --git a/legacy/core/src/test/java/com/fsck/k9/mailstore/LocalStoreTest.java b/legacy/core/src/test/java/com/fsck/k9/mailstore/LocalStoreTest.java
index db28fd6df0a..13fa3b88c9d 100644
--- a/legacy/core/src/test/java/com/fsck/k9/mailstore/LocalStoreTest.java
+++ b/legacy/core/src/test/java/com/fsck/k9/mailstore/LocalStoreTest.java
@@ -7,6 +7,7 @@
 import org.junit.Test;
 
 import static org.junit.Assert.*;
+import static org.mockito.Mockito.mock;
 
 
 public class LocalStoreTest {
@@ -22,7 +23,7 @@ public void findPartById__withRootLocalBodyPart() throws Exception {
 
     @Test
     public void findPartById__withRootLocalMessage() throws Exception {
-        LocalMessage searchRoot = new LocalMessage(null, "uid", null);
+        LocalMessage searchRoot = new LocalMessage(null, "uid", null, mock());
         searchRoot.setMessagePartId(123L);
 
         Part part = LocalStore.findPartById(searchRoot, 123L);
@@ -79,4 +80,4 @@ public void findPartById__withTwoTimesNestedLocalMessagePart() throws Exception
 
         assertSame(needlePart, part);
     }
-}
\ No newline at end of file
+}
diff --git a/legacy/core/src/test/java/com/fsck/k9/message/TextBodyBuilderTest.kt b/legacy/core/src/test/java/com/fsck/k9/message/TextBodyBuilderTest.kt
index 1f47e7ec720..95d32062781 100644
--- a/legacy/core/src/test/java/com/fsck/k9/message/TextBodyBuilderTest.kt
+++ b/legacy/core/src/test/java/com/fsck/k9/message/TextBodyBuilderTest.kt
@@ -5,9 +5,13 @@ import assertk.assertions.isEqualTo
 import com.fsck.k9.message.quote.InsertableHtmlContent
 import net.thunderbird.core.logging.legacy.Log
 import net.thunderbird.core.logging.testing.TestLogger
+import net.thunderbird.core.preference.GeneralSettings
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
+import org.mockito.Mockito.mock
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.mock
 
 @RunWith(Parameterized::class)
 class TextBodyBuilderTest(val testData: TestData) {
@@ -156,7 +160,10 @@ class TextBodyBuilderTest(val testData: TestData) {
 
     init {
         Log.logger = TestLogger()
-        toTest = TextBodyBuilder(MESSAGE_TEXT)
+        toTest = TextBodyBuilder(
+            MESSAGE_TEXT,
+            mock { on { getConfig() } doReturn GeneralSettings() },
+        )
         toTest.setAppendSignature(testData.appendSignature)
         toTest.setIncludeQuotedText(testData.includeQuotedText)
         toTest.setInsertSeparator(testData.insertSeparator)
diff --git a/legacy/core/src/test/java/com/fsck/k9/preferences/AccountSettingsUpgraderTest.kt b/legacy/core/src/test/java/com/fsck/k9/preferences/AccountSettingsUpgraderTest.kt
index 2aaf084a60c..55d68af74ff 100644
--- a/legacy/core/src/test/java/com/fsck/k9/preferences/AccountSettingsUpgraderTest.kt
+++ b/legacy/core/src/test/java/com/fsck/k9/preferences/AccountSettingsUpgraderTest.kt
@@ -8,8 +8,20 @@ import assertk.assertions.prop
 import com.fsck.k9.preferences.Settings.BooleanSetting
 import com.fsck.k9.preferences.Settings.StringSetting
 import kotlin.test.Test
+import net.thunderbird.core.logging.legacy.Log
+import net.thunderbird.core.logging.testing.TestLogger
+import net.thunderbird.core.preference.GeneralSettings
+import org.junit.Before
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.mock
 
 class AccountSettingsUpgraderTest {
+
+    @Before
+    fun setUp() {
+        Log.logger = TestLogger()
+    }
+
     @Suppress("LongMethod")
     @Test
     fun `with combined settings upgrader`() {
@@ -33,6 +45,7 @@ class AccountSettingsUpgraderTest {
                 ),
             ),
             upgraders = emptyMap(),
+            generalSettingsManager = mock { on { getConfig() } doReturn GeneralSettings() },
         )
         val combinedUpgraders = mapOf(
             2 to {
@@ -58,6 +71,7 @@ class AccountSettingsUpgraderTest {
             settingsDescriptions = accountSettingsDescriptions,
             upgraders = emptyMap(),
             combinedUpgraders = combinedUpgraders,
+            generalSettingsManager = mock { on { getConfig() } doReturn GeneralSettings() },
         )
         val account = ValidatedSettings.Account(
             uuid = "irrelevant",
@@ -109,6 +123,7 @@ class AccountSettingsUpgraderTest {
         return IdentitySettingsUpgrader(
             settingsDescriptions = emptyMap(),
             upgraders = emptyMap(),
+            generalSettingsManager = mock { on { getConfig() } doReturn GeneralSettings() },
         )
     }
 
@@ -116,6 +131,7 @@ class AccountSettingsUpgraderTest {
         return ServerSettingsUpgrader(
             settingsDescriptions = emptyMap(),
             upgraders = emptyMap(),
+            generalSettingsManager = mock { on { getConfig() } doReturn GeneralSettings() },
         )
     }
 
diff --git a/legacy/core/src/test/java/com/fsck/k9/preferences/ServerSettingsUpgraderTest.kt b/legacy/core/src/test/java/com/fsck/k9/preferences/ServerSettingsUpgraderTest.kt
index 4cc448880fb..0be0872bb7b 100644
--- a/legacy/core/src/test/java/com/fsck/k9/preferences/ServerSettingsUpgraderTest.kt
+++ b/legacy/core/src/test/java/com/fsck/k9/preferences/ServerSettingsUpgraderTest.kt
@@ -3,9 +3,10 @@ package com.fsck.k9.preferences
 import assertk.assertThat
 import assertk.assertions.isEqualTo
 import kotlin.test.Test
+import org.mockito.kotlin.mock
 
 class ServerSettingsUpgraderTest {
-    private val upgrader = ServerSettingsUpgrader()
+    private val upgrader = ServerSettingsUpgrader(generalSettingsManager = mock())
 
     @Test
     fun `upgrade from version 1 to 92`() {
diff --git a/legacy/core/src/test/java/com/fsck/k9/preferences/SettingsUpgradeHelperTest.kt b/legacy/core/src/test/java/com/fsck/k9/preferences/SettingsUpgradeHelperTest.kt
index 8ceb8ba3cbe..9f829589e7b 100644
--- a/legacy/core/src/test/java/com/fsck/k9/preferences/SettingsUpgradeHelperTest.kt
+++ b/legacy/core/src/test/java/com/fsck/k9/preferences/SettingsUpgradeHelperTest.kt
@@ -10,8 +10,20 @@ import assertk.fail
 import com.fsck.k9.preferences.Settings.BooleanSetting
 import com.fsck.k9.preferences.Settings.StringSetting
 import kotlin.test.Test
+import net.thunderbird.core.logging.legacy.Log
+import net.thunderbird.core.logging.testing.TestLogger
+import net.thunderbird.core.preference.GeneralSettings
+import org.junit.Before
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.mock
 
 class SettingsUpgradeHelperTest {
+
+    @Before
+    fun setUp() {
+        Log.logger = TestLogger()
+    }
+
     @Test
     fun `upgrade() with new setting being added`() {
         val version = 1
@@ -33,6 +45,7 @@ class SettingsUpgradeHelperTest {
             upgraders,
             settingsDescriptions,
             settings,
+            mock { on { getConfig() } doReturn GeneralSettings() },
         )
 
         assertThat(result).isEqualTo(
@@ -65,6 +78,7 @@ class SettingsUpgradeHelperTest {
             upgraders,
             settingsDescriptions,
             settings,
+            mock { on { getConfig() } doReturn GeneralSettings() },
         )
 
         assertThat(result).isEqualTo(
@@ -101,6 +115,7 @@ class SettingsUpgradeHelperTest {
             upgraders,
             settingsDescriptions,
             settings,
+            mock { on { getConfig() } doReturn GeneralSettings() },
         )
 
         assertThat(result).isEqualTo(
@@ -133,6 +148,7 @@ class SettingsUpgradeHelperTest {
             upgraders,
             settingsDescriptions,
             settings,
+            mock { on { getConfig() } doReturn GeneralSettings() },
         )
 
         assertThat(result).isEqualTo(
@@ -162,6 +178,7 @@ class SettingsUpgradeHelperTest {
                 upgraders,
                 settingsDescriptions,
                 settings,
+                mock { on { getConfig() } doReturn GeneralSettings() },
             )
         }.isInstanceOf<AssertionError>()
             .hasMessage("First version of a setting must be non-null!")
@@ -192,6 +209,7 @@ class SettingsUpgradeHelperTest {
             upgraders,
             settingsDescriptions,
             settings,
+            mock { on { getConfig() } doReturn GeneralSettings() },
         )
 
         assertThat(result).isEqualTo(
@@ -234,6 +252,7 @@ class SettingsUpgradeHelperTest {
             upgraders,
             settingsDescriptions,
             settings,
+            mock { on { getConfig() } doReturn GeneralSettings() },
         )
 
         assertThat(result).isEqualTo(
diff --git a/legacy/storage/src/test/java/com/fsck/k9/storage/messages/CopyMessageOperationsTest.kt b/legacy/storage/src/test/java/com/fsck/k9/storage/messages/CopyMessageOperationsTest.kt
index bfac29b2c96..578abccb38f 100644
--- a/legacy/storage/src/test/java/com/fsck/k9/storage/messages/CopyMessageOperationsTest.kt
+++ b/legacy/storage/src/test/java/com/fsck/k9/storage/messages/CopyMessageOperationsTest.kt
@@ -13,6 +13,7 @@ import okio.sink
 import okio.source
 import org.junit.After
 import org.junit.Test
+import org.mockito.kotlin.mock
 
 class CopyMessageOperationsTest : RobolectricTest() {
     private val messagePartDirectory = createRandomTempDirectory()
@@ -22,7 +23,7 @@ class CopyMessageOperationsTest : RobolectricTest() {
         override fun getAttachmentDirectory() = messagePartDirectory
     }
     private val lockableDatabase = createLockableDatabaseMock(sqliteDatabase)
-    private val attachmentFileManager = AttachmentFileManager(storageFilesProvider)
+    private val attachmentFileManager = AttachmentFileManager(storageFilesProvider, mock())
     private val threadMessageOperations = ThreadMessageOperations()
     private val copyMessageOperations = CopyMessageOperations(
         lockableDatabase,
diff --git a/legacy/storage/src/test/java/com/fsck/k9/storage/messages/DeleteFolderOperationsTest.kt b/legacy/storage/src/test/java/com/fsck/k9/storage/messages/DeleteFolderOperationsTest.kt
index 15113a7722b..f9c8b24062b 100644
--- a/legacy/storage/src/test/java/com/fsck/k9/storage/messages/DeleteFolderOperationsTest.kt
+++ b/legacy/storage/src/test/java/com/fsck/k9/storage/messages/DeleteFolderOperationsTest.kt
@@ -10,6 +10,7 @@ import com.fsck.k9.mailstore.StorageFilesProvider
 import com.fsck.k9.storage.RobolectricTest
 import org.junit.After
 import org.junit.Test
+import org.mockito.kotlin.mock
 
 class DeleteFolderOperationsTest : RobolectricTest() {
     private val messagePartDirectory = createRandomTempDirectory()
@@ -19,7 +20,7 @@ class DeleteFolderOperationsTest : RobolectricTest() {
         override fun getAttachmentDirectory() = messagePartDirectory
     }
     private val lockableDatabase = createLockableDatabaseMock(sqliteDatabase)
-    private val attachmentFileManager = AttachmentFileManager(storageFilesProvider)
+    private val attachmentFileManager = AttachmentFileManager(storageFilesProvider, mock())
     private val deleteFolderOperations = DeleteFolderOperations(lockableDatabase, attachmentFileManager)
 
     @After
diff --git a/legacy/storage/src/test/java/com/fsck/k9/storage/messages/DeleteMessageOperationsTest.kt b/legacy/storage/src/test/java/com/fsck/k9/storage/messages/DeleteMessageOperationsTest.kt
index 02161b09c8c..40c7b5343e6 100644
--- a/legacy/storage/src/test/java/com/fsck/k9/storage/messages/DeleteMessageOperationsTest.kt
+++ b/legacy/storage/src/test/java/com/fsck/k9/storage/messages/DeleteMessageOperationsTest.kt
@@ -12,6 +12,7 @@ import com.fsck.k9.mailstore.StorageFilesProvider
 import com.fsck.k9.storage.RobolectricTest
 import org.junit.After
 import org.junit.Test
+import org.mockito.kotlin.mock
 
 class DeleteMessageOperationsTest : RobolectricTest() {
     private val messagePartDirectory = createRandomTempDirectory()
@@ -21,7 +22,7 @@ class DeleteMessageOperationsTest : RobolectricTest() {
         override fun getAttachmentDirectory() = messagePartDirectory
     }
     private val lockableDatabase = createLockableDatabaseMock(sqliteDatabase)
-    private val attachmentFileManager = AttachmentFileManager(storageFilesProvider)
+    private val attachmentFileManager = AttachmentFileManager(storageFilesProvider, mock())
     private val deleteMessageOperations = DeleteMessageOperations(lockableDatabase, attachmentFileManager)
 
     @After
diff --git a/legacy/storage/src/test/java/com/fsck/k9/storage/messages/SaveMessageOperationsTest.kt b/legacy/storage/src/test/java/com/fsck/k9/storage/messages/SaveMessageOperationsTest.kt
index 1ae16da46b9..a6cb14d1ee9 100644
--- a/legacy/storage/src/test/java/com/fsck/k9/storage/messages/SaveMessageOperationsTest.kt
+++ b/legacy/storage/src/test/java/com/fsck/k9/storage/messages/SaveMessageOperationsTest.kt
@@ -26,6 +26,7 @@ import net.thunderbird.core.logging.testing.TestLogger
 import org.junit.After
 import org.junit.Before
 import org.junit.Test
+import org.mockito.Mockito.mock
 
 class SaveMessageOperationsTest : RobolectricTest() {
     private val messagePartDirectory = createRandomTempDirectory()
@@ -35,7 +36,7 @@ class SaveMessageOperationsTest : RobolectricTest() {
         override fun getAttachmentDirectory() = messagePartDirectory
     }
     private val lockableDatabase = createLockableDatabaseMock(sqliteDatabase)
-    private val attachmentFileManager = AttachmentFileManager(storageFilesProvider)
+    private val attachmentFileManager = AttachmentFileManager(storageFilesProvider, mock())
     private val basicPartInfoExtractor = BasicPartInfoExtractor()
     private val threadMessageOperations = ThreadMessageOperations()
     private val saveMessageOperations = SaveMessageOperations(
diff --git a/legacy/ui/legacy/src/test/java/com/fsck/k9/ui/messageview/ViewIntentFinderTest.kt b/legacy/ui/legacy/src/test/java/com/fsck/k9/ui/messageview/ViewIntentFinderTest.kt
index 56b5b2e5a5c..9ca93f9f6cc 100644
--- a/legacy/ui/legacy/src/test/java/com/fsck/k9/ui/messageview/ViewIntentFinderTest.kt
+++ b/legacy/ui/legacy/src/test/java/com/fsck/k9/ui/messageview/ViewIntentFinderTest.kt
@@ -15,7 +15,13 @@ import assertk.assertions.prop
 import com.fsck.k9.provider.AttachmentTempFileProvider
 import kotlin.test.Test
 import net.thunderbird.core.android.testing.RobolectricTest
+import net.thunderbird.core.preference.GeneralSettingsManager
+import org.junit.After
 import org.junit.Before
+import org.koin.core.context.GlobalContext.stopKoin
+import org.koin.core.context.startKoin
+import org.koin.dsl.module
+import org.mockito.kotlin.mock
 import org.robolectric.Robolectric
 import org.robolectric.Shadows.shadowOf
 
@@ -26,11 +32,23 @@ class ViewIntentFinderTest : RobolectricTest() {
 
     @Before
     fun setUp() {
+        startKoin {
+            modules(
+                module {
+                    single { mock<GeneralSettingsManager>() }
+                },
+            )
+        }
         // The AttachmentTempFileProvider methods called by ViewIntentFinder require the AUTHORITY property to be
         // set. The most robust way to accomplish this is to properly initialize the content provider.
         initializeAttachmentTempFileProvider()
     }
 
+    @After
+    fun tearDown() {
+        stopKoin()
+    }
+
     @Test
     fun `provided non-default content type should be preferred`() {
         addViewerAppFor(mimeType = "application/pdf")