move transport uri encoding into its own class

This commit is contained in:
Vincent Breitmoser 2017-08-23 01:08:31 +02:00
parent b9c0c92e74
commit c4f68b873a
15 changed files with 496 additions and 423 deletions

View file

@ -220,4 +220,21 @@ public class ServerSettings {
return new ServerSettings(type, host, port, connectionSecurity, AuthType.EXTERNAL,
username, password, newAlias);
}
@Override
public boolean equals(Object obj) {
if (! (obj instanceof ServerSettings)) {
return false;
}
ServerSettings that = (ServerSettings) obj;
return type == that.type &&
port == that.port &&
connectionSecurity == that.connectionSecurity &&
authenticationType == that.authenticationType &&
(host == null ? that.host == null : host.equals(that.host)) &&
(username == null ? that.username == null : username.equals(that.username)) &&
(password == null ? that.password == null : password.equals(that.password)) &&
(clientCertificateAlias == null ? that.clientCertificateAlias == null :
clientCertificateAlias.equals(that.clientCertificateAlias));
}
}

View file

@ -16,68 +16,9 @@ public abstract class Transport {
// RFC 1047
protected static final int SOCKET_READ_TIMEOUT = 300000;
/**
* Decodes the contents of transport-specific URIs and puts them into a {@link ServerSettings}
* object.
*
* @param uri
* the transport-specific URI to decode
*
* @return A {@link ServerSettings} object holding the settings contained in the URI.
*
* @see SmtpTransport#decodeUri(String)
* @see WebDavTransport#decodeUri(String)
*/
public static ServerSettings decodeTransportUri(String uri) {
if (uri.startsWith("smtp")) {
return SmtpTransport.decodeUri(uri);
} else if (uri.startsWith("webdav")) {
return WebDavTransport.decodeUri(uri);
} else {
throw new IllegalArgumentException("Not a valid transport URI");
}
}
/**
* Creates a transport URI from the information supplied in the {@link ServerSettings} object.
*
* @param server
* The {@link ServerSettings} object that holds the server settings.
*
* @return A transport URI that holds the same information as the {@code server} parameter.
*
* @see SmtpTransport#createUri(ServerSettings)
* @see WebDavTransport#createUri(ServerSettings)
*/
public static String createTransportUri(ServerSettings server) {
if (Type.SMTP == server.type) {
return SmtpTransport.createUri(server);
} else if (Type.WebDAV == server.type) {
return WebDavTransport.createUri(server);
} else {
throw new IllegalArgumentException("Not a valid transport URI");
}
}
public abstract void open() throws MessagingException;
public abstract void sendMessage(Message message) throws MessagingException;
public abstract void close();
protected static String encodeUtf8(String s) {
try {
return URLEncoder.encode(s, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("UTF-8 not found");
}
}
protected static String decodeUtf8(String s) {
try {
return URLDecoder.decode(s, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("UTF-8 not found");
}
}
}

View file

@ -21,8 +21,7 @@ public class TransportProvider {
String uri = storeConfig.getTransportUri();
if (uri.startsWith("smtp")) {
OAuth2TokenProvider oauth2TokenProvider = null;
return new SmtpTransport(storeConfig, new DefaultTrustedSocketFactory(context),
oauth2TokenProvider);
return new SmtpTransport(storeConfig, new DefaultTrustedSocketFactory(context), oauth2TokenProvider);
} else if (uri.startsWith("webdav")) {
return new WebDavTransport(storeConfig);
} else {

View file

@ -0,0 +1,229 @@
package com.fsck.k9.mail;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import com.fsck.k9.mail.ServerSettings.Type;
import com.fsck.k9.mail.store.webdav.WebDavStore;
public class TransportUris {
/**
* Decodes the contents of transport-specific URIs and puts them into a {@link ServerSettings}
* object.
*
* @param uri
* the transport-specific URI to decode
*
* @return A {@link ServerSettings} object holding the settings contained in the URI.
*/
public static ServerSettings decodeTransportUri(String uri) {
if (uri.startsWith("smtp")) {
return decodeSmtpUri(uri);
} else if (uri.startsWith("webdav")) {
return decodeWebDavUri(uri);
} else {
throw new IllegalArgumentException("Not a valid transport URI");
}
}
/**
* Creates a transport URI from the information supplied in the {@link ServerSettings} object.
*
* @param server
* The {@link ServerSettings} object that holds the server settings.
*
* @return A transport URI that holds the same information as the {@code server} parameter.
*/
public static String createTransportUri(ServerSettings server) {
if (Type.SMTP == server.type) {
return createSmtpUri(server);
} else if (Type.WebDAV == server.type) {
return createWebDavUri(server);
} else {
throw new IllegalArgumentException("Not a valid transport URI");
}
}
/**
* Decodes a SmtpTransport URI.
*
* NOTE: In contrast to ImapStore and Pop3Store, the authType is appended at the end!
*
* <p>Possible forms:</p>
* <pre>
* smtp://user:password:auth@server:port ConnectionSecurity.NONE
* smtp+tls+://user:password:auth@server:port ConnectionSecurity.STARTTLS_REQUIRED
* smtp+ssl+://user:password:auth@server:port ConnectionSecurity.SSL_TLS_REQUIRED
* </pre>
*/
private static ServerSettings decodeSmtpUri(String uri) {
String host;
int port;
ConnectionSecurity connectionSecurity;
AuthType authType = null;
String username = null;
String password = null;
String clientCertificateAlias = null;
URI smtpUri;
try {
smtpUri = new URI(uri);
} catch (URISyntaxException use) {
throw new IllegalArgumentException("Invalid SmtpTransport URI", use);
}
String scheme = smtpUri.getScheme();
/*
* Currently available schemes are:
* smtp
* smtp+tls+
* smtp+ssl+
*
* The following are obsolete schemes that may be found in pre-existing
* settings from earlier versions or that may be found when imported. We
* continue to recognize them and re-map them appropriately:
* smtp+tls
* smtp+ssl
*/
if (scheme.equals("smtp")) {
connectionSecurity = ConnectionSecurity.NONE;
port = ServerSettings.Type.SMTP.defaultPort;
} else if (scheme.startsWith("smtp+tls")) {
connectionSecurity = ConnectionSecurity.STARTTLS_REQUIRED;
port = ServerSettings.Type.SMTP.defaultPort;
} else if (scheme.startsWith("smtp+ssl")) {
connectionSecurity = ConnectionSecurity.SSL_TLS_REQUIRED;
port = ServerSettings.Type.SMTP.defaultTlsPort;
} else {
throw new IllegalArgumentException("Unsupported protocol (" + scheme + ")");
}
host = smtpUri.getHost();
if (smtpUri.getPort() != -1) {
port = smtpUri.getPort();
}
if (smtpUri.getUserInfo() != null) {
String[] userInfoParts = smtpUri.getUserInfo().split(":");
if (userInfoParts.length == 1) {
authType = AuthType.PLAIN;
username = decodeUtf8(userInfoParts[0]);
} else if (userInfoParts.length == 2) {
authType = AuthType.PLAIN;
username = decodeUtf8(userInfoParts[0]);
password = decodeUtf8(userInfoParts[1]);
} else if (userInfoParts.length == 3) {
// NOTE: In SmtpTransport URIs, the authType comes last!
authType = AuthType.valueOf(userInfoParts[2]);
username = decodeUtf8(userInfoParts[0]);
if (authType == AuthType.EXTERNAL) {
clientCertificateAlias = decodeUtf8(userInfoParts[1]);
} else {
password = decodeUtf8(userInfoParts[1]);
}
}
}
return new ServerSettings(ServerSettings.Type.SMTP, host, port, connectionSecurity,
authType, username, password, clientCertificateAlias);
}
/**
* Creates a SmtpTransport URI with the supplied settings.
*
* @param server
* The {@link ServerSettings} object that holds the server settings.
*
* @return A SmtpTransport URI that holds the same information as the {@code server} parameter.
*
* @see com.fsck.k9.mail.store.StoreConfig#getTransportUri()
*/
private static String createSmtpUri(ServerSettings server) {
String userEnc = (server.username != null) ?
encodeUtf8(server.username) : "";
String passwordEnc = (server.password != null) ?
encodeUtf8(server.password) : "";
String clientCertificateAliasEnc = (server.clientCertificateAlias != null) ?
encodeUtf8(server.clientCertificateAlias) : "";
String scheme;
switch (server.connectionSecurity) {
case SSL_TLS_REQUIRED:
scheme = "smtp+ssl+";
break;
case STARTTLS_REQUIRED:
scheme = "smtp+tls+";
break;
default:
case NONE:
scheme = "smtp";
break;
}
String userInfo;
AuthType authType = server.authenticationType;
// NOTE: authType is append at last item, in contrast to ImapStore and Pop3Store!
if (authType != null) {
if (AuthType.EXTERNAL == authType) {
userInfo = userEnc + ":" + clientCertificateAliasEnc + ":" + authType.name();
} else {
userInfo = userEnc + ":" + passwordEnc + ":" + authType.name();
}
} else {
userInfo = userEnc + ":" + passwordEnc;
}
try {
return new URI(scheme, userInfo, server.host, server.port, null, null,
null).toString();
} catch (URISyntaxException e) {
throw new IllegalArgumentException("Can't create SmtpTransport URI", e);
}
}
/**
* Decodes a WebDavTransport URI.
*
* <p>
* <b>Note:</b> Everything related to sending messages via WebDAV is handled by
* {@link WebDavStore}. So the transport URI is the same as the store URI.
* </p>
*/
private static ServerSettings decodeWebDavUri(String uri) {
return WebDavStore.decodeUri(uri);
}
/**
* Creates a WebDavTransport URI.
*
* <p>
* <b>Note:</b> Everything related to sending messages via WebDAV is handled by
* {@link WebDavStore}. So the transport URI is the same as the store URI.
* </p>
*/
private static String createWebDavUri(ServerSettings server) {
return WebDavStore.createUri(server);
}
private static String encodeUtf8(String s) {
try {
return URLEncoder.encode(s, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("UTF-8 not found");
}
}
private static String decodeUtf8(String s) {
try {
return URLDecoder.decode(s, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("UTF-8 not found");
}
}
}

View file

@ -14,32 +14,6 @@ import timber.log.Timber;
import java.util.Collections;
public class WebDavTransport extends Transport {
/**
* Decodes a WebDavTransport URI.
*
* <p>
* <b>Note:</b> Everything related to sending messages via WebDAV is handled by
* {@link WebDavStore}. So the transport URI is the same as the store URI.
* </p>
*/
public static ServerSettings decodeUri(String uri) {
return WebDavStore.decodeUri(uri);
}
/**
* Creates a WebDavTransport URI.
*
* <p>
* <b>Note:</b> Everything related to sending messages via WebDAV is handled by
* {@link WebDavStore}. So the transport URI is the same as the store URI.
* </p>
*/
public static String createUri(ServerSettings server) {
return WebDavStore.createUri(server);
}
private WebDavStore store;
public WebDavTransport(StoreConfig storeConfig) throws MessagingException {

View file

@ -12,8 +12,6 @@ import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.Arrays;
@ -36,7 +34,9 @@ import com.fsck.k9.mail.Message;
import com.fsck.k9.mail.Message.RecipientType;
import com.fsck.k9.mail.MessagingException;
import com.fsck.k9.mail.ServerSettings;
import com.fsck.k9.mail.ServerSettings.Type;
import com.fsck.k9.mail.Transport;
import com.fsck.k9.mail.TransportUris;
import com.fsck.k9.mail.filter.Base64;
import com.fsck.k9.mail.filter.EOLConvertingOutputStream;
import com.fsck.k9.mail.filter.LineWrapOutputStream;
@ -55,151 +55,12 @@ import static com.fsck.k9.mail.CertificateValidationException.Reason.MissingCapa
import static com.fsck.k9.mail.K9MailLib.DEBUG_PROTOCOL_SMTP;
public class SmtpTransport extends Transport {
public static final int SMTP_CONTINUE_REQUEST = 334;
public static final int SMTP_AUTHENTICATION_FAILURE_ERROR_CODE = 535;
private static final int SMTP_CONTINUE_REQUEST = 334;
private static final int SMTP_AUTHENTICATION_FAILURE_ERROR_CODE = 535;
private TrustedSocketFactory mTrustedSocketFactory;
private OAuth2TokenProvider oauthTokenProvider;
/**
* Decodes a SmtpTransport URI.
*
* NOTE: In contrast to ImapStore and Pop3Store, the authType is appended at the end!
*
* <p>Possible forms:</p>
* <pre>
* smtp://user:password:auth@server:port ConnectionSecurity.NONE
* smtp+tls+://user:password:auth@server:port ConnectionSecurity.STARTTLS_REQUIRED
* smtp+ssl+://user:password:auth@server:port ConnectionSecurity.SSL_TLS_REQUIRED
* </pre>
*/
public static ServerSettings decodeUri(String uri) {
String host;
int port;
ConnectionSecurity connectionSecurity;
AuthType authType = null;
String username = null;
String password = null;
String clientCertificateAlias = null;
URI smtpUri;
try {
smtpUri = new URI(uri);
} catch (URISyntaxException use) {
throw new IllegalArgumentException("Invalid SmtpTransport URI", use);
}
String scheme = smtpUri.getScheme();
/*
* Currently available schemes are:
* smtp
* smtp+tls+
* smtp+ssl+
*
* The following are obsolete schemes that may be found in pre-existing
* settings from earlier versions or that may be found when imported. We
* continue to recognize them and re-map them appropriately:
* smtp+tls
* smtp+ssl
*/
if (scheme.equals("smtp")) {
connectionSecurity = ConnectionSecurity.NONE;
port = ServerSettings.Type.SMTP.defaultPort;
} else if (scheme.startsWith("smtp+tls")) {
connectionSecurity = ConnectionSecurity.STARTTLS_REQUIRED;
port = ServerSettings.Type.SMTP.defaultPort;
} else if (scheme.startsWith("smtp+ssl")) {
connectionSecurity = ConnectionSecurity.SSL_TLS_REQUIRED;
port = ServerSettings.Type.SMTP.defaultTlsPort;
} else {
throw new IllegalArgumentException("Unsupported protocol (" + scheme + ")");
}
host = smtpUri.getHost();
if (smtpUri.getPort() != -1) {
port = smtpUri.getPort();
}
if (smtpUri.getUserInfo() != null) {
String[] userInfoParts = smtpUri.getUserInfo().split(":");
if (userInfoParts.length == 1) {
authType = AuthType.PLAIN;
username = decodeUtf8(userInfoParts[0]);
} else if (userInfoParts.length == 2) {
authType = AuthType.PLAIN;
username = decodeUtf8(userInfoParts[0]);
password = decodeUtf8(userInfoParts[1]);
} else if (userInfoParts.length == 3) {
// NOTE: In SmtpTransport URIs, the authType comes last!
authType = AuthType.valueOf(userInfoParts[2]);
username = decodeUtf8(userInfoParts[0]);
if (authType == AuthType.EXTERNAL) {
clientCertificateAlias = decodeUtf8(userInfoParts[1]);
} else {
password = decodeUtf8(userInfoParts[1]);
}
}
}
return new ServerSettings(ServerSettings.Type.SMTP, host, port, connectionSecurity,
authType, username, password, clientCertificateAlias);
}
/**
* Creates a SmtpTransport URI with the supplied settings.
*
* @param server
* The {@link ServerSettings} object that holds the server settings.
*
* @return A SmtpTransport URI that holds the same information as the {@code server} parameter.
*
* @see com.fsck.k9.mail.store.StoreConfig#getTransportUri()
* @see SmtpTransport#decodeUri(String)
*/
public static String createUri(ServerSettings server) {
String userEnc = (server.username != null) ?
encodeUtf8(server.username) : "";
String passwordEnc = (server.password != null) ?
encodeUtf8(server.password) : "";
String clientCertificateAliasEnc = (server.clientCertificateAlias != null) ?
encodeUtf8(server.clientCertificateAlias) : "";
String scheme;
switch (server.connectionSecurity) {
case SSL_TLS_REQUIRED:
scheme = "smtp+ssl+";
break;
case STARTTLS_REQUIRED:
scheme = "smtp+tls+";
break;
default:
case NONE:
scheme = "smtp";
break;
}
String userInfo;
AuthType authType = server.authenticationType;
// NOTE: authType is append at last item, in contrast to ImapStore and Pop3Store!
if (authType != null) {
if (AuthType.EXTERNAL == authType) {
userInfo = userEnc + ":" + clientCertificateAliasEnc + ":" + authType.name();
} else {
userInfo = userEnc + ":" + passwordEnc + ":" + authType.name();
}
} else {
userInfo = userEnc + ":" + passwordEnc;
}
try {
return new URI(scheme, userInfo, server.host, server.port, null, null,
null).toString();
} catch (URISyntaxException e) {
throw new IllegalArgumentException("Can't create SmtpTransport URI", e);
}
}
private String mHost;
private int mPort;
private String mUsername;
@ -219,11 +80,15 @@ public class SmtpTransport extends Transport {
OAuth2TokenProvider oauth2TokenProvider) throws MessagingException {
ServerSettings settings;
try {
settings = decodeUri(storeConfig.getTransportUri());
settings = TransportUris.decodeTransportUri(storeConfig.getTransportUri());
} catch (IllegalArgumentException e) {
throw new MessagingException("Error while decoding transport URI", e);
}
if (settings.type == Type.SMTP) {
throw new IllegalArgumentException("Expected SMTP StoreConfig!");
}
mHost = settings.host;
mPort = settings.port;

View file

@ -0,0 +1,181 @@
package com.fsck.k9.mail;
import android.annotation.SuppressLint;
import org.junit.Test;
import static junit.framework.Assert.assertEquals;
@SuppressLint("AuthLeak")
public class TransportUrisTest {
@Test
public void encodeThenDecode() throws Exception {
ServerSettings serverSettings = new ServerSettings(
ServerSettings.Type.SMTP, "server", 123456,
ConnectionSecurity.STARTTLS_REQUIRED, AuthType.CRAM_MD5,
"user", "password", null);
String uri = TransportUris.createTransportUri(serverSettings);
ServerSettings decodedSettings = TransportUris.decodeTransportUri(uri);
assertEquals(serverSettings, decodedSettings);
}
@Test
public void encodeThenDecode_externalAuth_preservesCert() throws Exception {
ServerSettings serverSettings = new ServerSettings(
ServerSettings.Type.SMTP, "server", 123456,
ConnectionSecurity.NONE, AuthType.EXTERNAL,
"username", null, "clientcert");
String uri = TransportUris.createTransportUri(serverSettings);
ServerSettings decodedSettings = TransportUris.decodeTransportUri(uri);
assertEquals(serverSettings, decodedSettings);
}
@Test
public void decodeTransportUri_canDecodeAuthType() {
String storeUri = "smtp://user:password:PLAIN@server:123456";
ServerSettings result = TransportUris.decodeTransportUri(storeUri);
assertEquals(AuthType.PLAIN, result.authenticationType);
}
@Test
public void decodeTransportUri_canDecodeUsername() {
String storeUri = "smtp://user:password:PLAIN@server:123456";
ServerSettings result = TransportUris.decodeTransportUri(storeUri);
assertEquals("user", result.username);
}
@Test
public void decodeTransportUri_canDecodePassword() {
String storeUri = "smtp://user:password:PLAIN@server:123456";
ServerSettings result = TransportUris.decodeTransportUri(storeUri);
assertEquals("password", result.password);
}
@Test
public void decodeTransportUri_canDecodeUsername_withNoAuthType() {
String storeUri = "smtp://user:password@server:123456";
ServerSettings result = TransportUris.decodeTransportUri(storeUri);
assertEquals("user", result.username);
}
@Test
public void decodeTransportUri_canDecodeUsername_withNoPasswordOrAuthType() {
String storeUri = "smtp://user@server:123456";
ServerSettings result = TransportUris.decodeTransportUri(storeUri);
assertEquals("user", result.username);
}
@Test
public void decodeTransportUri_canDecodeAuthType_withEmptyPassword() {
String storeUri = "smtp://user::PLAIN@server:123456";
ServerSettings result = TransportUris.decodeTransportUri(storeUri);
assertEquals(AuthType.PLAIN, result.authenticationType);
}
@Test
public void decodeTransportUri_canDecodeHost() {
String storeUri = "smtp://user:password:PLAIN@server:123456";
ServerSettings result = TransportUris.decodeTransportUri(storeUri);
assertEquals("server", result.host);
}
@Test
public void decodeTransportUri_canDecodePort() {
String storeUri = "smtp://user:password:PLAIN@server:123456";
ServerSettings result = TransportUris.decodeTransportUri(storeUri);
assertEquals(123456, result.port);
}
@Test
public void decodeTransportUri_canDecodeTLS() {
String storeUri = "smtp+tls+://user:password:PLAIN@server:123456";
ServerSettings result = TransportUris.decodeTransportUri(storeUri);
assertEquals(ConnectionSecurity.STARTTLS_REQUIRED, result.connectionSecurity);
}
@Test
public void decodeTransportUri_canDecodeSSL() {
String storeUri = "smtp+ssl+://user:password:PLAIN@server:123456";
ServerSettings result = TransportUris.decodeTransportUri(storeUri);
assertEquals(ConnectionSecurity.SSL_TLS_REQUIRED, result.connectionSecurity);
}
@Test
public void decodeTransportUri_canDecodeClientCert() {
String storeUri = "smtp+ssl+://user:clientCert:EXTERNAL@server:123456";
ServerSettings result = TransportUris.decodeTransportUri(storeUri);
assertEquals("clientCert", result.clientCertificateAlias);
}
@Test(expected = IllegalArgumentException.class)
public void decodeTransportUri_forUnknownSchema_throwsIllegalArgumentException() {
String storeUri = "unknown://user:clientCert:EXTERNAL@server:123456";
TransportUris.decodeTransportUri(storeUri);
}
@Test
public void createTransportUri_canEncodeSmtpSslUri() {
ServerSettings serverSettings = new ServerSettings(
ServerSettings.Type.SMTP, "server", 123456,
ConnectionSecurity.SSL_TLS_REQUIRED, AuthType.EXTERNAL,
"user", "password", "clientCert");
String result = TransportUris.createTransportUri(serverSettings);
assertEquals("smtp+ssl+://user:clientCert:EXTERNAL@server:123456", result);
}
@Test
public void createTransportUri_canEncodeSmtpTlsUri() {
ServerSettings serverSettings = new ServerSettings(
ServerSettings.Type.SMTP, "server", 123456,
ConnectionSecurity.STARTTLS_REQUIRED, AuthType.PLAIN,
"user", "password", "clientCert");
String result = TransportUris.createTransportUri(serverSettings);
assertEquals("smtp+tls+://user:password:PLAIN@server:123456", result);
}
@Test
public void createTransportUri_canEncodeSmtpUri() {
ServerSettings serverSettings = new ServerSettings(
ServerSettings.Type.SMTP, "server", 123456,
ConnectionSecurity.NONE, AuthType.CRAM_MD5,
"user", "password", "clientCert");
String result = TransportUris.createTransportUri(serverSettings);
assertEquals("smtp://user:password:CRAM_MD5@server:123456", result);
}
}

View file

@ -13,6 +13,7 @@ import com.fsck.k9.mail.Message;
import com.fsck.k9.mail.MessagingException;
import com.fsck.k9.mail.ServerSettings;
import com.fsck.k9.mail.ServerSettings.Type;
import com.fsck.k9.mail.TransportUris;
import com.fsck.k9.mail.XOAuth2ChallengeParserTest;
import com.fsck.k9.mail.filter.Base64;
import com.fsck.k9.mail.helpers.TestMessageBuilder;
@ -718,7 +719,7 @@ public class SmtpTransportTest {
USERNAME,
password,
CLIENT_CERTIFICATE_ALIAS);
String uri = SmtpTransport.createUri(serverSettings);
String uri = TransportUris.createTransportUri(serverSettings);
StoreConfig storeConfig = createStoreConfigWithTransportUri(uri);
return new TestSmtpTransport(storeConfig, socketFactory, oAuth2TokenProvider);

View file

@ -1,158 +0,0 @@
package com.fsck.k9.mail.transport.smtp;
import android.annotation.SuppressLint;
import com.fsck.k9.mail.AuthType;
import com.fsck.k9.mail.ConnectionSecurity;
import com.fsck.k9.mail.ServerSettings;
import com.fsck.k9.mail.transport.smtp.SmtpTransport;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
@SuppressLint("AuthLeak")
public class SmtpTransportUriTest {
@Test
public void decodeUri_canDecodeAuthType() {
String storeUri = "smtp://user:password:PLAIN@server:123456";
ServerSettings result = SmtpTransport.decodeUri(storeUri);
assertEquals(AuthType.PLAIN, result.authenticationType);
}
@Test
public void decodeUri_canDecodeUsername() {
String storeUri = "smtp://user:password:PLAIN@server:123456";
ServerSettings result = SmtpTransport.decodeUri(storeUri);
assertEquals("user", result.username);
}
@Test
public void decodeUri_canDecodePassword() {
String storeUri = "smtp://user:password:PLAIN@server:123456";
ServerSettings result = SmtpTransport.decodeUri(storeUri);
assertEquals("password", result.password);
}
@Test
public void decodeUri_canDecodeUsername_withNoAuthType() {
String storeUri = "smtp://user:password@server:123456";
ServerSettings result = SmtpTransport.decodeUri(storeUri);
assertEquals("user", result.username);
}
@Test
public void decodeUri_canDecodeUsername_withNoPasswordOrAuthType() {
String storeUri = "smtp://user@server:123456";
ServerSettings result = SmtpTransport.decodeUri(storeUri);
assertEquals("user", result.username);
}
@Test
public void decodeUri_canDecodeAuthType_withEmptyPassword() {
String storeUri = "smtp://user::PLAIN@server:123456";
ServerSettings result = SmtpTransport.decodeUri(storeUri);
assertEquals(AuthType.PLAIN, result.authenticationType);
}
@Test
public void decodeUri_canDecodeHost() {
String storeUri = "smtp://user:password:PLAIN@server:123456";
ServerSettings result = SmtpTransport.decodeUri(storeUri);
assertEquals("server", result.host);
}
@Test
public void decodeUri_canDecodePort() {
String storeUri = "smtp://user:password:PLAIN@server:123456";
ServerSettings result = SmtpTransport.decodeUri(storeUri);
assertEquals(123456, result.port);
}
@Test
public void decodeUri_canDecodeTLS() {
String storeUri = "smtp+tls+://user:password:PLAIN@server:123456";
ServerSettings result = SmtpTransport.decodeUri(storeUri);
assertEquals(ConnectionSecurity.STARTTLS_REQUIRED, result.connectionSecurity);
}
@Test
public void decodeUri_canDecodeSSL() {
String storeUri = "smtp+ssl+://user:password:PLAIN@server:123456";
ServerSettings result = SmtpTransport.decodeUri(storeUri);
assertEquals(ConnectionSecurity.SSL_TLS_REQUIRED, result.connectionSecurity);
}
@Test
public void decodeUri_canDecodeClientCert() {
String storeUri = "smtp+ssl+://user:clientCert:EXTERNAL@server:123456";
ServerSettings result = SmtpTransport.decodeUri(storeUri);
assertEquals("clientCert", result.clientCertificateAlias);
}
@Test(expected = IllegalArgumentException.class)
public void decodeUri_forUnknownSchema_throwsIllegalArgumentException() {
String storeUri = "unknown://user:clientCert:EXTERNAL@server:123456";
ServerSettings result = SmtpTransport.decodeUri(storeUri);
}
@Test
public void createUri_canEncodeSmtpSslUri() {
ServerSettings serverSettings = new ServerSettings(
ServerSettings.Type.SMTP, "server", 123456,
ConnectionSecurity.SSL_TLS_REQUIRED, AuthType.EXTERNAL,
"user", "password", "clientCert");
String result = SmtpTransport.createUri(serverSettings);
assertEquals("smtp+ssl+://user:clientCert:EXTERNAL@server:123456", result);
}
@Test
public void createUri_canEncodeSmtpTlsUri() {
ServerSettings serverSettings = new ServerSettings(
ServerSettings.Type.SMTP, "server", 123456,
ConnectionSecurity.STARTTLS_REQUIRED, AuthType.PLAIN,
"user", "password", "clientCert");
String result = SmtpTransport.createUri(serverSettings);
assertEquals("smtp+tls+://user:password:PLAIN@server:123456", result);
}
@Test
public void createUri_canEncodeSmtpUri() {
ServerSettings serverSettings = new ServerSettings(
ServerSettings.Type.SMTP, "server", 123456,
ConnectionSecurity.NONE, AuthType.CRAM_MD5,
"user", "password", "clientCert");
String result = SmtpTransport.createUri(serverSettings);
assertEquals("smtp://user:password:CRAM_MD5@server:123456", result);
}
}

View file

@ -1,6 +1,7 @@
package com.fsck.k9.activity;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
@ -34,7 +35,6 @@ import android.os.Bundle;
import android.os.Handler;
import android.text.Editable;
import android.text.TextWatcher;
import timber.log.Timber;
import android.util.SparseBooleanArray;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
@ -79,7 +79,7 @@ import com.fsck.k9.controller.MessagingController;
import com.fsck.k9.helper.SizeFormatter;
import com.fsck.k9.mail.AuthType;
import com.fsck.k9.mail.ServerSettings;
import com.fsck.k9.mail.Transport;
import com.fsck.k9.mail.TransportUris;
import com.fsck.k9.mail.store.RemoteStore;
import com.fsck.k9.mailstore.StorageManager;
import com.fsck.k9.preferences.SettingsExporter;
@ -94,8 +94,8 @@ import com.fsck.k9.search.SearchAccount;
import com.fsck.k9.search.SearchSpecification.Attribute;
import com.fsck.k9.search.SearchSpecification.SearchField;
import com.fsck.k9.view.ColorChip;
import de.cketti.library.changelog.ChangeLog;
import timber.log.Timber;
public class Accounts extends K9ListActivity implements OnItemClickListener {
@ -771,7 +771,7 @@ public class Accounts extends K9ListActivity implements OnItemClickListener {
private void show(final Accounts activity, boolean restore) {
ServerSettings incoming = RemoteStore.decodeStoreUri(mAccount.getStoreUri());
ServerSettings outgoing = Transport.decodeTransportUri(mAccount.getTransportUri());
ServerSettings outgoing = TransportUris.decodeTransportUri(mAccount.getTransportUri());
/*
* Don't ask for the password to the outgoing server for WebDAV
@ -996,9 +996,9 @@ public class Accounts extends K9ListActivity implements OnItemClickListener {
if (mOutgoingPassword != null) {
// Set outgoing server password
String transportUri = mAccount.getTransportUri();
ServerSettings outgoing = Transport.decodeTransportUri(transportUri);
ServerSettings outgoing = TransportUris.decodeTransportUri(transportUri);
ServerSettings newOutgoing = outgoing.newPassword(mOutgoingPassword);
String newTransportUri = Transport.createTransportUri(newOutgoing);
String newTransportUri = TransportUris.createTransportUri(newOutgoing);
mAccount.setTransportUri(newTransportUri);
}

View file

@ -17,7 +17,6 @@ import android.os.Bundle;
import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
import timber.log.Timber;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
@ -31,6 +30,7 @@ import com.fsck.k9.EmailAddressValidator;
import com.fsck.k9.K9;
import com.fsck.k9.Preferences;
import com.fsck.k9.R;
import com.fsck.k9.account.AccountCreator;
import com.fsck.k9.activity.K9Activity;
import com.fsck.k9.activity.setup.AccountSetupCheckSettings.CheckDirection;
import com.fsck.k9.helper.UrlEncodingHelper;
@ -38,11 +38,11 @@ import com.fsck.k9.helper.Utility;
import com.fsck.k9.mail.AuthType;
import com.fsck.k9.mail.ConnectionSecurity;
import com.fsck.k9.mail.ServerSettings;
import com.fsck.k9.mail.Transport;
import com.fsck.k9.mail.TransportUris;
import com.fsck.k9.mail.store.RemoteStore;
import com.fsck.k9.account.AccountCreator;
import com.fsck.k9.view.ClientCertificateSpinner;
import com.fsck.k9.view.ClientCertificateSpinner.OnClientCertificateChangedListener;
import timber.log.Timber;
/**
* Prompts the user for the email address and password.
@ -412,7 +412,7 @@ public class AccountSetupBasics extends K9Activity
ServerSettings transportServer = new ServerSettings(ServerSettings.Type.SMTP, "mail." + domain, -1,
ConnectionSecurity.SSL_TLS_REQUIRED, authenticationType, user, password, clientCertificateAlias);
String storeUri = RemoteStore.createStoreUri(storeServer);
String transportUri = Transport.createTransportUri(transportServer);
String transportUri = TransportUris.createTransportUri(transportServer);
mAccount.setStoreUri(storeUri);
mAccount.setTransportUri(transportUri);

View file

@ -1,6 +1,12 @@
package com.fsck.k9.activity.setup;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
@ -8,37 +14,41 @@ import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.text.method.DigitsKeyListener;
import timber.log.Timber;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.*;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import com.fsck.k9.*;
import com.fsck.k9.Account;
import com.fsck.k9.Account.FolderMode;
import com.fsck.k9.mail.NetworkType;
import com.fsck.k9.Preferences;
import com.fsck.k9.R;
import com.fsck.k9.account.AccountCreator;
import com.fsck.k9.activity.K9Activity;
import com.fsck.k9.activity.setup.AccountSetupCheckSettings.CheckDirection;
import com.fsck.k9.helper.Utility;
import com.fsck.k9.mail.AuthType;
import com.fsck.k9.mail.ConnectionSecurity;
import com.fsck.k9.mail.NetworkType;
import com.fsck.k9.mail.ServerSettings;
import com.fsck.k9.mail.ServerSettings.Type;
import com.fsck.k9.mail.Store;
import com.fsck.k9.mail.Transport;
import com.fsck.k9.mail.TransportUris;
import com.fsck.k9.mail.store.RemoteStore;
import com.fsck.k9.mail.store.imap.ImapStoreSettings;
import com.fsck.k9.mail.store.webdav.WebDavStoreSettings;
import com.fsck.k9.account.AccountCreator;
import com.fsck.k9.service.MailService;
import com.fsck.k9.view.ClientCertificateSpinner;
import com.fsck.k9.view.ClientCertificateSpinner.OnClientCertificateChangedListener;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;
import timber.log.Timber;
public class AccountSetupIncoming extends K9Activity implements OnClickListener {
private static final String EXTRA_ACCOUNT = "account";
@ -521,7 +531,7 @@ public class AccountSetupIncoming extends K9Activity implements OnClickListener
URI oldUri = new URI(mAccount.getTransportUri());
ServerSettings transportServer = new ServerSettings(Type.SMTP, oldUri.getHost(), oldUri.getPort(),
ConnectionSecurity.SSL_TLS_REQUIRED, authType, username, password, clientCertificateAlias);
String transportUri = Transport.createTransportUri(transportServer);
String transportUri = TransportUris.createTransportUri(transportServer);
mAccount.setTransportUri(transportUri);
} catch (URISyntaxException use) {
/*

View file

@ -1,35 +1,46 @@
package com.fsck.k9.activity.setup;
import java.net.URI;
import java.net.URISyntaxException;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.text.method.DigitsKeyListener;
import timber.log.Timber;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.*;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import com.fsck.k9.*;
import com.fsck.k9.Account;
import com.fsck.k9.Preferences;
import com.fsck.k9.R;
import com.fsck.k9.account.AccountCreator;
import com.fsck.k9.activity.K9Activity;
import com.fsck.k9.activity.setup.AccountSetupCheckSettings.CheckDirection;
import com.fsck.k9.helper.Utility;
import com.fsck.k9.mail.AuthType;
import com.fsck.k9.mail.ServerSettings.Type;
import com.fsck.k9.mail.ConnectionSecurity;
import com.fsck.k9.mail.ServerSettings;
import com.fsck.k9.mail.ServerSettings.Type;
import com.fsck.k9.mail.Transport;
import com.fsck.k9.mail.TransportUris;
import com.fsck.k9.view.ClientCertificateSpinner;
import com.fsck.k9.view.ClientCertificateSpinner.OnClientCertificateChangedListener;
import java.net.URI;
import java.net.URISyntaxException;
import timber.log.Timber;
public class AccountSetupOutgoing extends K9Activity implements OnClickListener,
OnCheckedChangeListener {
@ -135,7 +146,7 @@ public class AccountSetupOutgoing extends K9Activity implements OnClickListener,
}
try {
ServerSettings settings = Transport.decodeTransportUri(mAccount.getTransportUri());
ServerSettings settings = TransportUris.decodeTransportUri(mAccount.getTransportUri());
updateAuthPlainTextFromSecurityType(settings.connectionSecurity);
@ -467,7 +478,7 @@ public class AccountSetupOutgoing extends K9Activity implements OnClickListener,
String newHost = mServerView.getText().toString();
int newPort = Integer.parseInt(mPortView.getText().toString());
ServerSettings server = new ServerSettings(Type.SMTP, newHost, newPort, securityType, authType, username, password, clientCertificateAlias);
uri = Transport.createTransportUri(server);
uri = TransportUris.createTransportUri(server);
mAccount.deleteCertificate(newHost, newPort, CheckDirection.OUTGOING);
mAccount.setTransportUri(uri);
AccountSetupCheckSettings.actionCheckSettings(this, mAccount, CheckDirection.OUTGOING);

View file

@ -20,6 +20,7 @@ import android.content.Context;
import android.net.Uri;
import android.os.Environment;
import com.fsck.k9.mail.TransportUris;
import timber.log.Timber;
import android.util.Xml;
@ -266,7 +267,7 @@ public class SettingsExporter {
// Write outgoing server settings
ServerSettings outgoing = Transport.decodeTransportUri(account.getTransportUri());
ServerSettings outgoing = TransportUris.decodeTransportUri(account.getTransportUri());
serializer.startTag(null, OUTGOING_SERVER_ELEMENT);
serializer.attribute(null, TYPE_ATTRIBUTE, outgoing.type.name());

View file

@ -15,6 +15,8 @@ import android.content.Context;
import android.content.SharedPreferences;
import android.support.annotation.VisibleForTesting;
import android.text.TextUtils;
import com.fsck.k9.mail.TransportUris;
import timber.log.Timber;
import com.fsck.k9.Account;
@ -361,7 +363,7 @@ public class SettingsImporter {
if (account.outgoing != null) {
// Write outgoing server settings (transportUri)
ServerSettings outgoing = new ImportedServerSettings(account.outgoing);
String transportUri = Transport.createTransportUri(outgoing);
String transportUri = TransportUris.createTransportUri(outgoing);
putString(editor, accountKeyPrefix + Account.TRANSPORT_URI_KEY, Base64.encode(transportUri));
/*