0
0
mirror of https://github.com/thunderbird/thunderbird-android.git synced 2024-09-19 19:52:14 +02:00

Introduce AuthType.NONE

Previously "don't authenticate" was encoded using any `AuthType` value and an empty username.
This commit is contained in:
cketti 2024-06-25 14:33:49 +02:00
parent e1cec023ea
commit 86c0cd579f
8 changed files with 57 additions and 53 deletions

View File

@ -39,7 +39,7 @@ enum class AuthenticationType(
fun AuthenticationType.toAuthType(): AuthType {
return when (this) {
AuthenticationType.None -> AuthType.PLAIN
AuthenticationType.None -> AuthType.NONE
AuthenticationType.PasswordCleartext -> AuthType.PLAIN
AuthenticationType.PasswordEncrypted -> AuthType.CRAM_MD5
AuthenticationType.ClientCertificate -> AuthType.EXTERNAL
@ -53,6 +53,6 @@ fun AuthType.toAuthenticationType(): AuthenticationType {
AuthType.CRAM_MD5 -> AuthenticationType.PasswordEncrypted
AuthType.EXTERNAL -> AuthenticationType.ClientCertificate
AuthType.XOAUTH2 -> AuthenticationType.OAuth2
else -> AuthenticationType.None
AuthType.NONE -> AuthenticationType.None
}
}

View File

@ -20,7 +20,7 @@ class AuthenticationTypeTest {
AuthenticationType.PasswordEncrypted -> AuthType.CRAM_MD5
AuthenticationType.OAuth2 -> AuthType.XOAUTH2
AuthenticationType.ClientCertificate -> AuthType.EXTERNAL
else -> AuthType.PLAIN
AuthenticationType.None -> AuthType.NONE
},
)
}
@ -39,7 +39,7 @@ class AuthenticationTypeTest {
AuthType.CRAM_MD5 -> AuthenticationType.PasswordEncrypted
AuthType.EXTERNAL -> AuthenticationType.ClientCertificate
AuthType.XOAUTH2 -> AuthenticationType.OAuth2
else -> AuthenticationType.None
AuthType.NONE -> AuthenticationType.None
},
)
}

View File

