SMTP: Further test coverage for various cases
This commit is contained in:
parent
d1904900c8
commit
a2b545fc39
4 changed files with 309 additions and 9 deletions
|
@ -532,10 +532,8 @@ public class SmtpTransport extends Transport {
|
|||
entireMessageSent = true; // After the "\r\n." is attempted, we may have sent the message
|
||||
executeSimpleCommand(".");
|
||||
} catch (NegativeSmtpReplyException e) {
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
MessagingException me = new MessagingException("Unable to send message", e);
|
||||
me.setPermanentFailure(entireMessageSent);
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@ package com.fsck.k9.mail.transport;
|
|||
|
||||
import com.fsck.k9.mail.Address;
|
||||
import com.fsck.k9.mail.AuthType;
|
||||
import com.fsck.k9.mail.AuthenticationFailedException;
|
||||
import com.fsck.k9.mail.CertificateValidationException;
|
||||
import com.fsck.k9.mail.ConnectionSecurity;
|
||||
import com.fsck.k9.mail.Message;
|
||||
import com.fsck.k9.mail.MessagingException;
|
||||
|
@ -12,6 +14,7 @@ import com.fsck.k9.mail.ssl.TrustedSocketFactory;
|
|||
import com.fsck.k9.mail.store.StoreConfig;
|
||||
import com.fsck.k9.mail.transport.mockServer.MockSmtpServer;
|
||||
import com.fsck.k9.mail.transport.mockServer.TestMessage;
|
||||
import com.fsck.k9.mailstore.BinaryMemoryBody;
|
||||
import com.fsck.k9.testHelpers.TestTrustedSocketFactory;
|
||||
|
||||
import org.junit.Before;
|
||||
|
@ -24,6 +27,12 @@ import java.io.IOException;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
import static junit.framework.Assert.fail;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.Matchers.anyLong;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.inOrder;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
|
@ -86,7 +95,6 @@ public class SmtpTransportTest {
|
|||
server.output("220 localhost Simple Mail Transfer Service Ready");
|
||||
server.expect("EHLO localhost");
|
||||
server.output("250-localhost Hello client.localhost");
|
||||
server.output("250-SIZE 1000000");
|
||||
for (String extension: extensions) {
|
||||
server.output("250-"+extension);
|
||||
}
|
||||
|
@ -115,6 +123,26 @@ public class SmtpTransportTest {
|
|||
new SmtpTransport(storeConfig, trustedSocketFactory);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void open_withNoSecurityOrPasswordPlainAuth_connectsToServer_withoutLogin()
|
||||
throws MessagingException, IOException, InterruptedException {
|
||||
username = "user";
|
||||
authenticationType = AuthType.PLAIN;
|
||||
connectionSecurity = ConnectionSecurity.NONE;
|
||||
|
||||
MockSmtpServer server = new MockSmtpServer();
|
||||
server.output("220 localhost Simple Mail Transfer Service Ready");
|
||||
server.expect("EHLO localhost");
|
||||
server.output("250-localhost Hello client.localhost");
|
||||
server.output("250 OK");
|
||||
|
||||
SmtpTransport transport = startServerAndCreateSmtpTransport(server);
|
||||
transport.open();
|
||||
|
||||
server.verifyConnectionStillOpen();
|
||||
server.verifyInteractionCompleted();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void open_withNoSecurityPlainAuth_connectsToServer()
|
||||
throws MessagingException, IOException, InterruptedException {
|
||||
|
@ -127,8 +155,7 @@ public class SmtpTransportTest {
|
|||
server.output("220 localhost Simple Mail Transfer Service Ready");
|
||||
server.expect("EHLO localhost");
|
||||
server.output("250-localhost Hello client.localhost");
|
||||
server.output("250-SIZE 1000000");
|
||||
server.output("250 AUTH LOGIN PLAIN CRAM-MD5");
|
||||
server.output("250 AUTH PLAIN LOGIN");
|
||||
server.expect("AUTH PLAIN AHVzZXIAcGFzc3dvcmQ=");
|
||||
server.output("235 2.7.0 Authentication successful");
|
||||
|
||||
|
@ -139,6 +166,60 @@ public class SmtpTransportTest {
|
|||
server.verifyInteractionCompleted();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void open_withNoSecurityPlainAuth_usesLoginIfPlainUnavailable()
|
||||
throws MessagingException, IOException, InterruptedException {
|
||||
username = "user";
|
||||
password = "password";
|
||||
authenticationType = AuthType.PLAIN;
|
||||
connectionSecurity = ConnectionSecurity.NONE;
|
||||
|
||||
MockSmtpServer server = new MockSmtpServer();
|
||||
server.output("220 localhost Simple Mail Transfer Service Ready");
|
||||
server.expect("EHLO localhost");
|
||||
server.output("250-localhost Hello client.localhost");
|
||||
server.output("250 AUTH LOGIN");
|
||||
server.expect("AUTH LOGIN");
|
||||
server.output("250 OK");
|
||||
server.expect("dXNlcg==");
|
||||
server.output("250 OK");
|
||||
server.expect("cGFzc3dvcmQ=");
|
||||
server.output("235 2.7.0 Authentication successful");
|
||||
|
||||
SmtpTransport transport = startServerAndCreateSmtpTransport(server);
|
||||
transport.open();
|
||||
|
||||
server.verifyConnectionStillOpen();
|
||||
server.verifyInteractionCompleted();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void open_withNoSecurityPlainAuth_withNeither_throwsException()
|
||||
throws MessagingException, IOException, InterruptedException {
|
||||
username = "user";
|
||||
password = "password";
|
||||
authenticationType = AuthType.PLAIN;
|
||||
connectionSecurity = ConnectionSecurity.NONE;
|
||||
|
||||
MockSmtpServer server = new MockSmtpServer();
|
||||
server.output("220 localhost Simple Mail Transfer Service Ready");
|
||||
server.expect("EHLO localhost");
|
||||
server.output("250-localhost Hello client.localhost");
|
||||
server.output("250 AUTH");
|
||||
|
||||
try {
|
||||
SmtpTransport transport = startServerAndCreateSmtpTransport(server);
|
||||
transport.open();
|
||||
fail("Exception expected");
|
||||
} catch (MessagingException e) {
|
||||
assertEquals("Authentication methods SASL PLAIN and LOGIN are unavailable.",
|
||||
e.getMessage());
|
||||
}
|
||||
|
||||
server.verifyConnectionStillOpen();
|
||||
server.verifyInteractionCompleted();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void open_withNoSecurityCramMd5Auth_connectsToServer()
|
||||
throws MessagingException, IOException, InterruptedException {
|
||||
|
@ -151,8 +232,7 @@ public class SmtpTransportTest {
|
|||
server.output("220 localhost Simple Mail Transfer Service Ready");
|
||||
server.expect("EHLO localhost");
|
||||
server.output("250-localhost Hello client.localhost");
|
||||
server.output("250-SIZE 1000000");
|
||||
server.output("250 AUTH LOGIN PLAIN CRAM-MD5");
|
||||
server.output("250 AUTH CRAM-MD5");
|
||||
server.expect("AUTH CRAM-MD5");
|
||||
server.output(Base64.encode("<24609.1047914046@localhost>"));
|
||||
server.expect("dXNlciA3NmYxNWEzZmYwYTNiOGI1NzcxZmNhODZlNTcyMDk2Zg==");
|
||||
|
@ -165,6 +245,33 @@ public class SmtpTransportTest {
|
|||
server.verifyInteractionCompleted();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void open_withNoSecurityCramMd5Auth_withNoSupport_throwsException()
|
||||
throws MessagingException, IOException, InterruptedException {
|
||||
username = "user";
|
||||
password = "password";
|
||||
authenticationType = AuthType.CRAM_MD5;
|
||||
connectionSecurity = ConnectionSecurity.NONE;
|
||||
|
||||
MockSmtpServer server = new MockSmtpServer();
|
||||
server.output("220 localhost Simple Mail Transfer Service Ready");
|
||||
server.expect("EHLO localhost");
|
||||
server.output("250-localhost Hello client.localhost");
|
||||
server.output("250 AUTH PLAIN LOGIN");
|
||||
|
||||
try {
|
||||
SmtpTransport transport = startServerAndCreateSmtpTransport(server);
|
||||
transport.open();
|
||||
fail("Exception expected");
|
||||
} catch (MessagingException e) {
|
||||
assertEquals("Authentication method CRAM-MD5 is unavailable.",
|
||||
e.getMessage());
|
||||
}
|
||||
|
||||
server.verifyConnectionStillOpen();
|
||||
server.verifyInteractionCompleted();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void open_withNoSecurityExternalAuth_connectsToServer()
|
||||
throws MessagingException, IOException, InterruptedException {
|
||||
|
@ -177,7 +284,6 @@ public class SmtpTransportTest {
|
|||
server.output("220 localhost Simple Mail Transfer Service Ready");
|
||||
server.expect("EHLO localhost");
|
||||
server.output("250-localhost Hello client.localhost");
|
||||
server.output("250-SIZE 1000000");
|
||||
server.output("250 AUTH EXTERNAL");
|
||||
server.expect("AUTH EXTERNAL dXNlcg==");
|
||||
server.output("235 2.7.0 Authentication successful");
|
||||
|
@ -189,6 +295,104 @@ public class SmtpTransportTest {
|
|||
server.verifyInteractionCompleted();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void open_withNoSecurityExternal_withNoSupport_throwsException()
|
||||
throws MessagingException, IOException, InterruptedException {
|
||||
username = "user";
|
||||
password = "password";
|
||||
authenticationType = AuthType.EXTERNAL;
|
||||
connectionSecurity = ConnectionSecurity.NONE;
|
||||
|
||||
MockSmtpServer server = new MockSmtpServer();
|
||||
server.output("220 localhost Simple Mail Transfer Service Ready");
|
||||
server.expect("EHLO localhost");
|
||||
server.output("250-localhost Hello client.localhost");
|
||||
server.output("250 AUTH");
|
||||
|
||||
try {
|
||||
SmtpTransport transport = startServerAndCreateSmtpTransport(server);
|
||||
transport.open();
|
||||
fail("Exception expected");
|
||||
} catch (CertificateValidationException e) {
|
||||
assertEquals(CertificateValidationException.Reason.MissingCapability, e.getReason());
|
||||
}
|
||||
|
||||
server.verifyConnectionStillOpen();
|
||||
server.verifyInteractionCompleted();
|
||||
}
|
||||
@Test
|
||||
public void open_withNoSecurityAutomatic_connectsToServerWithCramMD5IfSupported()
|
||||
throws MessagingException, IOException, InterruptedException {
|
||||
username = "user";
|
||||
password = "password";
|
||||
authenticationType = AuthType.AUTOMATIC;
|
||||
connectionSecurity = ConnectionSecurity.NONE;
|
||||
|
||||
MockSmtpServer server = new MockSmtpServer();
|
||||
server.output("220 localhost Simple Mail Transfer Service Ready");
|
||||
server.expect("EHLO localhost");
|
||||
server.output("250-localhost Hello client.localhost");
|
||||
server.output("250 AUTH CRAM-MD5");
|
||||
server.expect("AUTH CRAM-MD5");
|
||||
server.output(Base64.encode("<24609.1047914046@localhost>"));
|
||||
server.expect("dXNlciA3NmYxNWEzZmYwYTNiOGI1NzcxZmNhODZlNTcyMDk2Zg==");
|
||||
server.output("235 2.7.0 Authentication successful");
|
||||
|
||||
SmtpTransport transport = startServerAndCreateSmtpTransport(server);
|
||||
transport.open();
|
||||
|
||||
server.verifyConnectionStillOpen();
|
||||
server.verifyInteractionCompleted();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void open_withNoSecurityAutomatic_withCramMD5Unsupported_throwsException()
|
||||
throws MessagingException, IOException, InterruptedException {
|
||||
username = "user";
|
||||
password = "password";
|
||||
authenticationType = AuthType.AUTOMATIC;
|
||||
connectionSecurity = ConnectionSecurity.NONE;
|
||||
|
||||
MockSmtpServer server = new MockSmtpServer();
|
||||
server.output("220 localhost Simple Mail Transfer Service Ready");
|
||||
server.expect("EHLO localhost");
|
||||
server.output("250-localhost Hello client.localhost");
|
||||
server.output("250 AUTH PLAIN LOGIN");
|
||||
|
||||
try {
|
||||
SmtpTransport transport = startServerAndCreateSmtpTransport(server);
|
||||
transport.open();
|
||||
fail("Exception expected");
|
||||
} catch (MessagingException e) {
|
||||
assertEquals("Update your outgoing server authentication setting. AUTOMATIC auth. is unavailable.",
|
||||
e.getMessage());
|
||||
}
|
||||
|
||||
server.verifyConnectionStillOpen();
|
||||
server.verifyInteractionCompleted();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void open_triesHELO_whenServerDoesntSupportEHLO()
|
||||
throws MessagingException, IOException, InterruptedException {
|
||||
username = "user";
|
||||
authenticationType = AuthType.PLAIN;
|
||||
connectionSecurity = ConnectionSecurity.NONE;
|
||||
|
||||
MockSmtpServer server = new MockSmtpServer();
|
||||
server.output("220 localhost Simple Mail Transfer Service Ready");
|
||||
server.expect("EHLO localhost");
|
||||
server.output("502 5.5.1, Unrecognized command.");
|
||||
server.expect("HELO localhost");
|
||||
server.output("250 localhost");
|
||||
|
||||
SmtpTransport transport = startServerAndCreateSmtpTransport(server);
|
||||
transport.open();
|
||||
|
||||
server.verifyConnectionStillOpen();
|
||||
server.verifyInteractionCompleted();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sendMessage_withNoAddressToSendTo_doesntOpenConnection()
|
||||
throws MessagingException, IOException, InterruptedException {
|
||||
|
@ -257,4 +461,61 @@ public class SmtpTransportTest {
|
|||
SmtpTransport transport = startServerAndCreateSmtpTransport(server);
|
||||
transport.sendMessage(message);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sendMessage_withMessageTooLarge_throwsException()
|
||||
throws MessagingException, IOException, InterruptedException {
|
||||
extensions.add("SIZE 1000");
|
||||
TestMessage message = new TestMessage();
|
||||
message.setFrom(new Address("user@localhost"));
|
||||
message.setRecipients(Message.RecipientType.TO, new Address[]{new Address("user2@localhost")});
|
||||
message.setAttachmentCount(1);
|
||||
message.setBody(new BinaryMemoryBody(new byte[1001], "US-ASCII"));
|
||||
|
||||
MockSmtpServer server = new MockSmtpServer();
|
||||
setupConnectAndPlainAuthentication(server);
|
||||
|
||||
SmtpTransport transport = startServerAndCreateSmtpTransport(server);
|
||||
|
||||
try {
|
||||
transport.sendMessage(message);
|
||||
fail("Expected message too large error");
|
||||
} catch (MessagingException e) {
|
||||
assertTrue(e.isPermanentFailure());
|
||||
assertEquals("Message too large for server", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sendMessage_withNegativeReply_throwsException()
|
||||
throws MessagingException, IOException, InterruptedException {
|
||||
TestMessage message = new TestMessage();
|
||||
message.setFrom(new Address("user@localhost"));
|
||||
message.setRecipients(Message.RecipientType.TO, new Address[]{new Address("user2@localhost")});
|
||||
|
||||
MockSmtpServer server = new MockSmtpServer();
|
||||
setupConnectAndPlainAuthentication(server);
|
||||
server.expect("MAIL FROM:<user@localhost>");
|
||||
server.output("250 OK");
|
||||
server.expect("RCPT TO:<user2@localhost>");
|
||||
server.output("250 OK");
|
||||
server.expect("DATA");
|
||||
server.output("354 End data with <CR><LF>.<CR><LF>");
|
||||
server.expect("");
|
||||
server.expect(".");
|
||||
server.output("421 4.7.0 Temporary system problem");
|
||||
server.expect("QUIT");
|
||||
server.output("221 BYE");
|
||||
server.closeConnection();
|
||||
|
||||
SmtpTransport transport = startServerAndCreateSmtpTransport(server);
|
||||
|
||||
try {
|
||||
transport.sendMessage(message);
|
||||
fail("Expected exception");
|
||||
} catch (SmtpTransport.NegativeSmtpReplyException e) {
|
||||
assertEquals(421, e.getReplyCode());
|
||||
assertEquals("4.7.0 Temporary system problem", e.getReplyText());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package com.fsck.k9.mail.transport;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
|
||||
import com.fsck.k9.mail.AuthType;
|
||||
import com.fsck.k9.mail.ConnectionSecurity;
|
||||
import com.fsck.k9.mail.ServerSettings;
|
||||
|
@ -8,6 +10,7 @@ import org.junit.Test;
|
|||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
@SuppressLint("AuthLeak")
|
||||
public class SmtpTransportUriTest {
|
||||
|
||||
@Test
|
||||
|
@ -37,6 +40,33 @@ public class SmtpTransportUriTest {
|
|||
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";
|
||||
|
@ -82,6 +112,13 @@ public class SmtpTransportUriTest {
|
|||
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(
|
||||
|
|
|
@ -59,6 +59,10 @@ public class TestMessage extends MimeMessage {
|
|||
return (mAttachmentCount > 0);
|
||||
}
|
||||
|
||||
public void setAttachmentCount(int i) {
|
||||
mAttachmentCount = i;
|
||||
}
|
||||
|
||||
public int getAttachmentCount() {
|
||||
return mAttachmentCount;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue