Merge pull request #1550 from k9mail/do_not_add_newline_to_message_body

Don't add additional CR LF to the end of a message when sending
This commit is contained in:
cketti 2016-08-10 05:14:52 +02:00 committed by GitHub
commit 5feed620f4
3 changed files with 82 additions and 20 deletions

View file

@ -7,8 +7,10 @@ import java.io.OutputStream;
public class EOLConvertingOutputStream extends FilterOutputStream {
private static final int CR = '\r';
private static final int LF = '\n';
private int lastChar;
private static final int IGNORE_LF = Integer.MIN_VALUE;
private int lastByte;
private boolean ignoreLf = false;
public EOLConvertingOutputStream(OutputStream out) {
@ -17,28 +19,46 @@ public class EOLConvertingOutputStream extends FilterOutputStream {
@Override
public void write(int oneByte) throws IOException {
if (oneByte == LF && lastChar == IGNORE_LF) {
lastChar = LF;
if (oneByte == LF && ignoreLf) {
ignoreLf = false;
return;
}
if (oneByte == LF && lastChar != CR) {
super.write(CR);
} else if (oneByte != LF && lastChar == CR) {
super.write(LF);
if (oneByte == LF && lastByte != CR) {
writeByte(CR);
} else if (oneByte != LF && lastByte == CR) {
writeByte(LF);
}
super.write(oneByte);
lastChar = oneByte;
writeByte(oneByte);
ignoreLf = false;
}
@Override
public void flush() throws IOException {
if (lastChar == CR) {
super.write(LF);
// We have to ignore the next character if it is <LF>. Otherwise it
// will be expanded to an additional <CR><LF> sequence although it
// belongs to the one just completed.
lastChar = IGNORE_LF;
completeCrLf();
super.flush();
}
public void endWithCrLfAndFlush() throws IOException {
completeCrLf();
if (lastByte != LF) {
writeByte(CR);
writeByte(LF);
}
super.flush();
}
private void completeCrLf() throws IOException {
if (lastByte == CR) {
writeByte(LF);
// We have to ignore the next character if it is <LF>. Otherwise it
// will be expanded to an additional <CR><LF> sequence although it
// belongs to the one just completed.
ignoreLf = true;
}
}
private void writeByte(int oneByte) throws IOException {
super.write(oneByte);
lastByte = oneByte;
}
}

View file

@ -527,12 +527,10 @@ public class SmtpTransport extends Transport {
new LineWrapOutputStream(new SmtpDataStuffing(mOut), 1000));
message.writeTo(msgOut);
// We use BufferedOutputStream. So make sure to call flush() !
msgOut.flush();
msgOut.endWithCrLfAndFlush();
entireMessageSent = true; // After the "\r\n." is attempted, we may have sent the message
executeSimpleCommand("\r\n.");
executeSimpleCommand(".");
} catch (NegativeSmtpReplyException e) {
throw e;
} catch (Exception e) {

View file

@ -78,4 +78,48 @@ public class EOLConvertingOutputStreamTest {
subject.write("\n".getBytes());
assertEquals("Flush\r\n\r\n", out.toString());
}
@Test
public void testFlushWithCrFollowedByLf() throws Exception {
subject.write("Flush\r".getBytes());
subject.flush();
subject.write("\n".getBytes());
assertEquals("Flush\r\n", out.toString());
}
@Test
public void endWithCrLfAndFlush_withoutNewline_shouldAddNewline() throws Exception {
subject.write("The end".getBytes());
subject.endWithCrLfAndFlush();
assertEquals("The end\r\n", out.toString());
}
@Test
public void endWithCrLfAndFlush_endingWithNewline_shouldNotAddAdditionalNewline() throws Exception {
subject.write("The end\r\n".getBytes());
subject.endWithCrLfAndFlush();
assertEquals("The end\r\n", out.toString());
}
@Test
public void endWithCrLfAndFlush_endingWithCr_shouldCompleteNewline() throws Exception {
subject.write("The end\r".getBytes());
subject.endWithCrLfAndFlush();
assertEquals("The end\r\n", out.toString());
}
@Test
public void endWithCrLfAndFlush_endingWithLf_shouldCompleteNewline() throws Exception {
subject.write("The end\n".getBytes());
subject.endWithCrLfAndFlush();
assertEquals("The end\r\n", out.toString());
}
}