Repository: thundernest/k-9
Issue: Not handling reject response correctly when multiple recipients

### Similar issues found
#3616 

### Root Cause
My mail server is enforcing a 'reject' rule on unknown recipient domain. So any email containing unknown domain will **not** be accepted.
It works with other MUA I tested, and indeed the 450 error is raised and no mail is sent until the list of recipients is sanitized.
In the case of K9-Mail, I end up with a **mangled header missing multiple fields** (From / Date) and with an 'unexpected end of header'.
For Googlemail, the server respond waving RFC 5322 and refuse to accept the email.
Others will discard and send a report to the recipient regarding the bad formatted email, and Outlook/Microsoft will accept it but it will be blank for the recipient.
On K9-Mail side, the email will be stuck forever in the Outbox, trying to resend the botched email every now and then, never succeeding (as expected). 

### Expected behavior
Whenever a recipient is rejected, the MUA should handle it gracefully. Testing with Thunderbird and SOGo, they both raise the error and do not try further attempts to deliver the email until the 'bad' recipients have been removed from the list.

K9-Mail should do the same and stop all attempt on receiving the reject from the mail server until the list of recipients has been sanitized. 

### Actual behavior
Mail server rejects the email, with and from=<> as per bouncing standards, however K9-Mail basically integrate that bad-formatted header and use it to try sending the email to the rest of the recipients.

### Steps to reproduce
0. Enforce reject rule on unknown recipient domains on your mail server (**before** any permit rule)
1. Prepare an email to multiple recipients with at least one 'bad' recipient (ex: unknown domain. Ex: nobody@gmail72.com)
2. Send it from K9-Mail
3. Check your Outbox in K9-Mail and your logs on the mail server

### Environment
K-9 Mail version: 5.500

Android version: 8.1.0

Account type (IMAP, POP3, WebDAV/Exchange): IMAP

