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

Issue:
[Account setup] Prefill server text field in manual setup flow
When the app can't find a configuration, users have to manually specify the server settings. In the past we've suggested a server name (e.g. imap.EMAILDOMAIN). The idea was to save the user time typing the server name when there's a good chance our suggestion (partially) matched the actual server name. However, often the name wasn't correct but users assumed the app auto-detected the value. So they went ahead and tapped the "Next" button, only to get an error when checking the server settings.

To avoid the above scenario we could suggest the name ".EMAILDOMAIN" (e.g. `.domain.example` when the user's email address ends in `@domain.example`). It has the advantage of being an invalid hostname. So users will see an error message when tapping the "Next" button without making a change.

![image](https://github.com/thunderbird/thunderbird-android/assets/218061/78764dbb-fb95-4f20-8127-ff6e181718f1)



Discussion hints:
I don't know if that belongs here, but it would be very handy if tunderbird stores the previous server settings for a specific domain and reuses them when the user adds a different account with the same domain.

Pull request: Prefill server text field in manual account setup flow
Fixes #7552  that includes:

1. Prefill server text value when server settings are null for both incoming & outgoing server.
2. Update relevant unit tests.



Test command: ./gradlew :feature:account:server:settings:testDebugUnitTest --tests "app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsStateMapperKtTest" --tests "app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsStateMapperKtTest"

Fix patch:
diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/common/EmailExtensions.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/common/EmailExtensions.kt
new file mode 100644
index 00000000000..485045c2075
--- /dev/null
+++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/common/EmailExtensions.kt
@@ -0,0 +1,3 @@
+package app.k9mail.feature.account.server.settings.ui.common
+
+fun String.toInvalidEmailDomain() = ".${this.substringAfter("@")}"
diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsStateMapper.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsStateMapper.kt
index c5f1e8402f8..a5979fcdcdc 100644
--- a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsStateMapper.kt
+++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsStateMapper.kt
@@ -8,6 +8,7 @@ import app.k9mail.feature.account.common.domain.entity.toConnectionSecurity
 import app.k9mail.feature.account.common.domain.entity.toMailConnectionSecurity
 import app.k9mail.feature.account.common.domain.input.NumberInputField
 import app.k9mail.feature.account.common.domain.input.StringInputField
+import app.k9mail.feature.account.server.settings.ui.common.toInvalidEmailDomain
 import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract.State
 import com.fsck.k9.mail.ServerSettings
 import com.fsck.k9.mail.store.imap.ImapStoreSettings
@@ -19,6 +20,7 @@ import com.fsck.k9.mail.store.imap.ImapStoreSettings.pathPrefix
 fun AccountState.toIncomingServerSettingsState() = incomingServerSettings?.toIncomingServerSettingsState()
     ?: State(
         username = StringInputField(value = emailAddress ?: ""),
+        server = StringInputField(value = emailAddress?.toInvalidEmailDomain() ?: ""),
     )
 
 private fun ServerSettings.toIncomingServerSettingsState(): State {
diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsStateMapper.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsStateMapper.kt
index 4d665c2f674..5475d3789b6 100644
--- a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsStateMapper.kt
+++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsStateMapper.kt
@@ -7,6 +7,7 @@ import app.k9mail.feature.account.common.domain.entity.toConnectionSecurity
 import app.k9mail.feature.account.common.domain.entity.toMailConnectionSecurity
 import app.k9mail.feature.account.common.domain.input.NumberInputField
 import app.k9mail.feature.account.common.domain.input.StringInputField
+import app.k9mail.feature.account.server.settings.ui.common.toInvalidEmailDomain
 import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract.State
 import com.fsck.k9.mail.ServerSettings
 
@@ -17,6 +18,7 @@ fun AccountState.toOutgoingServerSettingsState(): State {
         ?: State(
             username = StringInputField(value = emailAddress ?: ""),
             password = StringInputField(value = password),
+            server = StringInputField(value = emailAddress?.toInvalidEmailDomain() ?: ""),
         )
 }
 


Test patch:
diff --git a/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsStateMapperKtTest.kt b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsStateMapperKtTest.kt
index ccce4248ae3..125f93d1a3c 100644
--- a/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsStateMapperKtTest.kt
+++ b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsStateMapperKtTest.kt
@@ -7,6 +7,7 @@ import app.k9mail.feature.account.common.domain.entity.IncomingProtocolType
 import app.k9mail.feature.account.common.domain.entity.MailConnectionSecurity
 import app.k9mail.feature.account.common.domain.input.NumberInputField
 import app.k9mail.feature.account.common.domain.input.StringInputField
+import app.k9mail.feature.account.server.settings.ui.common.toInvalidEmailDomain
 import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract.State
 import assertk.assertThat
 import assertk.assertions.isEqualTo
@@ -17,10 +18,12 @@ import org.junit.Test
 
 class IncomingServerSettingsStateMapperKtTest {
 
+    @Suppress("MaxLineLength")
     @Test
-    fun `should map to state with email as username when server settings are null`() {
+    fun `should map to state with email as username and emailDomain With dot prefix as server name when server settings are null`() {
+        val email = "test@example.com"
         val accountState = AccountState(
-            emailAddress = "test@example.com",
+            emailAddress = email,
             incomingServerSettings = null,
         )
 
@@ -28,7 +31,8 @@ class IncomingServerSettingsStateMapperKtTest {
 
         assertThat(result).isEqualTo(
             State(
-                username = StringInputField(value = "test@example.com"),
+                username = StringInputField(value = email),
+                server = StringInputField(value = email.toInvalidEmailDomain()),
             ),
         )
     }
diff --git a/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsStateMapperKtTest.kt b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsStateMapperKtTest.kt
index 015914db406..bd4fab829b8 100644
--- a/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsStateMapperKtTest.kt
+++ b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsStateMapperKtTest.kt
@@ -6,6 +6,7 @@ import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity
 import app.k9mail.feature.account.common.domain.entity.MailConnectionSecurity
 import app.k9mail.feature.account.common.domain.input.NumberInputField
 import app.k9mail.feature.account.common.domain.input.StringInputField
+import app.k9mail.feature.account.server.settings.ui.common.toInvalidEmailDomain
 import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract.State
 import assertk.assertThat
 import assertk.assertions.isEqualTo
@@ -15,10 +16,12 @@ import org.junit.Test
 
 class OutgoingServerSettingsStateMapperKtTest {
 
+    @Suppress("MaxLineLength")
     @Test
-    fun `should map to state with email as username when server settings are null`() {
+    fun `should map to state with email as username and emailDomain With dot prefix as server name when server settings are null`() {
+        val email = "test@example.com"
         val accountState = AccountState(
-            emailAddress = "test@example.com",
+            emailAddress = email,
             outgoingServerSettings = null,
         )
 
@@ -26,15 +29,18 @@ class OutgoingServerSettingsStateMapperKtTest {
 
         assertThat(result).isEqualTo(
             State(
-                username = StringInputField(value = "test@example.com"),
+                username = StringInputField(value = email),
+                server = StringInputField(value = email.toInvalidEmailDomain()),
             ),
         )
     }
 
+    @Suppress("MaxLineLength")
     @Test
-    fun `should map to state with password from incomingServerSettings when outgoingServerSettings is null`() {
+    fun `should map to state with password from incomingServerSettings and emailDomain With dot prefix as server name when outgoingServerSettings is null`() {
+        val email = "test@domain.example"
         val accountState = AccountState(
-            emailAddress = "test@domain.example",
+            emailAddress = email,
             incomingServerSettings = IMAP_SERVER_SETTINGS,
             outgoingServerSettings = null,
         )
@@ -43,8 +49,9 @@ class OutgoingServerSettingsStateMapperKtTest {
 
         assertThat(result).isEqualTo(
             State(
-                username = StringInputField(value = "test@domain.example"),
+                username = StringInputField(value = email),
                 password = StringInputField(value = INCOMING_SERVER_PASSWORD),
+                server = StringInputField(value = email.toInvalidEmailDomain()),
             ),
         )
     }