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

Issue:
Migrate K9.isHideUserAgent to PreferenceDataStore
The current implementation in Thunderbird Android directly accesses the static field `K9.isHideUserAgent` to determine whether the **User-Agent** header should be removed from outgoing emails. This approach bypasses the modern PreferenceDataStore, which is the preferred mechanism for managing application settings.

This task involves refactoring all direct references to `K9.isHideUserAgent` and replacing them with proper usage of PreferenceDataStore. This will improve consistency, testability, and alignment with the app’s current architecture for preference management.


Discussion hints:
nan

Pull request: Migrate K9.isHideUserAgent to PreferenceDataStore
 - Fixes #9422 
###  Implementation Highlights:
- Migrated `isHideUserAgent` from `K9` to `PrivacySettings`.
- Delegated `isHideUserAgent` value updates to `PrivacySettingsManager`.
-  Replaced static reference of `isHideUserAgent` with access via `generalSettings.privacySettings.isHideUserAgent`.
- Updated tests to reflect the migration of `isHideUserAgent`.

Test command: ./gradlew :legacy:core:testDebugUnitTest --tests "com.fsck.k9.notification.SendFailedNotificationControllerTest" --tests "com.fsck.k9.notification.NotificationContentCreatorTest" --tests "com.fsck.k9.notification.CertificateErrorNotificationControllerTest" --tests "com.fsck.k9.message.quote.QuoteDateFormatterTest" --tests "com.fsck.k9.notification.SummaryNotificationDataCreatorTest" --tests "com.fsck.k9.message.MessageBuilderTest" --tests "com.fsck.k9.helper.MessageHelperTest" --tests "com.fsck.k9.notification.NewMailNotificationManagerTest" --tests "com.fsck.k9.notification.AuthenticationErrorNotificationControllerTest" :legacy:ui:legacy:testDebugUnitTest --tests "com.fsck.k9.message.PgpMessageBuilderTest" :feature:mail:message:list:testDebugUnitTest --tests "net.thunderbird.feature.mail.message.list.domain.usecase.BuildSwipeActionsTest"

Fix patch:
diff --git a/core/preference/api/src/commonMain/kotlin/net/thunderbird/core/preference/privacy/PrivacySettings.kt b/core/preference/api/src/commonMain/kotlin/net/thunderbird/core/preference/privacy/PrivacySettings.kt
index 8ad058942a9..1f871ad4696 100644
--- a/core/preference/api/src/commonMain/kotlin/net/thunderbird/core/preference/privacy/PrivacySettings.kt
+++ b/core/preference/api/src/commonMain/kotlin/net/thunderbird/core/preference/privacy/PrivacySettings.kt
@@ -2,4 +2,5 @@ package net.thunderbird.core.preference.privacy
 
 data class PrivacySettings(
     val isHideTimeZone: Boolean,
+    val isHideUserAgent: Boolean,
 )
diff --git a/core/preference/api/src/commonMain/kotlin/net/thunderbird/core/preference/privacy/PrivacySettingsManager.kt b/core/preference/api/src/commonMain/kotlin/net/thunderbird/core/preference/privacy/PrivacySettingsManager.kt
index 248acfb7b0b..e631a08ff22 100644
--- a/core/preference/api/src/commonMain/kotlin/net/thunderbird/core/preference/privacy/PrivacySettingsManager.kt
+++ b/core/preference/api/src/commonMain/kotlin/net/thunderbird/core/preference/privacy/PrivacySettingsManager.kt
@@ -4,4 +4,5 @@ interface PrivacySettingsManager {
     val privacySettings: PrivacySettings
 
     fun setIsHideTimeZone(isHideTimeZone: Boolean)
+    fun setIsHideUserAgent(isHideUserAgent: Boolean)
 }
diff --git a/core/preference/impl/src/commonMain/kotlin/net/thunderbird/core/preference/privacy/DefaultPrivacySettingsManager.kt b/core/preference/impl/src/commonMain/kotlin/net/thunderbird/core/preference/privacy/DefaultPrivacySettingsManager.kt
index 2d088755001..5ba5bd7d4b3 100644
--- a/core/preference/impl/src/commonMain/kotlin/net/thunderbird/core/preference/privacy/DefaultPrivacySettingsManager.kt
+++ b/core/preference/impl/src/commonMain/kotlin/net/thunderbird/core/preference/privacy/DefaultPrivacySettingsManager.kt
@@ -10,4 +10,9 @@ class DefaultPrivacySettingsManager(
         val privacySettings = preferenceManager.getConfig()
         preferenceManager.save(privacySettings.copy(isHideTimeZone = isHideTimeZone))
     }
+
+    override fun setIsHideUserAgent(isHideUserAgent: Boolean) {
+        val privacySettings = preferenceManager.getConfig()
+        preferenceManager.save(privacySettings.copy(isHideUserAgent = isHideUserAgent))
+    }
 }
