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]

Reply via email to