René Cordier created MIME4J-330: ----------------------------------- Summary: Regression in MimeStreamParser: part body stream ends with CR Key: MIME4J-330 URL: https://issues.apache.org/jira/browse/MIME4J-330 Project: James Mime4j Issue Type: Bug Reporter: René Cordier
A member of the community, Madis Loitmaa (madis.loit...@gmail.com) reported on the ML to have spotted a regression in the MimeStreamParser: part body stream ends with CR. Specifically, when processing messages with certain body lengths, the CR character (from the CRLF sequence preceding the boundary marker) is incorrectly included as the last character of the part body. Environment: This issue was identified after upgrading Mime4j in our project from version 0.8.7 to 0.8.11. It appears to affect all versions starting from 0.8.8. Reproduction: - Madis has attached a unit test, which demonstrates the problem. The test fails for a part body length of 4051 bytes on the current master branch (commit 85995590ad6700cc8bf7a3b8462ce87843dab5bd), but passes when tested with version 0.8.7 (commit ed5a50c8071080b4eaedd6ab13baf25843d691a3). - The bug appears when CRLF is used as the line separator. The issue does not occur when LF is used. Here is the unit test: {code:java} // file src/test/java/org/apache/james/mime4j/parser/PartLengthTest.java package org.apache.james.mime4j.parser; import org.apache.commons.io.IOUtils; import org.apache.james.mime4j.MimeException; import org.apache.james.mime4j.stream.BodyDescriptor; import org.junit.Assert; import org.junit.Test; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; public class PartLengthTest { @Test public void testExtractPartWithDifferentLengths() throws Exception { StringBuilder partBuilder = new StringBuilder(); for (int i = 1; i <= 5000; i++) { partBuilder.append(i % 80 == 0 ? "\n" : "A"); String part = partBuilder.toString(); String mimeMessage = createMimeMultipart(part); String extracted = extractPart(mimeMessage); if (!part.equals(extracted)) { System.out.println("Extracted part comparison failed for part length " + i); } Assert.assertEquals(part, extracted); } } private String createMimeMultipart(String part) { return "Content-type: multipart/mixed; boundary=QvEgqhjEnYxz\r\n" + "\r\n" + "--QvEgqhjEnYxz\r\n" + "Content-Type: text/plain\r\n" + "\r\n" + part + "\r\n" + "--QvEgqhjEnYxz--\r\n"; } private String extractPart(String mimeMessage) throws MimeException, IOException { String[] resultWrapper = new String[1]; MimeStreamParser parser = new MimeStreamParser(); parser.setContentHandler(new AbstractContentHandler() { @Override public void body(BodyDescriptor bd, InputStream is) throws MimeException, IOException { resultWrapper[0] = new String(IOUtils.toString(is, StandardCharsets.UTF_8).getBytes()); } }); parser.parse(new ByteArrayInputStream(mimeMessage.getBytes())); return resultWrapper[0]; } } //end-of-file{code} -- This message was sent by Atlassian Jira (v8.20.10#820010)