@ -23,7 +23,11 @@ fun AccountState.toOutgoingServerSettingsState(): State {
}
private fun AccountState.getOutgoingServerPassword(): String {
return outgoingServerSettings?.password ?: incomingServerSettings?.password ?: ""
return if (outgoingServerSettings?.authenticationType?.toAuthenticationType()?.isPasswordRequired == false) {
""
} else {
outgoingServerSettings?.password ?: incomingServerSettings?.password ?: ""
}
}
private fun ServerSettings.toOutgoingServerSettingsState(password: String): State {

View File

@ -63,7 +63,7 @@ class OutgoingServerSettingsStateMapperKtTest {
}
@Test
fun `should use password from incomingServerSettings when outgoingServerSettings contains no password`() {
fun `should use password from incomingServerSettings when outgoingServerSettings is missing a password`() {
val accountState = AccountState(
incomingServerSettings = IMAP_SERVER_SETTINGS,
outgoingServerSettings = SMTP_SERVER_SETTINGS.copy(password = null),

View File

@ -22,4 +22,5 @@ public enum AuthType {
* https://developers.google.com/gmail/xoauth2_protocol#the_sasl_xoauth2_mechanism
*/
XOAUTH2,
NONE,
}

View File

@ -15,9 +15,10 @@ data class ServerSettings @JvmOverloads constructor(
val extra: Map<String, String?> = emptyMap(),
) {
val isMissingCredentials: Boolean = when (authenticationType) {
AuthType.NONE -> false
AuthType.EXTERNAL -> clientCertificateAlias == null
AuthType.XOAUTH2 -> username.isBlank()
else -> username.isNotBlank() && password == null
else -> username.isBlank() || password.isNullOrBlank()
}
init {

View File

@ -147,50 +147,48 @@ class SmtpTransport(
}
parseOptionalSizeValue(extensions["SIZE"])
if (
username.isNotEmpty() &&
(!password.isNullOrEmpty() || AuthType.EXTERNAL == authType || AuthType.XOAUTH2 == authType)
) {
when (authType) {
AuthType.PLAIN -> {
// try saslAuthPlain first, because it supports UTF-8 explicitly
if (authPlainSupported) {
saslAuthPlain()
} else if (authLoginSupported) {
saslAuthLogin()
} else {
throw MissingCapabilityException("AUTH PLAIN")
}
when (authType) {
AuthType.NONE -> {
// The outgoing server is configured to not use any authentication. So do nothing.
}
AuthType.PLAIN -> {
// try saslAuthPlain first, because it supports UTF-8 explicitly
if (authPlainSupported) {
saslAuthPlain()
} else if (authLoginSupported) {
saslAuthLogin()
} else {
throw MissingCapabilityException("AUTH PLAIN")
}
AuthType.CRAM_MD5 -> {
if (authCramMD5Supported) {
saslAuthCramMD5()
} else {
throw MissingCapabilityException("AUTH CRAM-MD5")
}
}
AuthType.CRAM_MD5 -> {
if (authCramMD5Supported) {
saslAuthCramMD5()
} else {
throw MissingCapabilityException("AUTH CRAM-MD5")
}
AuthType.XOAUTH2 -> {
if (oauthTokenProvider == null) {
throw MessagingException("No OAuth2TokenProvider available.")
} else if (authOAuthBearerSupported) {
saslOAuth(OAuthMethod.OAUTHBEARER)
} else if (authXoauth2Supported) {
saslOAuth(OAuthMethod.XOAUTH2)
} else {
throw MissingCapabilityException("AUTH OAUTHBEARER")
}
}
AuthType.XOAUTH2 -> {
if (oauthTokenProvider == null) {
throw MessagingException("No OAuth2TokenProvider available.")
} else if (authOAuthBearerSupported) {
saslOAuth(OAuthMethod.OAUTHBEARER)
} else if (authXoauth2Supported) {
saslOAuth(OAuthMethod.XOAUTH2)
} else {
throw MissingCapabilityException("AUTH OAUTHBEARER")
}
AuthType.EXTERNAL -> {
if (authExternalSupported) {
saslAuthExternal()
} else {
throw MissingCapabilityException("AUTH EXTERNAL")
}
}
else -> {
throw MessagingException("Unhandled authentication method found in server settings (bug).")
}
AuthType.EXTERNAL -> {
if (authExternalSupported) {
saslAuthExternal()
} else {
throw MissingCapabilityException("AUTH EXTERNAL")
}
}
else -> {
throw MessagingException("Unhandled authentication method found in server settings (bug).")
}
}
} catch (e: MessagingException) {
close()

View File

@ -39,14 +39,14 @@ class SmtpTransportTest {
private val oAuth2TokenProvider = createMockOAuth2TokenProvider()
@Test
fun `open() should provide hostname`() {
fun `open() should issue EHLO command`() {
val server = MockSmtpServer().apply {
output("220 localhost Simple Mail Transfer Service Ready")
expect("EHLO [127.0.0.1]")
output("250-localhost Hello client.localhost")
output("250 OK")
}
val transport = startServerAndCreateSmtpTransport(server, password = null)
val transport = startServerAndCreateSmtpTransportWithoutAuthentication(server)
transport.open()
@ -55,14 +55,14 @@ class SmtpTransportTest {
}
@Test
fun `open() without AUTH LOGIN extension should connect without authentication`() {
fun `open() without AUTH LOGIN extension should connect when not using authentication`() {
val server = MockSmtpServer().apply {
output("220 localhost Simple Mail Transfer Service Ready")
expect("EHLO [127.0.0.1]")
output("250-localhost Hello client.localhost")
output("250 OK")
}
val transport = startServerAndCreateSmtpTransportWithoutPassword(server)
val transport = startServerAndCreateSmtpTransportWithoutAuthentication(server)
transport.open()
@ -473,7 +473,7 @@ class SmtpTransportTest {
expect("HELO [127.0.0.1]")
output("250 localhost")
}
val transport = startServerAndCreateSmtpTransportWithoutPassword(server)
val transport = startServerAndCreateSmtpTransportWithoutAuthentication(server)
transport.open()
@ -885,8 +885,8 @@ class SmtpTransportTest {
server.verifyInteractionCompleted()
}
private fun startServerAndCreateSmtpTransportWithoutPassword(server: MockSmtpServer): SmtpTransport {
return startServerAndCreateSmtpTransport(server, AuthType.PLAIN, ConnectionSecurity.NONE, null)
private fun startServerAndCreateSmtpTransportWithoutAuthentication(server: MockSmtpServer): SmtpTransport {
return startServerAndCreateSmtpTransport(server, AuthType.NONE, ConnectionSecurity.NONE, password = null)
}
private fun startServerAndCreateSmtpTransport(