This is an automated email from the ASF dual-hosted git repository. chibenwa pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/james-mime4j.git
commit e377ed69f6754ebb4ed298e43486736047e40de1 Author: Benoit TELLIER <[email protected]> AuthorDate: Wed Nov 4 15:10:48 2026 +0100 [FIX] QuotedPrintableOutputStream: encode whitespace that ends the content completeEncoding() wrote a pending space or TAB unencoded, but the end of the content ends an encoded line, so the decoder drops that trailing whitespace (RFC 2045 6.7 rule (3)) and a body ending with a blank lost it on the next parse. The last space or TAB is now written as =20 / =09. Fixes #110 --- .../mime4j/codec/QuotedPrintableOutputStream.java | 5 +++++ .../mime4j/codec/QuotedPrintableTextEncodeTest.java | 19 ++++++++++++++++--- .../mime4j/message/DefaultMessageWriterTest.java | 13 +++++++++++++ 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/apache/james/mime4j/codec/QuotedPrintableOutputStream.java b/core/src/main/java/org/apache/james/mime4j/codec/QuotedPrintableOutputStream.java index 5c572a80..e07f3e3e 100644 --- a/core/src/main/java/org/apache/james/mime4j/codec/QuotedPrintableOutputStream.java +++ b/core/src/main/java/org/apache/james/mime4j/codec/QuotedPrintableOutputStream.java @@ -82,6 +82,11 @@ public class QuotedPrintableOutputStream extends FilterOutputStream { } private void completeEncoding() throws IOException { + if (!pendingCR && (pendingSpace || pendingTab)) { + // whitespace that ends the content ends an encoded line: it must be encoded + escape(pendingSpace ? SP : TB); + clearPending(); + } writePending(); flushOutput(); } diff --git a/core/src/test/java/org/apache/james/mime4j/codec/QuotedPrintableTextEncodeTest.java b/core/src/test/java/org/apache/james/mime4j/codec/QuotedPrintableTextEncodeTest.java index d48cbe27..5c66859e 100644 --- a/core/src/test/java/org/apache/james/mime4j/codec/QuotedPrintableTextEncodeTest.java +++ b/core/src/test/java/org/apache/james/mime4j/codec/QuotedPrintableTextEncodeTest.java @@ -144,17 +144,30 @@ public class QuotedPrintableTextEncodeTest { @Test public void testDontEscapeSpaceBeforeLineEnd() throws Exception { - check(" ", " "); + check(" ", " =20"); } @Test public void testDontEscapeTabsBeforeLineEnd() throws Exception { - check("\t\t\t\t", "\t\t\t\t"); + check("\t\t\t\t", "\t\t\t=09"); } @Test public void testDontWhiteSpaceBeforeLineEnd() throws Exception { - check(" \t\t \t", " \t\t \t"); + check(" \t\t \t", " \t\t =09"); + } + + @Test + public void testEscapeWhitespaceAtEndOfContent() throws Exception { + check("a\t", "a=09"); + check("a ", "a=20"); + check("a \r", "a =0D"); + } + + @Test + public void testWhitespaceAtEndOfContentRoundTrips() throws Exception { + checkRoundtrip("a\t"); + checkRoundtrip(" "); } private void checkRoundtrip(String content) throws Exception { diff --git a/dom/src/test/java/org/apache/james/mime4j/message/DefaultMessageWriterTest.java b/dom/src/test/java/org/apache/james/mime4j/message/DefaultMessageWriterTest.java index 6fd79e2d..369bf6fa 100644 --- a/dom/src/test/java/org/apache/james/mime4j/message/DefaultMessageWriterTest.java +++ b/dom/src/test/java/org/apache/james/mime4j/message/DefaultMessageWriterTest.java @@ -334,4 +334,17 @@ public class DefaultMessageWriterTest { assertThat(ContentUtil.buffer(((SingleBody) m2.getBody()).getInputStream())) .isEqualTo("a\r\r\nb\rc\n\r\n".getBytes(StandardCharsets.US_ASCII)); } + + @Test + public void quotedPrintableBodyEndingWithWhitespaceSurvivesWriteAndParse() throws Exception { + byte[] raw = "Content-Transfer-Encoding: quoted-printable\r\n\r\na\t=\r\n".getBytes(StandardCharsets.US_ASCII); + DefaultMessageBuilder builder = new DefaultMessageBuilder(); + Message m1 = builder.parseMessage(new ByteArrayInputStream(raw)); + ByteArrayOutputStream w1 = new ByteArrayOutputStream(); + new DefaultMessageWriter().writeMessage(m1, w1); + Message m2 = builder.parseMessage(new ByteArrayInputStream(w1.toByteArray())); + + assertThat(ContentUtil.buffer(((SingleBody) m2.getBody()).getInputStream())) + .isEqualTo("a\t".getBytes(StandardCharsets.US_ASCII)); + } } --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
