Skip to content

Commit 350dc5b

Browse files
authored
Merge pull request #11 from openimap/bodystructure
Resolves #10: Emit the bodystructure during parsing
2 parents b1642c2 + 2c94f6e commit 350dc5b

File tree

4 files changed

+79
-5
lines changed

4 files changed

+79
-5
lines changed

README.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,16 @@ parser.onbody = function(node, chunk){
6868
};
6969
```
7070

71+
#### Bodystructure
72+
73+
Bodystructure is the original raw message stripped of bodies and multipart preambles. MIME stores like to store the bodystructure of MIME content in raw (loss-less) form, to later run through a MIME parser to answer IMAP or WebDAV type queries. Bodystructure is emitted in chunks of String. Define `onbodystructure` to catch these chunks:
74+
75+
```javascript
76+
parser.onbodystructure = function(chunk){
77+
console.log(chunk);
78+
};
79+
```
80+
7181
#### Parse end
7282

7383
When the parsing is finished, `onend` is called
@@ -80,7 +90,7 @@ parser.onend = function(){
8090

8191
## Quirks
8292

83-
This seems like asynchronous but actually it is not. So always define `onheader`, `onbody` and `onend` before writing the first chunk of data to the parser.
93+
This seems like asynchronous but actually it is not. So always define `onheader`, `onbody`, `onbodystructure`, and `onend` before writing the first chunk of data to the parser.
8494

8595
**message/rfc822** is automatically parsed if the mime part does not have a `Content-Disposition: attachment` header, otherwise it will be emitted as a regular attachment (as one long Uint8Array value).
8696

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "emailjs-mime-parser",
3-
"version": "1.0.0",
3+
"version": "1.0.1-prerelease",
44
"homepage": "https://github.com/emailjs/emailjs-mime-parser",
55
"description": "Parse a mime tree, no magic included.",
66
"author": "Andris Reinman <[email protected]>",

src/emailjs-mime-parser.js

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,14 @@
323323
*/
324324
MimeParser.prototype.onbody = function() {};
325325

326+
/**
327+
* Override this function.
328+
* Called when a bodystructure chunk is emitted. The bodystructure is the raw multipart message with empty bodies.
329+
* @event
330+
* @param {String} chunk Bodystructure chunk
331+
*/
332+
MimeParser.prototype.onbodystructure = function() {};
333+
326334
// NODE PROCESSING
327335

328336
/**
@@ -421,7 +429,7 @@
421429
// Public methods
422430

423431
/**
424-
* Processes an enitre input line
432+
* Processes an entire input line
425433
*
426434
* @param {String} line Entire input line as 'binary' string
427435
*/
@@ -458,6 +466,7 @@
458466
if (!line) {
459467
this._parseHeaders();
460468
this._parser.onheader(this);
469+
this._parser.onbodystructure(this.header.join('\n') + '\n\n');
461470
this._state = 'BODY';
462471
return;
463472
}
@@ -678,7 +687,7 @@
678687
};
679688

680689
/**
681-
* Parses Content-Trasnfer-Encoding value to see if the body needs to be converted
690+
* Parses Content-Transfer-Encoding value to see if the body needs to be converted
682691
* before it can be emitted
683692
*/
684693
MimeNode.prototype._processContentTransferEncoding = function() {
@@ -700,20 +709,22 @@
700709

701710
if (this._isMultipart) {
702711
if (line === '--' + this._multipartBoundary) {
712+
this._parser.onbodystructure(line + '\n');
703713
if (this._currentChild) {
704714
this._currentChild.finalize();
705715
}
706716
this._currentChild = new MimeNode(this, this._parser);
707717
this._childNodes.push(this._currentChild);
708718
} else if (line === '--' + this._multipartBoundary + '--') {
719+
this._parser.onbodystructure(line + '\n');
709720
if (this._currentChild) {
710721
this._currentChild.finalize();
711722
}
712723
this._currentChild = false;
713724
} else if (this._currentChild) {
714725
this._currentChild.writeLine(line);
715726
} else {
716-
// Ignore body for multipart
727+
// Ignore multipart preamble
717728
}
718729
} else if (this._isRfc822) {
719730
this._currentChild.writeLine(line);

test/mimeparser-unit.js

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -948,6 +948,59 @@
948948
parser.write(fixture);
949949
parser.end();
950950
});
951+
952+
it('should emit bodystructure', function(done) {
953+
var fixture =
954+
'MIME-Version: 1.0\n' +
955+
'Content-Type: multipart/mixed;\n' +
956+
' boundary="------------304E429112E7D6AC36F087A8"\n' +
957+
'\n' +
958+
'This is a multi-part message in MIME format.\n' +
959+
'--------------304E429112E7D6AC36F087A8\n' +
960+
'Content-Type: text/html; charset=utf-8\n' +
961+
'Content-Transfer-Encoding: 7bit\n' +
962+
'\n' +
963+
'<html/>\n' +
964+
'--------------304E429112E7D6AC36F087A8\n' +
965+
'Content-Type: text/plain; charset=UTF-8; x-mac-type="0"; x-mac-creator="0";\n' +
966+
' name="hello.mime"\n' +
967+
'Content-Transfer-Encoding: base64\n' +
968+
'Content-Disposition: attachment;\n' +
969+
' filename="hello.mime"\n' +
970+
'\n' +
971+
'SGkgbW9tIQ==\n' +
972+
'--------------304E429112E7D6AC36F087A8--\n';
973+
974+
var expectedBodystructure =
975+
'MIME-Version: 1.0\n' +
976+
'Content-Type: multipart/mixed;\n' +
977+
' boundary="------------304E429112E7D6AC36F087A8"\n' +
978+
'\n' +
979+
'--------------304E429112E7D6AC36F087A8\n' +
980+
'Content-Type: text/html; charset=utf-8\n' +
981+
'Content-Transfer-Encoding: 7bit\n' +
982+
'\n' +
983+
'--------------304E429112E7D6AC36F087A8\n' +
984+
'Content-Type: text/plain; charset=UTF-8; x-mac-type="0"; x-mac-creator="0";\n' +
985+
' name="hello.mime"\n' +
986+
'Content-Transfer-Encoding: base64\n' +
987+
'Content-Disposition: attachment;\n' +
988+
' filename="hello.mime"\n' +
989+
'\n' +
990+
'--------------304E429112E7D6AC36F087A8--\n';
991+
992+
var bodystructure = '';
993+
parser.onbodystructure = function(chunk) {
994+
bodystructure += chunk;
995+
};
996+
997+
parser.onend = function() {
998+
expect(bodystructure).to.equal(expectedBodystructure);
999+
done();
1000+
};
1001+
parser.write(fixture);
1002+
parser.end();
1003+
});
9511004
});
9521005
});
9531006
}));

0 commit comments

Comments
 (0)