diff --git a/k9mail-library/src/main/java/com/fsck/k9/mail/transport/smtp/SmtpTransport.java b/k9mail-library/src/main/java/com/fsck/k9/mail/transport/smtp/SmtpTransport.java index 11086eb03..b2cd02793 100644 --- a/k9mail-library/src/main/java/com/fsck/k9/mail/transport/smtp/SmtpTransport.java +++ b/k9mail-library/src/main/java/com/fsck/k9/mail/transport/smtp/SmtpTransport.java @@ -651,22 +651,30 @@ public class SmtpTransport extends Transport { } private void readPipelinedResponse(Queue pipelinedCommands) throws IOException, MessagingException { - int noOfPipelinedResponse = pipelinedCommands.size(); String responseLine = null; List results = new ArrayList<>(); - while (noOfPipelinedResponse > 0) { - noOfPipelinedResponse--; + NegativeSmtpReplyException negativeRecipient = null; + for (String command : pipelinedCommands) { results.clear(); responseLine = readCommandResponseLine(results); try { responseLineToCommandResponse(responseLine, results); } catch (MessagingException exception) { - if (noOfPipelinedResponse == 0) { + if (command.equals("DATA")) { throw exception; } - Timber.d("SMTP <<< " + exception.getMessage()); - //continue reading response till DATA response . + if (command.startsWith("RCPT")) { + negativeRecipient = (NegativeSmtpReplyException) exception; + } + } + } + + if (negativeRecipient != null) { + try { + executeCommand("."); + } catch (NegativeSmtpReplyException e) { + throw negativeRecipient; } } diff --git a/k9mail-library/src/test/java/com/fsck/k9/mail/helpers/TestMessage.java b/k9mail-library/src/test/java/com/fsck/k9/mail/helpers/TestMessage.java index e44f283d7..c867b0fba 100644 --- a/k9mail-library/src/test/java/com/fsck/k9/mail/helpers/TestMessage.java +++ b/k9mail-library/src/test/java/com/fsck/k9/mail/helpers/TestMessage.java @@ -61,7 +61,15 @@ class TestMessage extends MimeMessage { bufferedSink.emit(); } - private static Address[] toAddressArray(String email) { - return email == null ? new Address[0] : new Address[] { new Address(email) }; + private static Address[] toAddressArray(String[] emails) { + return emails == null ? new Address[0] : stringArrayToAddressArray(emails); + } + + private static Address[] stringArrayToAddressArray(String[] emails) { + Address addresses[] = new Address[emails.length]; + for (int i = 0; i < emails.length; i++) { + addresses[i] = new Address(emails[i]); + } + return addresses; } } diff --git a/k9mail-library/src/test/java/com/fsck/k9/mail/helpers/TestMessageBuilder.java b/k9mail-library/src/test/java/com/fsck/k9/mail/helpers/TestMessageBuilder.java index 9a28fcc23..f8d545e2e 100644 --- a/k9mail-library/src/test/java/com/fsck/k9/mail/helpers/TestMessageBuilder.java +++ b/k9mail-library/src/test/java/com/fsck/k9/mail/helpers/TestMessageBuilder.java @@ -5,18 +5,18 @@ import com.fsck.k9.mail.Message; public class TestMessageBuilder { - String from; - String to; + String[] from; + String[] to; boolean hasAttachments; long messageSize; - public TestMessageBuilder from(String email) { + public TestMessageBuilder from(String... email) { from = email; return this; } - public TestMessageBuilder to(String email) { + public TestMessageBuilder to(String... email) { to = email; return this; } diff --git a/k9mail-library/src/test/java/com/fsck/k9/mail/transport/smtp/SmtpTransportTest.java b/k9mail-library/src/test/java/com/fsck/k9/mail/transport/smtp/SmtpTransportTest.java index 196067dea..fd8323f2a 100644 --- a/k9mail-library/src/test/java/com/fsck/k9/mail/transport/smtp/SmtpTransportTest.java +++ b/k9mail-library/src/test/java/com/fsck/k9/mail/transport/smtp/SmtpTransportTest.java @@ -745,17 +745,23 @@ public class SmtpTransportTest { server.expect("RCPT TO:"); server.expect("DATA"); server.output("250 OK"); - server.output("421 4.7.0 Temporary system problem"); + server.output("550 remote mail to not allowed"); server.output("354 End data with ."); - server.expect("[message data]"); server.expect("."); - server.output("250 OK: queued as 12345"); + server.output("554 no valid recipients"); server.expect("QUIT"); server.output("221 BYE"); server.closeConnection(); SmtpTransport transport = startServerAndCreateSmtpTransport(server); - transport.sendMessage(message); + try { + transport.sendMessage(message); + fail("Expected exception"); + } catch (NegativeSmtpReplyException e) { + assertEquals(550, e.getReplyCode()); + assertEquals("remote mail to not allowed", e.getReplyText()); + } + server.verifyConnectionClosed(); server.verifyInteractionCompleted(); @@ -788,6 +794,38 @@ public class SmtpTransportTest { server.verifyInteractionCompleted(); } + @Test + public void sendMessagePipelining_with250and550ReplyforRecipients_shouldThrow() throws Exception { + Message message = getMessageWithTwoRecipients(); + MockSmtpServer server = createServerAndSetupForPlainAuthentication("PIPELINING"); + server.expect("MAIL FROM:"); + server.expect("RCPT TO:"); + server.expect("RCPT TO:"); + server.expect("DATA"); + server.output("250 OK"); + server.output("250 OK"); + server.output("550 remote mail to not allowed"); + server.output("354 End data with ."); + server.expect("."); + server.output("554 no valid recipients given"); + server.expect("QUIT"); + server.output("221 BYE"); + server.closeConnection(); + SmtpTransport transport = startServerAndCreateSmtpTransport(server); + + try { + transport.sendMessage(message); + fail("Expected exception"); + } catch (NegativeSmtpReplyException e) { + assertEquals(550, e.getReplyCode()); + assertEquals("remote mail to not allowed", e.getReplyText()); + } + + server.verifyConnectionClosed(); + server.verifyInteractionCompleted(); + } + + private SmtpTransport startServerAndCreateSmtpTransport(MockSmtpServer server) throws IOException, MessagingException { return startServerAndCreateSmtpTransport(server, AuthType.PLAIN, ConnectionSecurity.NONE); @@ -840,6 +878,13 @@ public class SmtpTransportTest { return getDefaultMessageBuilder().build(); } + private Message getMessageWithTwoRecipients() { + return new TestMessageBuilder() + .from("user@localhost") + .to("user2@localhost", "user3@localhost") + .build(); + } + private MockSmtpServer createServerAndSetupForPlainAuthentication(String... extensions) { MockSmtpServer server = new MockSmtpServer();