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 1c7690c54ecce3f3da27160e71a63495060c5539 Author: Benoit TELLIER <[email protected]> AuthorDate: Wed Nov 4 15:04:22 2026 +0100 [FIX] MimeTokenStream: stop() also stops the nested entities stop() only truncated the root entity. A nested multipart or message reads its header and body from its own buffer, refilled from its parent: after stop() it went on reporting fields, parts and bodies as if nothing happened. stop() now stops every open entity, so only the end events of the open entities follow. Fixes #102 --- .../apache/james/mime4j/stream/MimeTokenStream.java | 6 ++++++ .../james/mime4j/stream/MimeTokenStreamTest.java | 20 ++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/core/src/main/java/org/apache/james/mime4j/stream/MimeTokenStream.java b/core/src/main/java/org/apache/james/mime4j/stream/MimeTokenStream.java index d6d89cc1..d60a95ee 100644 --- a/core/src/main/java/org/apache/james/mime4j/stream/MimeTokenStream.java +++ b/core/src/main/java/org/apache/james/mime4j/stream/MimeTokenStream.java @@ -271,6 +271,12 @@ public class MimeTokenStream { */ public void stop() { rootentity.stopSoft(); + // Nested entities read from their own buffers: stop them all + for (EntityStateMachine entity : entities) { + if (entity instanceof MimeEntity) { + ((MimeEntity) entity).stopSoft(); + } + } fieldBuilder.release(); } diff --git a/core/src/test/java/org/apache/james/mime4j/stream/MimeTokenStreamTest.java b/core/src/test/java/org/apache/james/mime4j/stream/MimeTokenStreamTest.java index 7f0aee45..491cd776 100644 --- a/core/src/test/java/org/apache/james/mime4j/stream/MimeTokenStreamTest.java +++ b/core/src/test/java/org/apache/james/mime4j/stream/MimeTokenStreamTest.java @@ -140,4 +140,24 @@ public class MimeTokenStreamTest { Assert.assertFalse(states.toString(), states.contains(EntityState.T_START_BODYPART)); Assert.assertTrue(states.toString(), states.contains(EntityState.T_END_MULTIPART)); } + + @Test + public void stopInANestedPartShouldNotReportItsFields() throws Exception { + String msg = "From: [email protected]\nContent-Type: multipart/mixed; boundary=\"outer\"\n\n" + + "--outer\nContent-Type: multipart/alternative; boundary=\"inner\"\n\n" + + "--inner\nContent-Type: text/plain\nX-After: stop\n\nhello\n--inner--\n--outer--\n"; + MimeTokenStream stream = new MimeTokenStream(); + stream.parse(new ByteArrayInputStream(msg.getBytes(StandardCharsets.US_ASCII))); + int startHeaders = 0; + EntityState state; + while ((state = stream.next()) != EntityState.T_START_HEADER || ++startHeaders < 3) { + Assert.assertNotEquals(EntityState.T_END_OF_STREAM, state); + } + stream.stop(); + for (int i = 0; i < 100 && (state = stream.next()) != EntityState.T_END_OF_STREAM; i++) { + Assert.assertNotEquals(EntityState.T_FIELD, state); + Assert.assertNotEquals(EntityState.T_START_BODYPART, state); + } + Assert.assertEquals(EntityState.T_END_OF_STREAM, state); + } } --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
