Skip to content

Commit ca3a3e0

Browse files
authored
Merge pull request #27 from thomasoeser/main
Handle text and html body messages that include Unicode characters and are encoded in base64
2 parents 1632713 + 17c4f1c commit ca3a3e0

File tree

7 files changed

+2355
-12
lines changed

7 files changed

+2355
-12
lines changed

dist/charset.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"use strict";
22
Object.defineProperty(exports, "__esModule", { value: true });
3+
exports.convert = exports.decode = exports.arr2str = exports.encode = void 0;
34
var text_encoding_1 = require("text-encoding");
45
/**
56
* Encodes an unicode string into an Uint8Array object as UTF-8

dist/index.js

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
"use strict";
22
Object.defineProperty(exports, "__esModule", { value: true });
3+
exports.GBKUTF8 = exports.buildEml = exports.readEml = exports.parseEml = exports.completeBoundary = exports.decode = exports.encode = exports.convert = exports.Base64 = exports.mimeDecode = exports.unquotePrintable = exports.unquoteString = exports.getCharset = exports.getBoundary = exports.createBoundary = exports.toEmailAddress = exports.getEmailAddress = void 0;
34
/**
45
* @author superchow
56
67
*/
78
var js_base64_1 = require("js-base64");
8-
exports.Base64 = js_base64_1.Base64;
9+
Object.defineProperty(exports, "Base64", { enumerable: true, get: function () { return js_base64_1.Base64; } });
910
var charset_1 = require("./charset");
10-
exports.convert = charset_1.convert;
11-
exports.decode = charset_1.decode;
12-
exports.encode = charset_1.encode;
11+
Object.defineProperty(exports, "convert", { enumerable: true, get: function () { return charset_1.convert; } });
12+
Object.defineProperty(exports, "decode", { enumerable: true, get: function () { return charset_1.decode; } });
13+
Object.defineProperty(exports, "encode", { enumerable: true, get: function () { return charset_1.encode; } });
1314
var utils_1 = require("./utils");
14-
exports.GBKUTF8 = utils_1.GB2312UTF8;
15-
exports.mimeDecode = utils_1.mimeDecode;
15+
Object.defineProperty(exports, "GBKUTF8", { enumerable: true, get: function () { return utils_1.GB2312UTF8; } });
16+
Object.defineProperty(exports, "mimeDecode", { enumerable: true, get: function () { return utils_1.mimeDecode; } });
1617
/**
1718
* log for test
1819
*/
@@ -274,7 +275,6 @@ exports.parseEml = parse;
274275
* @returns {ParsedEmlJson}
275276
*/
276277
function parseRecursive(lines, start, parent, options) {
277-
var _a, _b, _c;
278278
var boundary = null;
279279
var lastHeaderName = '';
280280
var findBoundary = '';
@@ -373,15 +373,15 @@ function parseRecursive(lines, start, parent, options) {
373373
}
374374
if (insideBoundary) {
375375
//Search for boundary end
376-
if (((_a = boundary) === null || _a === void 0 ? void 0 : _a.boundary) && lines[i - 1] == '' && line.indexOf('--' + findBoundary + '--') == 0) {
376+
if ((boundary === null || boundary === void 0 ? void 0 : boundary.boundary) && lines[i - 1] == '' && line.indexOf('--' + findBoundary + '--') == 0) {
377377
insideBoundary = false;
378378
complete(boundary);
379379
continue;
380380
}
381-
if (((_b = boundary) === null || _b === void 0 ? void 0 : _b.boundary) && line.indexOf('--' + findBoundary + '--') == 0) {
381+
if ((boundary === null || boundary === void 0 ? void 0 : boundary.boundary) && line.indexOf('--' + findBoundary + '--') == 0) {
382382
continue;
383383
}
384-
(_c = boundary) === null || _c === void 0 ? void 0 : _c.lines.push(line);
384+
boundary === null || boundary === void 0 ? void 0 : boundary.lines.push(line);
385385
}
386386
}
387387
else {
@@ -714,7 +714,10 @@ function read(eml, options, callback) {
714714
//Message in HTML format
715715
result.html = content.replace(/\r\n|(")/g, '').replace(/\"/g, "\"");
716716
try {
717-
if (js_base64_1.Base64.btoa(js_base64_1.Base64.atob(result.html)) == result.html) {
717+
if (encoding === 'base64') {
718+
result.html = js_base64_1.Base64.decode(result.html);
719+
}
720+
else if (js_base64_1.Base64.btoa(js_base64_1.Base64.atob(result.html)) == result.html) {
718721
result.html = js_base64_1.Base64.atob(result.html);
719722
}
720723
}
@@ -731,6 +734,9 @@ function read(eml, options, callback) {
731734
if (typeof content !== 'string') {
732735
content = charset_1.decode(content, charset);
733736
}
737+
if (encoding === 'base64') {
738+
content = js_base64_1.Base64.decode(content);
739+
}
734740
//Plain text message
735741
result.text = content;
736742
result.textheaders = {

dist/utils.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"use strict";
22
Object.defineProperty(exports, "__esModule", { value: true });
3+
exports.GB2312UTF8 = exports.isStringOrError = exports.mimeDecode = exports.wrap = exports.guid = exports.getCharsetName = exports.getBoundary = void 0;
34
var charset_1 = require("./charset");
45
/**
56
* Gets the boundary name

src/index.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -860,7 +860,10 @@ function read(
860860
result.html = content.replace(/\r\n|(")/g, '').replace(/\"/g, `"`);
861861

862862
try {
863-
if (Base64.btoa(Base64.atob(result.html)) == result.html) {
863+
if (encoding === 'base64') {
864+
result.html = Base64.decode(result.html);
865+
}
866+
else if (Base64.btoa(Base64.atob(result.html)) == result.html) {
864867
result.html = Base64.atob(result.html);
865868
}
866869
} catch (error) {
@@ -876,6 +879,9 @@ function read(
876879
if (typeof content !== 'string') {
877880
content = decode(content as Uint8Array, charset);
878881
}
882+
if (encoding === 'base64') {
883+
content = Base64.decode(content);
884+
}
879885
//Plain text message
880886
result.text = content;
881887
result.textheaders = {

test/fixtures/unicode.eml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
MIME-Version: 1.0
2+
Date: Thu, 29 Sep 2022 12:22:20 +0100
3+
Message-ID: <CAGFso0R6WbMomMx6mFFJzt_wiL8wRm3sN0YQwXz12Ugbt72XSw@mail.gmail.com>
4+
Subject: =?UTF-8?q?Off-The-Beaten-Path_Trails_You've_Never_Heard_Of!__=F0=9F=8C=8F?=
5+
From: =?UTF-8?Q?Nobody_there?= <[email protected]>
6+
To: =?UTF-8?Q?Nobody_here?= <[email protected]>
7+
Content-Type: multipart/alternative;
8+
boundary="_000_CAAzdmDbpBCQ8p50QA09RWh7B4ScFWKLbP2C4hvwN0fhxhwmailgmai_"
9+
MIME-Version: 1.0
10+
11+
--_000_CAAzdmDbpBCQ8p50QA09RWh7B4ScFWKLbP2C4hvwN0fhxhwmailgmai_
12+
Content-Type: text/plain; charset="utf-8"
13+
Content-Transfer-Encoding: base64
14+
15+
DQpFeHRlcm5hbCBlLW1haWwuIFVzZSBjYXV0aW9uISAvIENvdXJyaWVsIGV4dGVybmUuIEZhaXRl
16+
cyBhdHRlbnRpb24hDQoNCg0KDQoNCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fDQpr
17+
amtqICDjgrPjg5Tjg7zjg5zjgr/jg7PjgpLjgq/jg6rjg4Pjgq/jgZnjgovjgagNCg0K
18+
19+
--_000_CAAzdmDbpBCQ8p50QA09RWh7B4ScFWKLbP2C4hvwN0fhxhwmailgmai_
20+
Content-Type: text/html; charset="utf-8"
21+
Content-ID: <[email protected]>
22+
Content-Transfer-Encoding: base64
23+
24+
PGh0bWw+DQo8aGVhZD4NCjxtZXRhIGh0dHAtZXF1aXY9IkNvbnRlbnQtVHlwZSIgY29udGVudD0i
25+
dGV4dC9odG1sOyBjaGFyc2V0PXV0Zi04Ij4NCjwvaGVhZD4NCjxib2R5Pg0KPHRhYmxlPg0KPGJy
26+
Pg0KPHRib2R5Pg0KPHRyPg0KPHRkIGFsaWduPSJsZWZ0IiBoZWlnaHQ9IjAiIHdpZHRoPSIxMDAl
27+
IiBiZ2NvbG9yPSIjZmZmZjAwIj48Yj5FeHRlcm5hbCBlLW1haWwuIFVzZSBjYXV0aW9uISAvIENv
28+
dXJyaWVsIGV4dGVybmUuIEZhaXRlcyBhdHRlbnRpb24hDQo8L2I+PC90ZD4NCjxicj4NCjwvdHI+
29+
DQo8YnI+DQo8L3Rib2R5Pg0KPC90YWJsZT4NCjxicj4NCjxicj4NCjxicj4NCjxocj4NCjxkaXYg
30+
ZGlyPSJsdHIiPmtqa2ombmJzcDsgPGIgc3R5bGU9ImxldHRlci1zcGFjaW5nOi0ycHgiPuOCs+OD
31+
lOODvOODnOOCv+ODs+OCkuOCr+ODquODg+OCr+OBmeOCi+OBqDxicj4NCjxicj4NCjwvYj48L2Rp
32+
dj4NCjwvYm9keT4NCjwvaHRtbD4NCg==
33+
34+
--_000_CAAzdmDbpBCQ8p50QA09RWh7B4ScFWKLbP2C4hvwN0fhxhwmailgmai_--

test/index.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ describe('readEml should decode', () => {
108108
const readEmlJson = readEmlForTest('./fixtures/smallEmail.eml');
109109
expect(readEmlJson.subject).to.equal('Off-The-Beaten-Path Trails You\'ve Never Heard Of! 🌏');
110110
expect(readEmlJson.text.trim()).to.equal('A small body with _underscores.');
111+
expect(readEmlJson.html).to.contain('A small body with _underscores');
111112
})
112113

113114
it('headers with line breaks correctly', () => {
@@ -129,4 +130,11 @@ describe('readEml should decode', () => {
129130
expect(readEmlJson.attachments.length).to.equal(1);
130131
expect(readEmlJson.attachments[0].name).to.equal('image.png');
131132
});
133+
134+
it('base64 encoded text and html body', () => {
135+
const readEmlJson = readEmlForTest('./fixtures/unicode.eml');
136+
expect(readEmlJson.text).to.contain('コピーボタンをクリックすると');
137+
expect(readEmlJson.html).to.contain('コピーボタンをクリックすると');
138+
});
139+
132140
})

0 commit comments

Comments
 (0)