Please take some time to [retrieve logs](https://github.com/k9mail/k-9/wiki/LoggingErrors) and attach them here:

Logs from the mail server:
```
Jul 23 09:44:35 myhost postfix/smtpd[26369]: connect from XXX.XXX.XXX.137.threembb.co.uk[XXX.XXX.XXX.137]
Jul 23 09:44:35 myhost postfix/smtpd[26369]: Anonymous TLS connection established from XXX.XXX.XXX.137.threembb.co.uk[XXX.XXX.XXX.137]: TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)
Jul 23 09:44:35 myhost postfix/smtpd[26369]: CEC231003: client=XXX.XXX.XXX.137.threembb.co.uk[XXX.XXX.XXX.137], sasl_method=PLAIN, sasl_username=obsucated-p@domain.fr
Jul 23 09:44:35 myhost postfix/smtpd[26369]: CEC231003: reject: RCPT from XXX.XXX.XXX.137.threembb.co.uk[XXX.XXX.XXX.137]: 450 4.1.2 <obsucated-t@domain.com>: <b>Recipient address rejected: Domain not found</b>; from=<obsucated-p@domain.fr> to=<obsucated-t@domain.com> proto=ESMTP helo=<[XXX.XXX.XXX.119]>
Jul 23 09:44:36 myhost postfix/cleanup[26374]: CEC231003: message-id=<>
Jul 23 09:44:36 myhost opendkim[32642]: <b>CEC231003: can't determine message sender; accepting</b>
Jul 23 09:44:36 myhost opendmarc[619]: CEC231003: RFC5322 requirement error: missing From field; accepting
Jul 23 09:44:36 myhost postfix/qmgr[26269]: CEC231003: from=<obsucated-p@domain.fr>, size=213, nrcpt=2 (queue active)
Jul 23 09:44:36 myhost postfix/smtp[26375]: Untrusted TLS connection established to gmail-smtp-in.l.google.com[2a00:1450:400c:c0a::1b]:25: TLSv1.2 with cipher ECDHE-RSA-CHACHA20-POLY1305 (256/256 bits)
Jul 23 09:44:36 myhost postfix/smtpd[26369]: disconnect from XXX.XXX.XXX.137.threembb.co.uk[XXX.XXX.XXX.137] ehlo=2 starttls=1 auth=1 mail=1 rcpt=2/3 data=1 quit=1 commands=9/10
Jul 23 09:44:36 myhost postfix/smtp[26375]: CEC231003: to=<obsucated-j@domain.com>, relay=gmail-smtp-in.l.google.com[2a00:1450:400c:c0a::1b]:25, delay=0.99, delays=0.4/0.01/0.16/0.43, dsn=5.7.1, status=bounced (host gmail-smtp-in.l.google.com[2a00:1450:400c:c0a::1b] said: 550-5.7.1 [2a01:4f8:10a:2493:b827:a8ff:fe4b:b71c      11] Our system has 550-5.7.1 detected that this message is not RFC 5322 compliant: 550-5.7.1 'From' header is missing. 550-5.7.1 To reduce the amount of spam sent to Gmail, this message has been 550-5.7.1 blocked. Please visit 550-5.7.1  https://support.google.com/mail/?p=RfcMessageNonCompliant 550 5.7.1 and review RFC 5322 specifications for more information. y4si40902182wrr.356 - gsmtp (in reply to end of DATA command))
```


Changed files:
mail/protocols/smtp/src/main/java/com/fsck/k9/mail/transport/smtp/SmtpTransport.java
mail/protocols/smtp/src/test/java/com/fsck/k9/mail/transport/smtp/SmtpTransportTest.java

diff --git a/mail/protocols/smtp/src/main/java/com/fsck/k9/mail/transport/smtp/SmtpTransport.java b/mail/protocols/smtp/src/main/java/com/fsck/k9/mail/transport/smtp/SmtpTransport.java
index aeaff52f6..001919834 100644
--- a/mail/protocols/smtp/src/main/java/com/fsck/k9/mail/transport/smtp/SmtpTransport.java
+++ b/mail/protocols/smtp/src/main/java/com/fsck/k9/mail/transport/smtp/SmtpTransport.java
@@ -413,7 +413,6 @@ public class SmtpTransport extends Transport {
                     pipelinedCommands.add(String.format("RCPT TO:<%s>", address));
                 }
 
-                pipelinedCommands.add("DATA");
                 executePipelinedCommands(pipelinedCommands);
                 readPipelinedResponse(pipelinedCommands);
             } else {
@@ -422,10 +421,10 @@ public class SmtpTransport extends Transport {
                 for (String address : addresses) {
                     executeCommand("RCPT TO:<%s>", address);
                 }
-
-                executeCommand("DATA");
             }
 
+            executeCommand("DATA");
+
             EOLConvertingOutputStream msgOut = new EOLConvertingOutputStream(
                     new LineWrapOutputStream(new SmtpDataStuffing(outputStream), 1000));
 
@@ -618,35 +617,23 @@ public class SmtpTransport extends Transport {
     private void readPipelinedResponse(Queue<String> pipelinedCommands) throws IOException, MessagingException {
         String responseLine;
         List<String> results = new ArrayList<>();
-        NegativeSmtpReplyException firstNegativeResponse = null;
-        boolean dataCommandOk = true;
-        for (String command : pipelinedCommands) {
+        MessagingException firstException = null;
+        for (int i = 0, size = pipelinedCommands.size(); i < size; i++) {
             results.clear();
             responseLine = readCommandResponseLine(results);
             try {
                 responseLineToCommandResponse(responseLine, results);
 
             } catch (MessagingException exception) {
-                if (command.equals("DATA")) {
-                    dataCommandOk = false;
-                }
-                if (firstNegativeResponse == null) {
-                    firstNegativeResponse = (NegativeSmtpReplyException) exception;
+                if (firstException == null) {
+                    firstException = exception;
                 }
             }
         }
 
-        if (firstNegativeResponse != null) {
-            try {
-                if (dataCommandOk) {
-                    executeCommand(".");
-                }
-                throw firstNegativeResponse;
-            } catch (NegativeSmtpReplyException e) {
-                throw firstNegativeResponse;
-            }
+        if (firstException != null) {
+            throw firstException;
         }
-
     }
 
     private CommandResponse responseLineToCommandResponse(String line, List<String> results) throws MessagingException {
diff --git a/mail/protocols/smtp/src/test/java/com/fsck/k9/mail/transport/smtp/SmtpTransportTest.java b/mail/protocols/smtp/src/test/java/com/fsck/k9/mail/transport/smtp/SmtpTransportTest.java
index 06aa6f9e7..33a4025c4 100644
--- a/mail/protocols/smtp/src/test/java/com/fsck/k9/mail/transport/smtp/SmtpTransportTest.java
+++ b/mail/protocols/smtp/src/test/java/com/fsck/k9/mail/transport/smtp/SmtpTransportTest.java
@@ -692,9 +692,9 @@ public class SmtpTransportTest {
         MockSmtpServer server = createServerAndSetupForPlainAuthentication("PIPELINING");
         server.expect("MAIL FROM:<user@localhost>");
         server.expect("RCPT TO:<user2@localhost>");
-        server.expect("DATA");
         server.output("250 OK");
         server.output("250 OK");
+        server.expect("DATA");
         server.output("354 End data with <CR><LF>.<CR><LF>");
         server.expect("[message data]");
         server.expect(".");
@@ -740,12 +740,8 @@ public class SmtpTransportTest {
         MockSmtpServer server = createServerAndSetupForPlainAuthentication("PIPELINING");
         server.expect("MAIL FROM:<user@localhost>");
         server.expect("RCPT TO:<user2@localhost>");
-        server.expect("DATA");
         server.output("250 OK");
         server.output("550 remote mail to <user2@localhost> not allowed");
-        server.output("354 End data with <CR><LF>.<CR><LF>");
-        server.expect(".");
-        server.output("554 no valid recipients");
         server.expect("QUIT");
         server.output("221 BYE");
         server.closeConnection();
@@ -770,10 +766,8 @@ public class SmtpTransportTest {
         MockSmtpServer server = createServerAndSetupForPlainAuthentication("PIPELINING");
         server.expect("MAIL FROM:<user@localhost>");
         server.expect("RCPT TO:<user2@localhost>");
-        server.expect("DATA");
         server.output("250 OK");
         server.output("550 remote mail to <user2@localhost> not allowed");
-        server.output("554 no valid recipients given");
         server.expect("QUIT");
         server.output("221 BYE");
         server.closeConnection();
@@ -798,13 +792,9 @@ public class SmtpTransportTest {
         server.expect("MAIL FROM:<user@localhost>");
         server.expect("RCPT TO:<user2@localhost>");
         server.expect("RCPT TO:<user3@localhost>");
-        server.expect("DATA");
         server.output("250 OK");
         server.output("550 remote mail to <user2@localhost> not allowed");
         server.output("550 remote mail to <user3@localhost> not allowed");
-        server.output("354 End data with <CR><LF>.<CR><LF>");
-        server.expect(".");
-        server.output("554 no valid recipients given");
         server.expect("QUIT");
         server.output("221 BYE");
         server.closeConnection();
@@ -829,13 +819,9 @@ public class SmtpTransportTest {
         server.expect("MAIL FROM:<user@localhost>");
         server.expect("RCPT TO:<user2@localhost>");
         server.expect("RCPT TO:<user3@localhost>");
-        server.expect("DATA");
         server.output("250 OK");
         server.output("250 OK");
         server.output("550 remote mail to <user3@localhost> not allowed");
-        server.output("354 End data with <CR><LF>.<CR><LF>");
-        server.expect(".");
-        server.output("250 OK");
         server.expect("QUIT");
         server.output("221 BYE");
         server.closeConnection();