diff --git a/core/preference/impl/src/commonMain/kotlin/net/thunderbird/core/preference/privacy/DefaultPrivacySettingsPreferenceManager.kt b/core/preference/impl/src/commonMain/kotlin/net/thunderbird/core/preference/privacy/DefaultPrivacySettingsPreferenceManager.kt
index 4f9c5664b8a..b1dab2446b8 100644
--- a/core/preference/impl/src/commonMain/kotlin/net/thunderbird/core/preference/privacy/DefaultPrivacySettingsPreferenceManager.kt
+++ b/core/preference/impl/src/commonMain/kotlin/net/thunderbird/core/preference/privacy/DefaultPrivacySettingsPreferenceManager.kt
@@ -65,12 +65,14 @@ class DefaultPrivacySettingsPreferenceManager(
 
     private fun loadConfig(): PrivacySettings = PrivacySettings(
         isHideTimeZone = storage.getBoolean(KEY_HIDE_TIME_ZONE, false),
+        isHideUserAgent = storage.getBoolean(KEY_HIDE_USER_AGENT, false),
     )
 
     private fun writeConfig(config: PrivacySettings) {
         scope.launch(ioDispatcher) {
             mutex.withLock {
                 storageEditor.putBoolean(KEY_HIDE_TIME_ZONE, config.isHideTimeZone)
+                storageEditor.putBoolean(KEY_HIDE_USER_AGENT, config.isHideUserAgent)
                 storageEditor.commit()
             }
         }
@@ -78,5 +80,6 @@ class DefaultPrivacySettingsPreferenceManager(
 
     companion object {
         private const val KEY_HIDE_TIME_ZONE = "hideTimeZone"
+        private const val KEY_HIDE_USER_AGENT = "hideUserAgent"
     }
 }
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 dc4b24affed..6e45ac4d618 100644
--- a/legacy/core/src/main/java/com/fsck/k9/K9.kt
+++ b/legacy/core/src/main/java/com/fsck/k9/K9.kt
@@ -197,9 +197,6 @@ object K9 : KoinComponent {
 
     var isNotificationDuringQuietTimeEnabled = true
 
-    @JvmStatic
-    var isHideUserAgent = false
-
     @get:Synchronized
     @set:Synchronized
     @JvmStatic
@@ -296,7 +293,6 @@ object K9 : KoinComponent {
             storage.getEnum("messageViewPostDeleteAction", PostRemoveNavigation.ReturnToMessageList)
         messageViewPostMarkAsUnreadNavigation =
             storage.getEnum("messageViewPostMarkAsUnreadAction", PostMarkAsUnreadNavigation.ReturnToMessageList)
-        isHideUserAgent = storage.getBoolean("hideUserAgent", false)
 
         isConfirmDelete = storage.getBoolean("confirmDelete", false)
         isConfirmDiscardMessage = storage.getBoolean("confirmDiscardMessage", true)
@@ -369,7 +365,6 @@ object K9 : KoinComponent {
         editor.putInt("registeredNameColor", contactNameColor)
         editor.putEnum("messageViewPostDeleteAction", messageViewPostRemoveNavigation)
         editor.putEnum("messageViewPostMarkAsUnreadAction", messageViewPostMarkAsUnreadNavigation)
-        editor.putBoolean("hideUserAgent", isHideUserAgent)
 
         editor.putString("language", k9Language)
 
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 a85433aa2ce..0d81aa46294 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
@@ -34,6 +34,7 @@
 import com.fsck.k9.mail.internet.TextBody;
 import com.fsck.k9.mailstore.TempFileBody;
 import com.fsck.k9.message.quote.InsertableHtmlContent;
+import net.thunderbird.core.preference.GeneralSettingsManager;
 import org.apache.james.mime4j.util.MimeUtil;
 
 
@@ -72,11 +73,17 @@ public abstract class MessageBuilder {
     private boolean isDraft;
     private boolean isPgpInlineEnabled;
 
+    private GeneralSettingsManager settingsManager;
+
     protected MessageBuilder(MessageIdGenerator messageIdGenerator,
-            BoundaryGenerator boundaryGenerator, CoreResourceProvider resourceProvider) {
+            BoundaryGenerator boundaryGenerator,
+            CoreResourceProvider resourceProvider,
+            GeneralSettingsManager settingsManager
+        ) {
         this.messageIdGenerator = messageIdGenerator;
         this.boundaryGenerator = boundaryGenerator;
         this.resourceProvider = resourceProvider;
+        this.settingsManager = settingsManager;
     }
 
     /**
@@ -110,7 +117,7 @@ private void buildHeader(MimeMessage message) throws MessagingException {
             message.setHeader("Return-Receipt-To", from.toEncodedString());
         }
 
-        if (!K9.isHideUserAgent()) {
+        if (!settingsManager.getSettings().getPrivacy().isHideUserAgent()) {
             String encodedUserAgent = MimeHeaderEncoder.encode("User-Agent", resourceProvider.userAgent());
             message.setHeader("User-Agent", encodedUserAgent);
         }
diff --git a/legacy/core/src/main/java/com/fsck/k9/message/PgpMessageBuilder.java b/legacy/core/src/main/java/com/fsck/k9/message/PgpMessageBuilder.java
index 30ab57f4e77..0828a1480fc 100644
--- a/legacy/core/src/main/java/com/fsck/k9/message/PgpMessageBuilder.java
+++ b/legacy/core/src/main/java/com/fsck/k9/message/PgpMessageBuilder.java
@@ -37,6 +37,7 @@
 import com.fsck.k9.mail.internet.MimeUtility;
 import com.fsck.k9.mail.internet.TextBody;
 import com.fsck.k9.mailstore.BinaryMemoryBody;
+import net.thunderbird.core.preference.GeneralSettingsManager;
 import org.apache.commons.io.IOUtils;
 import org.apache.james.mime4j.util.MimeUtil;
 import org.openintents.openpgp.OpenPgpError;
@@ -67,15 +68,16 @@ public static PgpMessageBuilder newInstance() {
         AutocryptOperations autocryptOperations = AutocryptOperations.getInstance();
         AutocryptOpenPgpApiInteractor autocryptOpenPgpApiInteractor = AutocryptOpenPgpApiInteractor.getInstance();
         CoreResourceProvider resourceProvider = DI.get(CoreResourceProvider.class);
+        GeneralSettingsManager settingsManager = DI.get(GeneralSettingsManager.class);
         return new PgpMessageBuilder(messageIdGenerator, boundaryGenerator, autocryptOperations,
-                autocryptOpenPgpApiInteractor, resourceProvider);
+                autocryptOpenPgpApiInteractor, resourceProvider, settingsManager);
     }
 
     @VisibleForTesting
     PgpMessageBuilder(MessageIdGenerator messageIdGenerator, BoundaryGenerator boundaryGenerator,
             AutocryptOperations autocryptOperations, AutocryptOpenPgpApiInteractor autocryptOpenPgpApiInteractor,
-            CoreResourceProvider resourceProvider) {
-        super(messageIdGenerator, boundaryGenerator, resourceProvider);
+            CoreResourceProvider resourceProvider, GeneralSettingsManager settingsManager) {
+        super(messageIdGenerator, boundaryGenerator, resourceProvider, settingsManager);
 
         this.autocryptOperations = autocryptOperations;
         this.autocryptOpenPgpApiInteractor = autocryptOpenPgpApiInteractor;
diff --git a/legacy/core/src/main/java/com/fsck/k9/message/SimpleMessageBuilder.java b/legacy/core/src/main/java/com/fsck/k9/message/SimpleMessageBuilder.java
index 77986c484df..71ec26d84a5 100644
--- a/legacy/core/src/main/java/com/fsck/k9/message/SimpleMessageBuilder.java
+++ b/legacy/core/src/main/java/com/fsck/k9/message/SimpleMessageBuilder.java
@@ -10,6 +10,7 @@
 import com.fsck.k9.mail.MessagingException;
 import com.fsck.k9.mail.internet.MessageIdGenerator;
 import com.fsck.k9.mail.internet.MimeMessage;
+import net.thunderbird.core.preference.GeneralSettingsManager;
 
 
 public class SimpleMessageBuilder extends MessageBuilder {
@@ -18,13 +19,18 @@ public static SimpleMessageBuilder newInstance() {
         MessageIdGenerator messageIdGenerator = MessageIdGenerator.getInstance();
         BoundaryGenerator boundaryGenerator = BoundaryGenerator.getInstance();
         CoreResourceProvider resourceProvider = DI.get(CoreResourceProvider.class);
-        return new SimpleMessageBuilder(messageIdGenerator, boundaryGenerator, resourceProvider);
+        GeneralSettingsManager settingsManager = DI.get(GeneralSettingsManager.class);
+        return new SimpleMessageBuilder(messageIdGenerator, boundaryGenerator, resourceProvider, settingsManager);
     }
 
     @VisibleForTesting
-    SimpleMessageBuilder(MessageIdGenerator messageIdGenerator, BoundaryGenerator boundaryGenerator,
-            CoreResourceProvider resourceProvider) {
-        super(messageIdGenerator, boundaryGenerator, resourceProvider);
+    SimpleMessageBuilder(
+        MessageIdGenerator messageIdGenerator,
+        BoundaryGenerator boundaryGenerator,
+        CoreResourceProvider resourceProvider,
+        GeneralSettingsManager settingsManager
+        ) {
+        super(messageIdGenerator, boundaryGenerator, resourceProvider, settingsManager);
     }
 
     @Override
diff --git a/legacy/core/src/main/java/com/fsck/k9/preferences/RealGeneralSettingsManager.kt b/legacy/core/src/main/java/com/fsck/k9/preferences/RealGeneralSettingsManager.kt
index fb75804a665..e1313f65287 100644
--- a/legacy/core/src/main/java/com/fsck/k9/preferences/RealGeneralSettingsManager.kt
+++ b/legacy/core/src/main/java/com/fsck/k9/preferences/RealGeneralSettingsManager.kt
@@ -240,6 +240,13 @@ internal class RealGeneralSettingsManager(
             .persist()
     }
 
+    override fun setIsHideUserAgent(isHideUserAgent: Boolean) {
+        privacySettingsManager.setIsHideUserAgent(isHideUserAgent)
+        getSettings()
+            .copy(privacy = privacySettings)
+            .persist()
+    }
+
     private fun writeSettings(editor: StorageEditor, settings: GeneralSettings) {
         editor.putBoolean("showRecentChanges", settings.showRecentChanges)
         editor.putEnum("theme", settings.appTheme)
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 14e64a741f4..6930839035f 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
@@ -46,7 +46,7 @@ class GeneralSettingsDataStore(
             "messageview_autofit_width" -> generalSettingsManager.getSettings().isAutoFitWidth
             "quiet_time_enabled" -> generalSettingsManager.getSettings().isQuietTimeEnabled
             "disable_notifications_during_quiet_time" -> !K9.isNotificationDuringQuietTimeEnabled
-            "privacy_hide_useragent" -> K9.isHideUserAgent
+            "privacy_hide_useragent" -> generalSettingsManager.getSettings().privacy.isHideUserAgent
             "privacy_hide_timezone" -> generalSettingsManager.getSettings().privacy.isHideTimeZone
             "debug_logging" -> K9.isDebugLoggingEnabled
             "sync_debug_logging" -> K9.isSyncLoggingEnabled
@@ -86,7 +86,7 @@ class GeneralSettingsDataStore(
             "messageview_autofit_width" -> setIsAutoFitWidth(isAutoFitWidth = value)
             "quiet_time_enabled" -> setIsQuietTimeEnabled(isQuietTimeEnabled = value)
             "disable_notifications_during_quiet_time" -> K9.isNotificationDuringQuietTimeEnabled = !value
-            "privacy_hide_useragent" -> K9.isHideUserAgent = value
+            "privacy_hide_useragent" -> setIsHideUserAgent(isHideUserAgent = value)
             "privacy_hide_timezone" -> setIsHideTimeZone(isHideTimeZone = value)
             "debug_logging" -> K9.isDebugLoggingEnabled = value
             "sync_debug_logging" -> K9.isSyncLoggingEnabled = value
@@ -388,6 +388,13 @@ class GeneralSettingsDataStore(
         )
     }
 
+    private fun setIsHideUserAgent(isHideUserAgent: Boolean) {
+        skipSaveSettings = true
+        generalSettingsManager.setIsHideUserAgent(
+            isHideUserAgent = isHideUserAgent,
+        )
+    }
+
     private fun appThemeToString(theme: AppTheme) = when (theme) {
         AppTheme.LIGHT -> "light"
         AppTheme.DARK -> "dark"


Test patch:
diff --git a/feature/mail/message/list/src/test/kotlin/net/thunderbird/feature/mail/message/list/domain/usecase/BuildSwipeActionsTest.kt b/feature/mail/message/list/src/test/kotlin/net/thunderbird/feature/mail/message/list/domain/usecase/BuildSwipeActionsTest.kt
index 1cf0aecb62f..8f70c61a29b 100644
--- a/feature/mail/message/list/src/test/kotlin/net/thunderbird/feature/mail/message/list/domain/usecase/BuildSwipeActionsTest.kt
+++ b/feature/mail/message/list/src/test/kotlin/net/thunderbird/feature/mail/message/list/domain/usecase/BuildSwipeActionsTest.kt
@@ -57,8 +57,10 @@ class BuildSwipeActionsTest {
             quietTimeEnds = "7:00",
             isQuietTime = false,
             isQuietTimeEnabled = false,
-            privacy = PrivacySettings(isHideTimeZone = false),
-
+            privacy = PrivacySettings(
+                isHideTimeZone = false,
+                isHideUserAgent = false,
+            ),
         )
 
     @Test
@@ -457,6 +459,10 @@ private class FakeGeneralSettingsManager(
     override fun setIsHideTimeZone(isHideTimeZone: Boolean) = error(
         "not implemented",
     )
+
+    override fun setIsHideUserAgent(isHideUserAgent: Boolean) = error(
+        "not implemented",
+    )
 }
 
 private class FakeStorage(
diff --git a/legacy/core/src/test/java/com/fsck/k9/helper/MessageHelperTest.kt b/legacy/core/src/test/java/com/fsck/k9/helper/MessageHelperTest.kt
index f9160543fdf..145f67b437f 100644
--- a/legacy/core/src/test/java/com/fsck/k9/helper/MessageHelperTest.kt
+++ b/legacy/core/src/test/java/com/fsck/k9/helper/MessageHelperTest.kt
@@ -65,7 +65,10 @@ class MessageHelperTest : RobolectricTest() {
                 isQuietTimeEnabled = false,
                 quietTimeEnds = "7:00",
                 quietTimeStarts = "7:00",
-                privacy = PrivacySettings(isHideTimeZone = false),
+                privacy = PrivacySettings(
+                    isHideTimeZone = false,
+                    isHideUserAgent = false,
+                ),
             ),
         )
     }
diff --git a/legacy/core/src/test/java/com/fsck/k9/message/MessageBuilderTest.java b/legacy/core/src/test/java/com/fsck/k9/message/MessageBuilderTest.java
index ecbad6f57a9..be4d4b40642 100644
--- a/legacy/core/src/test/java/com/fsck/k9/message/MessageBuilderTest.java
+++ b/legacy/core/src/test/java/com/fsck/k9/message/MessageBuilderTest.java
@@ -12,6 +12,8 @@
 import java.util.List;
 import java.util.Map;
 
+import androidx.annotation.NonNull;
+import kotlinx.coroutines.flow.Flow;
 import net.thunderbird.core.android.testing.RobolectricTest;
 import net.thunderbird.core.android.account.QuoteStyle;
 import com.fsck.k9.CoreResourceProvider;
@@ -31,6 +33,12 @@
 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.AppTheme;
+import net.thunderbird.core.preference.BackgroundSync;
+import net.thunderbird.core.preference.GeneralSettings;
+import net.thunderbird.core.preference.GeneralSettingsManager;
+import net.thunderbird.core.preference.SubTheme;
+import net.thunderbird.core.preference.privacy.PrivacySettings;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
@@ -197,6 +205,183 @@ public class MessageBuilderTest extends RobolectricTest {
     private BoundaryGenerator boundaryGenerator;
     private CoreResourceProvider resourceProvider = new TestCoreResourceProvider();
     private Callback callback;
+    private final GeneralSettingsManager fakeSettingsManager = new GeneralSettingsManager() {
+        @Override
+        public void setIsHideTimeZone(boolean isHideTimeZone) {
+            throw new UnsupportedOperationException("not implemented");
+        }
+
+        @NonNull
+        @Override
+        public PrivacySettings getPrivacySettings() {
+            throw new UnsupportedOperationException("not implemented");
+        }
+
+        @Override
+        public void setIsQuietTimeEnabled(boolean isQuietTimeEnabled) {
+            throw new UnsupportedOperationException("not implemented");
+        }
+
+        @Override
+        public void setQuietTimeStarts(@NonNull String quietTimeStarts) {
+            throw new UnsupportedOperationException("not implemented");
+        }
+
+        @Override
+        public void setQuietTimeEnds(@NonNull String quietTimeEnds) {
+            throw new UnsupportedOperationException("not implemented");
+        }
+
+        @NonNull
+        @Override
+        public GeneralSettings getSettings() {
+            return new GeneralSettings(
+                BackgroundSync.NEVER,
+                false,
+                AppTheme.FOLLOW_SYSTEM,
+                SubTheme.USE_GLOBAL,
+                SubTheme.USE_GLOBAL,
+                false,
+                false,
+                false,
+                false,
+                false,
+                false,
+                false,
+                false,
+                false,
+                false,
+                false,
+                false,
+                false,
+                false,
+                false,
+                false,
+                false,
+                "07:00",
+                "07:00",
+                false,
+                false,
+                new PrivacySettings(false, false)
+            );
+        }
+
+        @NonNull
+        @Override
+        public Flow<GeneralSettings> getSettingsFlow() {
+            throw new UnsupportedOperationException("not implemented");
+        }
+
+        @Override
+        public void setShowRecentChanges(boolean showRecentChanges) {
+            throw new UnsupportedOperationException("not implemented");
+        }
+
+        @Override
+        public void setAppTheme(@NonNull AppTheme appTheme) {
+            throw new UnsupportedOperationException("not implemented");
+        }
+
+        @Override
+        public void setMessageViewTheme(@NonNull SubTheme subTheme) {
+            throw new UnsupportedOperationException("not implemented");
+        }
+
+        @Override
+        public void setMessageComposeTheme(@NonNull SubTheme subTheme) {
+            throw new UnsupportedOperationException("not implemented");
+        }
+
+        @Override
+        public void setFixedMessageViewTheme(boolean fixedMessageViewTheme) {
+            throw new UnsupportedOperationException("not implemented");
+        }
+
+        @Override
+        public void setIsShowUnifiedInbox(boolean isShowUnifiedInbox) {
+            throw new UnsupportedOperationException("not implemented");
+        }
+
+        @Override
+        public void setIsShowStarredCount(boolean isShowStarredCount) {
+            throw new UnsupportedOperationException("not implemented");
+        }
+
+        @Override
+        public void setIsShowMessageListStars(boolean isShowMessageListStars) {
+            throw new UnsupportedOperationException("not implemented");
+        }
+
+        @Override
+        public void setIsShowAnimations(boolean isShowAnimations) {
+            throw new UnsupportedOperationException("not implemented");
+        }
+
+        @Override
+        public void setIsShowCorrespondentNames(boolean isShowCorrespondentNames) {
+            throw new UnsupportedOperationException("not implemented");
+        }
+
+        @Override
+        public void setSetupArchiveShouldNotShowAgain(boolean shouldShowSetupArchiveFolderDialog) {
+            throw new UnsupportedOperationException("not implemented");
+        }
+
+        @Override
+        public void setIsMessageListSenderAboveSubject(boolean isMessageListSenderAboveSubject) {
+            throw new UnsupportedOperationException("not implemented");
+        }
+
+        @Override
+        public void setIsShowContactName(boolean isShowContactName) {
+            throw new UnsupportedOperationException("not implemented");
+        }
+
+        @Override
+        public void setIsShowContactPicture(boolean isShowContactPicture) {
+            throw new UnsupportedOperationException("not implemented");
+        }
+
+        @Override
+        public void setIsChangeContactNameColor(boolean isChangeContactNameColor) {
+            throw new UnsupportedOperationException("not implemented");
+        }
+
+        @Override
+        public void setIsColorizeMissingContactPictures(boolean isColorizeMissingContactPictures) {
+            throw new UnsupportedOperationException("not implemented");
+        }
+
+        @Override
+        public void setIsUseBackgroundAsUnreadIndicator(boolean isUseBackgroundAsUnreadIndicator) {
+            throw new UnsupportedOperationException("not implemented");
+        }
+
+        @Override
+        public void setIsShowComposeButtonOnMessageList(boolean isShowComposeButtonOnMessageList) {
+            throw new UnsupportedOperationException("not implemented");
+        }
+
+        @Override
+        public void setIsThreadedViewEnabled(boolean isThreadedViewEnabled) {
+            throw new UnsupportedOperationException("not implemented");
+        }
+
+        @Override
+        public void setIsUseMessageViewFixedWidthFont(boolean isUseMessageViewFixedWidthFont) {
+            throw new UnsupportedOperationException("not implemented");
+        }
+
+        @Override
+        public void setIsAutoFitWidth(boolean isAutoFitWidth) {
+            throw new UnsupportedOperationException("not implemented");
+        }
+
+        @Override
+        public void setIsHideUserAgent(boolean isHideUserAgent) {
+            throw new UnsupportedOperationException("not implemented");
+        }
+    };
 
 
     @Before
@@ -345,7 +530,7 @@ public void build_detachAndReattach_shouldSucceed() throws MessagingException {
 
     @Test
     public void buildWithException_shouldThrow() throws MessagingException {
-        MessageBuilder messageBuilder = new SimpleMessageBuilder(messageIdGenerator, boundaryGenerator, resourceProvider) {
+        MessageBuilder messageBuilder = new SimpleMessageBuilder(messageIdGenerator, boundaryGenerator, resourceProvider, fakeSettingsManager) {
             @Override
             protected void buildMessageInternal() {
                 queueMessageBuildException(new MessagingException("expected error"));
@@ -361,7 +546,7 @@ protected void buildMessageInternal() {
     @Test
     public void buildWithException_detachAndReattach_shouldThrow() throws MessagingException {
         Callback anotherCallback = mock(Callback.class);
-        MessageBuilder messageBuilder = new SimpleMessageBuilder(messageIdGenerator, boundaryGenerator, resourceProvider) {
+        MessageBuilder messageBuilder = new SimpleMessageBuilder(messageIdGenerator, boundaryGenerator, resourceProvider, fakeSettingsManager) {
             @Override
             protected void buildMessageInternal() {
                 queueMessageBuildException(new MessagingException("expected error"));
@@ -436,7 +621,7 @@ public boolean isInternalAttachment() {
 
     private MessageBuilder createSimpleMessageBuilder() {
         Identity identity = createIdentity();
-        return new SimpleMessageBuilder(messageIdGenerator, boundaryGenerator, resourceProvider)
+        return new SimpleMessageBuilder(messageIdGenerator, boundaryGenerator, resourceProvider, fakeSettingsManager)
                 .setSubject(TEST_SUBJECT)
                 .setSentDate(SENT_DATE)
                 .setHideTimeZone(true)
diff --git a/legacy/core/src/test/java/com/fsck/k9/message/quote/QuoteDateFormatterTest.kt b/legacy/core/src/test/java/com/fsck/k9/message/quote/QuoteDateFormatterTest.kt
index 27a626eabba..997bd8bc272 100644
--- a/legacy/core/src/test/java/com/fsck/k9/message/quote/QuoteDateFormatterTest.kt
+++ b/legacy/core/src/test/java/com/fsck/k9/message/quote/QuoteDateFormatterTest.kt
@@ -30,7 +30,10 @@ class QuoteDateFormatterTest {
         messageViewTheme = SubTheme.USE_GLOBAL,
         messageComposeTheme = SubTheme.USE_GLOBAL,
         fixedMessageViewTheme = false,
-        privacy = PrivacySettings(isHideTimeZone = false),
+        privacy = PrivacySettings(
+            isHideTimeZone = false,
+            isHideUserAgent = false,
+        ),
         isAutoFitWidth = false,
         isThreadedViewEnabled = false,
         isUseMessageViewFixedWidthFont = false,
diff --git a/legacy/core/src/test/java/com/fsck/k9/notification/AuthenticationErrorNotificationControllerTest.kt b/legacy/core/src/test/java/com/fsck/k9/notification/AuthenticationErrorNotificationControllerTest.kt
index b593cd00fbf..8953df7a2b9 100644
--- a/legacy/core/src/test/java/com/fsck/k9/notification/AuthenticationErrorNotificationControllerTest.kt
+++ b/legacy/core/src/test/java/com/fsck/k9/notification/AuthenticationErrorNotificationControllerTest.kt
@@ -149,7 +149,10 @@ class AuthenticationErrorNotificationControllerTest : RobolectricTest() {
                     quietTimeStarts = "7:00",
                     quietTimeEnds = "7:00",
                     isQuietTimeEnabled = false,
-                    privacy = PrivacySettings(isHideTimeZone = false),
+                    privacy = PrivacySettings(
+                        isHideTimeZone = false,
+                        isHideUserAgent = false,
+                    ),
                 )
             },
         ) {
diff --git a/legacy/core/src/test/java/com/fsck/k9/notification/CertificateErrorNotificationControllerTest.kt b/legacy/core/src/test/java/com/fsck/k9/notification/CertificateErrorNotificationControllerTest.kt
index 282f3b48966..2898088354e 100644
--- a/legacy/core/src/test/java/com/fsck/k9/notification/CertificateErrorNotificationControllerTest.kt
+++ b/legacy/core/src/test/java/com/fsck/k9/notification/CertificateErrorNotificationControllerTest.kt
@@ -149,7 +149,10 @@ class CertificateErrorNotificationControllerTest : RobolectricTest() {
                 quietTimeStarts = "7:00",
                 quietTimeEnds = "7:00",
                 isQuietTimeEnabled = false,
-                privacy = PrivacySettings(isHideTimeZone = false),
+                privacy = PrivacySettings(
+                    isHideTimeZone = false,
+                    isHideUserAgent = false,
+                ),
             )
         },
     ) {
diff --git a/legacy/core/src/test/java/com/fsck/k9/notification/NewMailNotificationManagerTest.kt b/legacy/core/src/test/java/com/fsck/k9/notification/NewMailNotificationManagerTest.kt
index 536c4851e2d..294ec651e99 100644
--- a/legacy/core/src/test/java/com/fsck/k9/notification/NewMailNotificationManagerTest.kt
+++ b/legacy/core/src/test/java/com/fsck/k9/notification/NewMailNotificationManagerTest.kt
@@ -79,7 +79,10 @@ class NewMailNotificationManagerTest {
                     quietTimeStarts = "7:00",
                     quietTimeEnds = "7:00",
                     isQuietTimeEnabled = false,
-                    privacy = PrivacySettings(isHideTimeZone = false),
+                    privacy = PrivacySettings(
+                        isHideTimeZone = false,
+                        isHideUserAgent = false,
+                    ),
                 )
             },
         ),
diff --git a/legacy/core/src/test/java/com/fsck/k9/notification/NotificationContentCreatorTest.kt b/legacy/core/src/test/java/com/fsck/k9/notification/NotificationContentCreatorTest.kt
index 188ee045aaa..e1666bb04bc 100644
--- a/legacy/core/src/test/java/com/fsck/k9/notification/NotificationContentCreatorTest.kt
+++ b/legacy/core/src/test/java/com/fsck/k9/notification/NotificationContentCreatorTest.kt
@@ -175,7 +175,10 @@ class NotificationContentCreatorTest : RobolectricTest() {
                     quietTimeStarts = "7:00",
                     quietTimeEnds = "7:00",
                     isQuietTimeEnabled = false,
-                    privacy = PrivacySettings(isHideTimeZone = false),
+                    privacy = PrivacySettings(
+                        isHideTimeZone = false,
+                        isHideUserAgent = false,
+                    ),
                 )
             },
         )
diff --git a/legacy/core/src/test/java/com/fsck/k9/notification/SendFailedNotificationControllerTest.kt b/legacy/core/src/test/java/com/fsck/k9/notification/SendFailedNotificationControllerTest.kt
index 0cc1cd394e2..b5445be8826 100644
--- a/legacy/core/src/test/java/com/fsck/k9/notification/SendFailedNotificationControllerTest.kt
+++ b/legacy/core/src/test/java/com/fsck/k9/notification/SendFailedNotificationControllerTest.kt
@@ -66,7 +66,10 @@ class SendFailedNotificationControllerTest : RobolectricTest() {
                 quietTimeStarts = "7:00",
                 quietTimeEnds = "7:00",
                 isQuietTimeEnabled = false,
-                privacy = PrivacySettings(isHideTimeZone = false),
+                privacy = PrivacySettings(
+                    isHideTimeZone = false,
+                    isHideUserAgent = false,
+                ),
             )
         },
     )
diff --git a/legacy/core/src/test/java/com/fsck/k9/notification/SummaryNotificationDataCreatorTest.kt b/legacy/core/src/test/java/com/fsck/k9/notification/SummaryNotificationDataCreatorTest.kt
index 915fbc2e23b..0588f75a633 100644
--- a/legacy/core/src/test/java/com/fsck/k9/notification/SummaryNotificationDataCreatorTest.kt
+++ b/legacy/core/src/test/java/com/fsck/k9/notification/SummaryNotificationDataCreatorTest.kt
@@ -58,7 +58,10 @@ class SummaryNotificationDataCreatorTest {
         quietTimeStarts = "0:00",
         quietTimeEnds = "23:59",
         isQuietTimeEnabled = false,
-        privacy = PrivacySettings(isHideTimeZone = false),
+        privacy = PrivacySettings(
+            isHideTimeZone = false,
+            isHideUserAgent = false,
+        ),
     )
     private val notificationDataCreator = SummaryNotificationDataCreator(
         singleMessageNotificationDataCreator = SingleMessageNotificationDataCreator(),
diff --git a/legacy/ui/legacy/src/test/java/com/fsck/k9/message/PgpMessageBuilderTest.kt b/legacy/ui/legacy/src/test/java/com/fsck/k9/message/PgpMessageBuilderTest.kt
index 6050742351c..6f2cd48b9ad 100644
--- a/legacy/ui/legacy/src/test/java/com/fsck/k9/message/PgpMessageBuilderTest.kt
+++ b/legacy/ui/legacy/src/test/java/com/fsck/k9/message/PgpMessageBuilderTest.kt
@@ -46,10 +46,17 @@ import com.fsck.k9.message.quote.InsertableHtmlContent
 import com.fsck.k9.view.RecipientSelectView
 import java.io.OutputStream
 import java.util.Date
+import kotlinx.coroutines.flow.Flow
 import net.thunderbird.core.android.account.Identity
 import net.thunderbird.core.android.account.QuoteStyle
 import net.thunderbird.core.logging.legacy.Log
 import net.thunderbird.core.logging.testing.TestLogger
+import net.thunderbird.core.preference.AppTheme
+import net.thunderbird.core.preference.BackgroundSync
+import net.thunderbird.core.preference.GeneralSettings
+import net.thunderbird.core.preference.GeneralSettingsManager
+import net.thunderbird.core.preference.SubTheme
+import net.thunderbird.core.preference.privacy.PrivacySettings
 import org.apache.james.mime4j.util.MimeUtil
 import org.junit.Before
 import org.junit.Test
@@ -774,6 +781,7 @@ class PgpMessageBuilderTest : K9RobolectricTest() {
                 AutocryptOperations.getInstance(),
                 autocryptOpenPgpApiInteractor,
                 resourceProvider,
+                fakeGeneralSettingsManager,
             )
             builder.setOpenPgpApi(openPgpApi)
 
@@ -837,5 +845,105 @@ class PgpMessageBuilderTest : K9RobolectricTest() {
                 }
             }
         }
+
+        private val fakeGeneralSettingsManager = object : GeneralSettingsManager {
+            override fun getSettings() = GeneralSettings(
+                backgroundSync = BackgroundSync.NEVER,
+                showRecentChanges = false,
+                appTheme = AppTheme.FOLLOW_SYSTEM,
+                messageViewTheme = SubTheme.USE_GLOBAL,
+                messageComposeTheme = SubTheme.USE_GLOBAL,
+                fixedMessageViewTheme = false,
+                isShowUnifiedInbox = false,
+                isShowStarredCount = false,
+                isShowMessageListStars = false,
+                isShowAnimations = false,
+                isShowCorrespondentNames = false,
+                shouldShowSetupArchiveFolderDialog = false,
+                isMessageListSenderAboveSubject = false,
+                isShowContactName = false,
+                isShowContactPicture = false,
+                isChangeContactNameColor = false,
+                isColorizeMissingContactPictures = false,
+                isUseBackgroundAsUnreadIndicator = false,
+                isShowComposeButtonOnMessageList = false,
+                isThreadedViewEnabled = false,
+                isUseMessageViewFixedWidthFont = false,
+                isAutoFitWidth = false,
+                privacy = PrivacySettings(isHideUserAgent = false, isHideTimeZone = false),
+                quietTimeEnds = "07:00",
+                quietTimeStarts = "07:00",
+                isQuietTimeEnabled = false,
+                isQuietTime = false,
+            )
+
+            override fun getSettingsFlow(): Flow<GeneralSettings> = error("not implemented")
+
+            override fun setShowRecentChanges(showRecentChanges: Boolean) = error("not implemented")
+
+            override fun setAppTheme(appTheme: AppTheme) = error("not implemented")
+
+            override fun setMessageViewTheme(subTheme: SubTheme) = error("not implemented")
+
+            override fun setMessageComposeTheme(subTheme: SubTheme) = error("not implemented")
+
+            override fun setFixedMessageViewTheme(fixedMessageViewTheme: Boolean) = error("not implemented")
+
+            override fun setIsShowUnifiedInbox(isShowUnifiedInbox: Boolean) = error("not implemented")
+
+            override fun setIsShowStarredCount(isShowStarredCount: Boolean) = error("not implemented")
+
+            override fun setIsShowMessageListStars(isShowMessageListStars: Boolean) = error("not implemented")
+
+            override fun setIsShowAnimations(isShowAnimations: Boolean) = error("not implemented")
+
+            override fun setIsShowCorrespondentNames(isShowCorrespondentNames: Boolean) = error("not implemented")
+
+            override fun setSetupArchiveShouldNotShowAgain(shouldShowSetupArchiveFolderDialog: Boolean) = error(
+                "not implemented",
+            )
+
+            override fun setIsMessageListSenderAboveSubject(isMessageListSenderAboveSubject: Boolean) = error(
+                "not implemented",
+            )
+
+            override fun setIsShowContactName(isShowContactName: Boolean) = error("not implemented")
+
+            override fun setIsShowContactPicture(isShowContactPicture: Boolean) = error("not implemented")
+
+            override fun setIsChangeContactNameColor(isChangeContactNameColor: Boolean) = error("not implemented")
+
+            override fun setIsColorizeMissingContactPictures(isColorizeMissingContactPictures: Boolean) = error(
+                "not implemented",
+            )
+
+            override fun setIsUseBackgroundAsUnreadIndicator(isUseBackgroundAsUnreadIndicator: Boolean) = error(
+                "not implemented",
+            )
+
+            override fun setIsShowComposeButtonOnMessageList(isShowComposeButtonOnMessageList: Boolean) = error(
+                "not implemented",
+            )
+
+            override fun setIsThreadedViewEnabled(isThreadedViewEnabled: Boolean) = error("not implemented")
+
+            override fun setIsUseMessageViewFixedWidthFont(isUseMessageViewFixedWidthFont: Boolean) = error(
+                "not implemented",
+            )
+
+            override fun setIsAutoFitWidth(isAutoFitWidth: Boolean) = error("not implemented")
+            override fun setQuietTimeEnds(quietTimeEnds: String) = error("not implemented")
+
+            override fun setQuietTimeStarts(quietTimeStarts: String) = error("not implemented")
+
+            override fun setIsQuietTimeEnabled(isQuietTimeEnabled: Boolean) = error("not implemented")
+
+            override val privacySettings: PrivacySettings
+                get() = error("not implemented")
+
+            override fun setIsHideTimeZone(isHideTimeZone: Boolean) = error("not implemented")
+
+            override fun setIsHideUserAgent(isHideUserAgent: Boolean) = error("not implemented")
+        }
     }
 }