Merge pull request #2695 from k9mail/cleanup-smtp-transport
Cleanup smtp transport
This commit is contained in:
commit
cfd5d8a301
15 changed files with 596 additions and 544 deletions
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
229
k9mail-library/src/main/java/com/fsck/k9/mail/TransportUris.java
Normal file
229
k9mail-library/src/main/java/com/fsck/k9/mail/TransportUris.java
Normal 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");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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,203 +55,73 @@ 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 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 static final int SMTP_CONTINUE_REQUEST = 334;
|
||||
private static final int SMTP_AUTHENTICATION_FAILURE_ERROR_CODE = 535;
|
||||
|
||||
|
||||
private String mHost;
|
||||
private int mPort;
|
||||
private String mUsername;
|
||||
private String mPassword;
|
||||
private String mClientCertificateAlias;
|
||||
private AuthType mAuthType;
|
||||
private ConnectionSecurity mConnectionSecurity;
|
||||
private Socket mSocket;
|
||||
private PeekableInputStream mIn;
|
||||
private OutputStream mOut;
|
||||
private boolean m8bitEncodingAllowed;
|
||||
private boolean mEnhancedStatusCodesProvided;
|
||||
private int mLargestAcceptableMessage;
|
||||
private final TrustedSocketFactory trustedSocketFactory;
|
||||
private final OAuth2TokenProvider oauthTokenProvider;
|
||||
|
||||
private final String host;
|
||||
private final int port;
|
||||
private final String username;
|
||||
private final String password;
|
||||
private final String clientCertificateAlias;
|
||||
private final AuthType authType;
|
||||
private final ConnectionSecurity connectionSecurity;
|
||||
|
||||
|
||||
private Socket socket;
|
||||
private PeekableInputStream inputStream;
|
||||
private OutputStream outputStream;
|
||||
private boolean is8bitEncodingAllowed;
|
||||
private boolean isEnhancedStatusCodesProvided;
|
||||
private int largestAcceptableMessage;
|
||||
private boolean retryXoauthWithNewToken;
|
||||
|
||||
|
||||
public SmtpTransport(StoreConfig storeConfig, TrustedSocketFactory trustedSocketFactory,
|
||||
OAuth2TokenProvider oauth2TokenProvider) throws MessagingException {
|
||||
OAuth2TokenProvider oauthTokenProvider) 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);
|
||||
}
|
||||
|
||||
mHost = settings.host;
|
||||
mPort = settings.port;
|
||||
if (settings.type != Type.SMTP) {
|
||||
throw new IllegalArgumentException("Expected SMTP StoreConfig!");
|
||||
}
|
||||
|
||||
mConnectionSecurity = settings.connectionSecurity;
|
||||
host = settings.host;
|
||||
port = settings.port;
|
||||
|
||||
mAuthType = settings.authenticationType;
|
||||
mUsername = settings.username;
|
||||
mPassword = settings.password;
|
||||
mClientCertificateAlias = settings.clientCertificateAlias;
|
||||
mTrustedSocketFactory = trustedSocketFactory;
|
||||
oauthTokenProvider = oauth2TokenProvider;
|
||||
connectionSecurity = settings.connectionSecurity;
|
||||
|
||||
authType = settings.authenticationType;
|
||||
username = settings.username;
|
||||
password = settings.password;
|
||||
clientCertificateAlias = settings.clientCertificateAlias;
|
||||
|
||||
this.trustedSocketFactory = trustedSocketFactory;
|
||||
this.oauthTokenProvider = oauthTokenProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open() throws MessagingException {
|
||||
try {
|
||||
boolean secureConnection = false;
|
||||
InetAddress[] addresses = InetAddress.getAllByName(mHost);
|
||||
InetAddress[] addresses = InetAddress.getAllByName(host);
|
||||
for (int i = 0; i < addresses.length; i++) {
|
||||
try {
|
||||
SocketAddress socketAddress = new InetSocketAddress(addresses[i], mPort);
|
||||
if (mConnectionSecurity == ConnectionSecurity.SSL_TLS_REQUIRED) {
|
||||
mSocket = mTrustedSocketFactory.createSocket(null, mHost, mPort, mClientCertificateAlias);
|
||||
mSocket.connect(socketAddress, SOCKET_CONNECT_TIMEOUT);
|
||||
SocketAddress socketAddress = new InetSocketAddress(addresses[i], port);
|
||||
if (connectionSecurity == ConnectionSecurity.SSL_TLS_REQUIRED) {
|
||||
socket = trustedSocketFactory.createSocket(null, host, port, clientCertificateAlias);
|
||||
socket.connect(socketAddress, SOCKET_CONNECT_TIMEOUT);
|
||||
secureConnection = true;
|
||||
} else {
|
||||
mSocket = new Socket();
|
||||
mSocket.connect(socketAddress, SOCKET_CONNECT_TIMEOUT);
|
||||
socket = new Socket();
|
||||
socket.connect(socketAddress, SOCKET_CONNECT_TIMEOUT);
|
||||
}
|
||||
} catch (SocketException e) {
|
||||
if (i < (addresses.length - 1)) {
|
||||
|
@ -264,15 +134,15 @@ public class SmtpTransport extends Transport {
|
|||
}
|
||||
|
||||
// RFC 1047
|
||||
mSocket.setSoTimeout(SOCKET_READ_TIMEOUT);
|
||||
socket.setSoTimeout(SOCKET_READ_TIMEOUT);
|
||||
|
||||
mIn = new PeekableInputStream(new BufferedInputStream(mSocket.getInputStream(), 1024));
|
||||
mOut = new BufferedOutputStream(mSocket.getOutputStream(), 1024);
|
||||
inputStream = new PeekableInputStream(new BufferedInputStream(socket.getInputStream(), 1024));
|
||||
outputStream = new BufferedOutputStream(socket.getOutputStream(), 1024);
|
||||
|
||||
// Eat the banner
|
||||
executeCommand(null);
|
||||
|
||||
InetAddress localAddress = mSocket.getLocalAddress();
|
||||
InetAddress localAddress = socket.getLocalAddress();
|
||||
String localHost = getCanonicalHostName(localAddress);
|
||||
String ipAddr = localAddress.getHostAddress();
|
||||
|
||||
|
@ -293,22 +163,22 @@ public class SmtpTransport extends Transport {
|
|||
|
||||
Map<String, String> extensions = sendHello(localHost);
|
||||
|
||||
m8bitEncodingAllowed = extensions.containsKey("8BITMIME");
|
||||
mEnhancedStatusCodesProvided = extensions.containsKey("ENHANCEDSTATUSCODES");
|
||||
is8bitEncodingAllowed = extensions.containsKey("8BITMIME");
|
||||
isEnhancedStatusCodesProvided = extensions.containsKey("ENHANCEDSTATUSCODES");
|
||||
|
||||
if (mConnectionSecurity == ConnectionSecurity.STARTTLS_REQUIRED) {
|
||||
if (connectionSecurity == ConnectionSecurity.STARTTLS_REQUIRED) {
|
||||
if (extensions.containsKey("STARTTLS")) {
|
||||
executeCommand("STARTTLS");
|
||||
|
||||
mSocket = mTrustedSocketFactory.createSocket(
|
||||
mSocket,
|
||||
mHost,
|
||||
mPort,
|
||||
mClientCertificateAlias);
|
||||
socket = trustedSocketFactory.createSocket(
|
||||
socket,
|
||||
host,
|
||||
port,
|
||||
clientCertificateAlias);
|
||||
|
||||
mIn = new PeekableInputStream(new BufferedInputStream(mSocket.getInputStream(),
|
||||
inputStream = new PeekableInputStream(new BufferedInputStream(socket.getInputStream(),
|
||||
1024));
|
||||
mOut = new BufferedOutputStream(mSocket.getOutputStream(), 1024);
|
||||
outputStream = new BufferedOutputStream(socket.getOutputStream(), 1024);
|
||||
/*
|
||||
* Now resend the EHLO. Required by RFC2487 Sec. 5.2, and more specifically,
|
||||
* Exim.
|
||||
|
@ -343,12 +213,12 @@ public class SmtpTransport extends Transport {
|
|||
}
|
||||
parseOptionalSizeValue(extensions);
|
||||
|
||||
if (!TextUtils.isEmpty(mUsername)
|
||||
&& (!TextUtils.isEmpty(mPassword) ||
|
||||
AuthType.EXTERNAL == mAuthType ||
|
||||
AuthType.XOAUTH2 == mAuthType)) {
|
||||
if (!TextUtils.isEmpty(username)
|
||||
&& (!TextUtils.isEmpty(password) ||
|
||||
AuthType.EXTERNAL == authType ||
|
||||
AuthType.XOAUTH2 == authType)) {
|
||||
|
||||
switch (mAuthType) {
|
||||
switch (authType) {
|
||||
|
||||
/*
|
||||
* LOGIN is an obsolete option which is unavailable to users,
|
||||
|
@ -359,9 +229,9 @@ public class SmtpTransport extends Transport {
|
|||
case PLAIN:
|
||||
// try saslAuthPlain first, because it supports UTF-8 explicitly
|
||||
if (authPlainSupported) {
|
||||
saslAuthPlain(mUsername, mPassword);
|
||||
saslAuthPlain();
|
||||
} else if (authLoginSupported) {
|
||||
saslAuthLogin(mUsername, mPassword);
|
||||
saslAuthLogin();
|
||||
} else {
|
||||
throw new MessagingException(
|
||||
"Authentication methods SASL PLAIN and LOGIN are unavailable.");
|
||||
|
@ -370,21 +240,21 @@ public class SmtpTransport extends Transport {
|
|||
|
||||
case CRAM_MD5:
|
||||
if (authCramMD5Supported) {
|
||||
saslAuthCramMD5(mUsername, mPassword);
|
||||
saslAuthCramMD5();
|
||||
} else {
|
||||
throw new MessagingException("Authentication method CRAM-MD5 is unavailable.");
|
||||
}
|
||||
break;
|
||||
case XOAUTH2:
|
||||
if (authXoauth2Supported && oauthTokenProvider != null) {
|
||||
saslXoauth2(mUsername);
|
||||
saslXoauth2();
|
||||
} else {
|
||||
throw new MessagingException("Authentication method XOAUTH2 is unavailable.");
|
||||
}
|
||||
break;
|
||||
case EXTERNAL:
|
||||
if (authExternalSupported) {
|
||||
saslAuthExternal(mUsername);
|
||||
saslAuthExternal();
|
||||
} else {
|
||||
/*
|
||||
* Some SMTP servers are known to provide no error
|
||||
|
@ -409,17 +279,17 @@ public class SmtpTransport extends Transport {
|
|||
if (secureConnection) {
|
||||
// try saslAuthPlain first, because it supports UTF-8 explicitly
|
||||
if (authPlainSupported) {
|
||||
saslAuthPlain(mUsername, mPassword);
|
||||
saslAuthPlain();
|
||||
} else if (authLoginSupported) {
|
||||
saslAuthLogin(mUsername, mPassword);
|
||||
saslAuthLogin();
|
||||
} else if (authCramMD5Supported) {
|
||||
saslAuthCramMD5(mUsername, mPassword);
|
||||
saslAuthCramMD5();
|
||||
} else {
|
||||
throw new MessagingException("No supported authentication methods available.");
|
||||
}
|
||||
} else {
|
||||
if (authCramMD5Supported) {
|
||||
saslAuthCramMD5(mUsername, mPassword);
|
||||
saslAuthCramMD5();
|
||||
} else {
|
||||
/*
|
||||
* We refuse to insecurely transmit the password
|
||||
|
@ -457,9 +327,9 @@ public class SmtpTransport extends Transport {
|
|||
private void parseOptionalSizeValue(Map<String, String> extensions) {
|
||||
if (extensions.containsKey("SIZE")) {
|
||||
String optionalsizeValue = extensions.get("SIZE");
|
||||
if (optionalsizeValue != null && optionalsizeValue != "") {
|
||||
if (optionalsizeValue != null && !"".equals(optionalsizeValue)) {
|
||||
try {
|
||||
mLargestAcceptableMessage = Integer.parseInt(optionalsizeValue);
|
||||
largestAcceptableMessage = Integer.parseInt(optionalsizeValue);
|
||||
} catch (NumberFormatException e) {
|
||||
if (K9MailLib.isDebug() && DEBUG_PROTOCOL_SMTP) {
|
||||
Timber.d(e, "Tried to parse %s and get an int", optionalsizeValue);
|
||||
|
@ -490,7 +360,7 @@ public class SmtpTransport extends Transport {
|
|||
* In case of a malformed response.
|
||||
*/
|
||||
private Map<String, String> sendHello(String host) throws IOException, MessagingException {
|
||||
Map<String, String> extensions = new HashMap<String, String>();
|
||||
Map<String, String> extensions = new HashMap<>();
|
||||
try {
|
||||
List<String> results = executeCommand("EHLO %s", host).results;
|
||||
// Remove the EHLO greeting response
|
||||
|
@ -515,7 +385,7 @@ public class SmtpTransport extends Transport {
|
|||
|
||||
@Override
|
||||
public void sendMessage(Message message) throws MessagingException {
|
||||
List<Address> addresses = new ArrayList<Address>();
|
||||
List<Address> addresses = new ArrayList<>();
|
||||
{
|
||||
addresses.addAll(Arrays.asList(message.getRecipients(RecipientType.TO)));
|
||||
addresses.addAll(Arrays.asList(message.getRecipients(RecipientType.CC)));
|
||||
|
@ -523,14 +393,13 @@ public class SmtpTransport extends Transport {
|
|||
}
|
||||
message.setRecipients(RecipientType.BCC, null);
|
||||
|
||||
Map<String, List<String>> charsetAddressesMap =
|
||||
new HashMap<String, List<String>>();
|
||||
Map<String, List<String>> charsetAddressesMap = new HashMap<>();
|
||||
for (Address address : addresses) {
|
||||
String addressString = address.getAddress();
|
||||
String charset = CharsetSupport.getCharsetFromAddress(addressString);
|
||||
List<String> addressesOfCharset = charsetAddressesMap.get(charset);
|
||||
if (addressesOfCharset == null) {
|
||||
addressesOfCharset = new ArrayList<String>();
|
||||
addressesOfCharset = new ArrayList<>();
|
||||
charsetAddressesMap.put(charset, addressesOfCharset);
|
||||
}
|
||||
addressesOfCharset.add(addressString);
|
||||
|
@ -550,13 +419,13 @@ public class SmtpTransport extends Transport {
|
|||
close();
|
||||
open();
|
||||
|
||||
if (!m8bitEncodingAllowed) {
|
||||
if (!is8bitEncodingAllowed) {
|
||||
Timber.d("Server does not support 8bit transfer encoding");
|
||||
}
|
||||
// If the message has attachments and our server has told us about a limit on
|
||||
// the size of messages, count the message's size before sending it
|
||||
if (mLargestAcceptableMessage > 0 && message.hasAttachments()) {
|
||||
if (message.calculateSize() > mLargestAcceptableMessage) {
|
||||
if (largestAcceptableMessage > 0 && message.hasAttachments()) {
|
||||
if (message.calculateSize() > largestAcceptableMessage) {
|
||||
throw new MessagingException("Message too large for server", true);
|
||||
}
|
||||
}
|
||||
|
@ -565,7 +434,7 @@ public class SmtpTransport extends Transport {
|
|||
Address[] from = message.getFrom();
|
||||
try {
|
||||
String fromAddress = from[0].getAddress();
|
||||
if (m8bitEncodingAllowed) {
|
||||
if (is8bitEncodingAllowed) {
|
||||
executeCommand("MAIL FROM:<%s> BODY=8BITMIME", fromAddress);
|
||||
} else {
|
||||
executeCommand("MAIL FROM:<%s>", fromAddress);
|
||||
|
@ -578,7 +447,7 @@ public class SmtpTransport extends Transport {
|
|||
executeCommand("DATA");
|
||||
|
||||
EOLConvertingOutputStream msgOut = new EOLConvertingOutputStream(
|
||||
new LineWrapOutputStream(new SmtpDataStuffing(mOut), 1000));
|
||||
new LineWrapOutputStream(new SmtpDataStuffing(outputStream), 1000));
|
||||
|
||||
message.writeTo(msgOut);
|
||||
msgOut.endWithCrLfAndFlush();
|
||||
|
@ -603,26 +472,25 @@ public class SmtpTransport extends Transport {
|
|||
try {
|
||||
executeCommand("QUIT");
|
||||
} catch (Exception e) {
|
||||
|
||||
// don't care
|
||||
}
|
||||
IOUtils.closeQuietly(mIn);
|
||||
IOUtils.closeQuietly(mOut);
|
||||
IOUtils.closeQuietly(mSocket);
|
||||
mIn = null;
|
||||
mOut = null;
|
||||
mSocket = null;
|
||||
IOUtils.closeQuietly(inputStream);
|
||||
IOUtils.closeQuietly(outputStream);
|
||||
IOUtils.closeQuietly(socket);
|
||||
inputStream = null;
|
||||
outputStream = null;
|
||||
socket = null;
|
||||
}
|
||||
|
||||
private String readLine() throws IOException {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int d;
|
||||
while ((d = mIn.read()) != -1) {
|
||||
if (((char)d) == '\r') {
|
||||
continue;
|
||||
} else if (((char)d) == '\n') {
|
||||
while ((d = inputStream.read()) != -1) {
|
||||
char c = (char) d;
|
||||
if (c == '\n') {
|
||||
break;
|
||||
} else {
|
||||
sb.append((char)d);
|
||||
} else if (c != '\r') {
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
String ret = sb.toString();
|
||||
|
@ -651,8 +519,8 @@ public class SmtpTransport extends Transport {
|
|||
* SMTP servers misbehave if CR and LF arrive in separate pakets.
|
||||
* See issue 799.
|
||||
*/
|
||||
mOut.write(data);
|
||||
mOut.flush();
|
||||
outputStream.write(data);
|
||||
outputStream.flush();
|
||||
}
|
||||
|
||||
private static class CommandResponse {
|
||||
|
@ -660,7 +528,7 @@ public class SmtpTransport extends Transport {
|
|||
private final int replyCode;
|
||||
private final List<String> results;
|
||||
|
||||
public CommandResponse(int replyCode, List<String> results) {
|
||||
CommandResponse(int replyCode, List<String> results) {
|
||||
this.replyCode = replyCode;
|
||||
this.results = results;
|
||||
}
|
||||
|
@ -700,7 +568,7 @@ public class SmtpTransport extends Transport {
|
|||
char replyCodeCategory = line.charAt(0);
|
||||
boolean isReplyCodeErrorCategory = (replyCodeCategory == '4') || (replyCodeCategory == '5');
|
||||
if (isReplyCodeErrorCategory) {
|
||||
if (mEnhancedStatusCodesProvided) {
|
||||
if (isEnhancedStatusCodesProvided) {
|
||||
throw buildEnhancedNegativeSmtpReplyException(replyCode, results);
|
||||
} else {
|
||||
String replyText = TextUtils.join(" ", results);
|
||||
|
@ -755,48 +623,26 @@ public class SmtpTransport extends Transport {
|
|||
}
|
||||
|
||||
|
||||
// C: AUTH LOGIN
|
||||
// S: 334 VXNlcm5hbWU6
|
||||
// C: d2VsZG9u
|
||||
// S: 334 UGFzc3dvcmQ6
|
||||
// C: dzNsZDBu
|
||||
// S: 235 2.0.0 OK Authenticated
|
||||
//
|
||||
// Lines 2-5 of the conversation contain base64-encoded information. The same conversation, with base64 strings decoded, reads:
|
||||
//
|
||||
//
|
||||
// C: AUTH LOGIN
|
||||
// S: 334 Username:
|
||||
// C: weldon
|
||||
// S: 334 Password:
|
||||
// C: w3ld0n
|
||||
// S: 235 2.0.0 OK Authenticated
|
||||
|
||||
private void saslAuthLogin(String username, String password) throws MessagingException,
|
||||
AuthenticationFailedException, IOException {
|
||||
private void saslAuthLogin() throws MessagingException, IOException {
|
||||
try {
|
||||
executeCommand("AUTH LOGIN");
|
||||
executeSensitiveCommand(Base64.encode(username));
|
||||
executeSensitiveCommand(Base64.encode(password));
|
||||
} catch (NegativeSmtpReplyException exception) {
|
||||
if (exception.getReplyCode() == SMTP_AUTHENTICATION_FAILURE_ERROR_CODE) {
|
||||
// Authentication credentials invalid
|
||||
throw new AuthenticationFailedException("AUTH LOGIN failed ("
|
||||
+ exception.getMessage() + ")");
|
||||
throw new AuthenticationFailedException("AUTH LOGIN failed (" + exception.getMessage() + ")");
|
||||
} else {
|
||||
throw exception;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void saslAuthPlain(String username, String password) throws MessagingException,
|
||||
AuthenticationFailedException, IOException {
|
||||
private void saslAuthPlain() throws MessagingException, IOException {
|
||||
String data = Base64.encode("\000" + username + "\000" + password);
|
||||
try {
|
||||
executeSensitiveCommand("AUTH PLAIN %s", data);
|
||||
} catch (NegativeSmtpReplyException exception) {
|
||||
if (exception.getReplyCode() == SMTP_AUTHENTICATION_FAILURE_ERROR_CODE) {
|
||||
// Authentication credentials invalid
|
||||
throw new AuthenticationFailedException("AUTH PLAIN failed ("
|
||||
+ exception.getMessage() + ")");
|
||||
} else {
|
||||
|
@ -805,8 +651,7 @@ public class SmtpTransport extends Transport {
|
|||
}
|
||||
}
|
||||
|
||||
private void saslAuthCramMD5(String username, String password) throws MessagingException,
|
||||
AuthenticationFailedException, IOException {
|
||||
private void saslAuthCramMD5() throws MessagingException, IOException {
|
||||
|
||||
List<String> respList = executeCommand("AUTH CRAM-MD5").results;
|
||||
if (respList.size() != 1) {
|
||||
|
@ -814,13 +659,12 @@ public class SmtpTransport extends Transport {
|
|||
}
|
||||
|
||||
String b64Nonce = respList.get(0);
|
||||
String b64CRAMString = Authentication.computeCramMd5(mUsername, mPassword, b64Nonce);
|
||||
String b64CRAMString = Authentication.computeCramMd5(username, password, b64Nonce);
|
||||
|
||||
try {
|
||||
executeSensitiveCommand(b64CRAMString);
|
||||
} catch (NegativeSmtpReplyException exception) {
|
||||
if (exception.getReplyCode() == SMTP_AUTHENTICATION_FAILURE_ERROR_CODE) {
|
||||
// Authentication credentials invalid
|
||||
throw new AuthenticationFailedException(exception.getMessage(), exception);
|
||||
} else {
|
||||
throw exception;
|
||||
|
@ -828,7 +672,7 @@ public class SmtpTransport extends Transport {
|
|||
}
|
||||
}
|
||||
|
||||
private void saslXoauth2(String username) throws MessagingException, IOException {
|
||||
private void saslXoauth2() throws MessagingException, IOException {
|
||||
retryXoauthWithNewToken = true;
|
||||
try {
|
||||
attemptXoauth2(username);
|
||||
|
@ -884,14 +728,14 @@ public class SmtpTransport extends Transport {
|
|||
|
||||
if (response.replyCode == SMTP_CONTINUE_REQUEST) {
|
||||
String replyText = TextUtils.join("", response.results);
|
||||
retryXoauthWithNewToken = XOAuth2ChallengeParser.shouldRetry(replyText, mHost);
|
||||
retryXoauthWithNewToken = XOAuth2ChallengeParser.shouldRetry(replyText, host);
|
||||
|
||||
//Per Google spec, respond to challenge with empty response
|
||||
executeCommand("");
|
||||
}
|
||||
}
|
||||
|
||||
private void saslAuthExternal(String username) throws MessagingException, IOException {
|
||||
private void saslAuthExternal() throws MessagingException, IOException {
|
||||
executeCommand("AUTH EXTERNAL %s", Base64.encode(username));
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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) {
|
||||
/*
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue