Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions test/fixtures/original.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
Subject: Example Email
From: Test <test@email312.net>
To: example@gmail.com
MIME-Version: 1.0
Date: Mon, 31 Mar 2025 09:09:56 +0000
Content-Type: multipart/alternative; boundary=t5wkULPt

--t5wkULPt
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable

=C2=A0

=

--t5wkULPt
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: quoted-printable

<html>
<head>
<body>
</body>
</html>
--t5wkULPt--
62 changes: 62 additions & 0 deletions test/message-splitter-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const fs = require('fs');
const crypto = require('crypto');
const MessageSplitter = require('../lib/message-splitter');
const MessageJoiner = require('../lib/message-joiner');
const { Readable, Transform } = require('stream');

module.exports['Split simple message'] = test => {
let splitter = new MessageSplitter();
Expand Down Expand Up @@ -450,6 +451,67 @@ module.exports['Split multipart message with embedded inline message/rfc88'] = t
);
};

module.exports['handles line break lines split into 2-byte chunks'] = test => {
const message = fs.readFileSync(__dirname + '/fixtures/original.txt');

const MAX_HEAD_SIZE = 2 * 1024 * 1024;
const splitter = new MessageSplitter({
ignoreEmbedded: true,
maxHeadSize: MAX_HEAD_SIZE
});

splitter.on('data', data => {
switch (data.type) {
case 'node':
// node header block
break;
case 'data':
// multipart message structure
// this is not related to any specific 'node' block as it includes
// everything between the end of some node body and between the next header
console.log(JSON.stringify(data.value.toString()));
break;
case 'body':
// Leaf element body. Includes the body for the last 'node' block. You might
// have several 'body' calls for a single 'node' block
console.log(JSON.stringify(data.value.toString()));
// console.log(data.value.toString());
break;
}
});

// Create a Transform stream that processes at most 2 bytes at a time
class TwoByteChunker extends Transform {
constructor(options) {
super(options);
}

_transform(chunk, encoding, callback) {
// Process the chunk in 2-byte segments
for (let i = 0; i < chunk.length; i += 2) {
const twoByteChunk = chunk.slice(i, i + 2);
// Push each 2-byte chunk to the output
this.push(twoByteChunk);
// console.log(`Processing chunk: ${JSON.stringify(twoByteChunk.toString())}`);
}
callback();
}
}

// Create a source stream with some test data
const source = Readable.from(message);

console.log(JSON.stringify(message.toString())); // Log raw message string for reference

// Pipe through our chunker
const chunker = new TwoByteChunker();

source.pipe(chunker).pipe(splitter);

test.expect(0);
test.done();
};

module.exports['Split multipart message with embedded message/rfc822 with header only'] = test => {
let splitter = new MessageSplitter();

Expand Down