From d3361d4aa73d99d7ff1968ed73714f06c0c07baf Mon Sep 17 00:00:00 2001 From: mindon Date: Thu, 4 Jul 2024 18:09:18 +0800 Subject: [PATCH 1/5] fix: multiple application/octet-stream and mixed with multiparts attachments --- src/EmlReader.js | 47 +++++++++++++++++------------------------- src/MultiPartParser.js | 14 ++++++------- 2 files changed, 25 insertions(+), 36 deletions(-) diff --git a/src/EmlReader.js b/src/EmlReader.js index 8bb6618..ae59853 100644 --- a/src/EmlReader.js +++ b/src/EmlReader.js @@ -62,35 +62,26 @@ export class EmlReader { } getAttachments() { - let attachments=[], mixedPart = this.#multipartParser.getPartByContentType('multipart', 'mixed'); - - // multipart/mixed - if (mixedPart) { - for (const subPart of mixedPart.getMultiParts()) { - if (subPart.isAttachment) { - attachments.push({ - filename: subPart.getFilename(), - contentType: subPart.contentType, - content: subPart.getBody(), - filesize: subPart.getBody().byteLength - }); - } - } - - // multipart/octet-stream - } else { - const att = this.#multipartParser.getPartByContentType('application', 'octet-stream'); - if (att && att.getFilename()) { - attachments.push({ - filename: att.getFilename(), - contentType: att.contentType, - content: att.getBody(), - filesize: att.getBody().byteLength - }); - } + let attachments = []; + const mixedPart = this.#multipartParser.getPartByContentType('multipart', 'mixed'); + if(mixedPart) for (const subPart of mixedPart.getMultiParts()) { + if (!subPart.isAttachment) continue; + attachments.push({ + filename: subPart.getFilename(), + contentType: subPart.contentType, + content: subPart.getBody(), + filesize: subPart.getBody().byteLength + }); } - - return attachments; + let atts = this.#multipartParser.getPartByContentType('application', 'octet-stream'); + if (!atts) return attachments; + if (! atts instanceof Array) atts = [atts]; + return attachments.concat(atts.filter(att => att && att.getFilename()).map(att => ({ + filename: att.getFilename(), + contentType: att.contentType, + content: att.getBody(), + filesize: att.getBody().byteLength + }))); } getMessageText() { diff --git a/src/MultiPartParser.js b/src/MultiPartParser.js index 6413bb6..b769a02 100644 --- a/src/MultiPartParser.js +++ b/src/MultiPartParser.js @@ -290,16 +290,14 @@ export class MultiPartParser { return me; } + const list = []; for (let mp of me.getMultiParts()) { - if (mp instanceof MultiPartParser) { - let subMp = this.#recursiveGetByContentType(mp, mediaType, subType); - if (subMp) { - return subMp; - } - } + if (!(mp instanceof MultiPartParser)) continue; + let subMp = this.#recursiveGetByContentType(mp, mediaType, subType); + if (subMp) list.push(subMp); } - - return null; + return list.length == 1 + ? list[0] : (list.length == 0 ? null : list); } #getLineEnding(arrbuf) { From e08083b84ef538b3d7663ef497f9d9091d88cdf2 Mon Sep 17 00:00:00 2001 From: mindon Date: Fri, 5 Jul 2024 12:05:27 +0800 Subject: [PATCH 2/5] fix: images --- src/EmlReader.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/EmlReader.js b/src/EmlReader.js index ae59853..5d4e1ed 100644 --- a/src/EmlReader.js +++ b/src/EmlReader.js @@ -74,8 +74,16 @@ export class EmlReader { }); } let atts = this.#multipartParser.getPartByContentType('application', 'octet-stream'); - if (!atts) return attachments; - if (! atts instanceof Array) atts = [atts]; + if (!atts) { + atts = []; + } else if (!atts instanceof Array) { + atts = [atts]; + } + const images = this.#multipartParser.getPartByContentType('image'); + if (images) { + if (images instanceof Array) atts = atts.concat(images); + else atts.push(images); + } return attachments.concat(atts.filter(att => att && att.getFilename()).map(att => ({ filename: att.getFilename(), contentType: att.contentType, From db21c5319e1db151610ca41ed5ff6dfad7e09762 Mon Sep 17 00:00:00 2001 From: mindon Date: Fri, 5 Jul 2024 14:23:31 +0800 Subject: [PATCH 3/5] feat: support attachments sorted by cid orders --- src/EmlReader.js | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/EmlReader.js b/src/EmlReader.js index 5d4e1ed..a95cba8 100644 --- a/src/EmlReader.js +++ b/src/EmlReader.js @@ -61,7 +61,7 @@ export class EmlReader { return this.#multipartParser.getHeader(key, decode, removeLineBreaks); } - getAttachments() { + getAttachments(sorted = false) { let attachments = []; const mixedPart = this.#multipartParser.getPartByContentType('multipart', 'mixed'); if(mixedPart) for (const subPart of mixedPart.getMultiParts()) { @@ -84,12 +84,26 @@ export class EmlReader { if (images instanceof Array) atts = atts.concat(images); else atts.push(images); } - return attachments.concat(atts.filter(att => att && att.getFilename()).map(att => ({ + const result = attachments.concat(atts.filter(att => att && att.getFilename()).map(att => ({ filename: att.getFilename(), contentType: att.contentType, content: att.getBody(), filesize: att.getBody().byteLength }))); + if (!sorted) return result; + const cids = (this.getMessageHtml().match(/ src="cid:[^"]+"/g) || []) + .map(s => s.substring(10,s.length-1)); + let n = cids.length; + result.forEach((d, j) => { + let k = -1; + for (let i = 0; i < cids.length; i++) { + k = cids.indexOf(d.filename); + if (k > -1) break; + } + result[j].n = k > -1 ? k : n++; + }) + result.sort((a,b,x='n')=>+(a[x]>b[x])-+(a[x] Date: Fri, 5 Jul 2024 16:04:45 +0800 Subject: [PATCH 4/5] fix: not instanceof Array issue --- src/EmlReader.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EmlReader.js b/src/EmlReader.js index a95cba8..fc2211b 100644 --- a/src/EmlReader.js +++ b/src/EmlReader.js @@ -76,7 +76,7 @@ export class EmlReader { let atts = this.#multipartParser.getPartByContentType('application', 'octet-stream'); if (!atts) { atts = []; - } else if (!atts instanceof Array) { + } else if (!(atts instanceof Array)) { atts = [atts]; } const images = this.#multipartParser.getPartByContentType('image'); From 757368d50d6b9af626692753110daa311859c544 Mon Sep 17 00:00:00 2001 From: mindon Date: Mon, 4 Nov 2024 10:35:56 +0800 Subject: [PATCH 5/5] Update MultiPartParser.js --- src/MultiPartParser.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/MultiPartParser.js b/src/MultiPartParser.js index b769a02..19079e9 100644 --- a/src/MultiPartParser.js +++ b/src/MultiPartParser.js @@ -228,7 +228,7 @@ export class MultiPartParser { const decoder = new TextDecoder(); raw = decoder.decode(raw); } - const binary_string = window.atob(raw); + const binary_string = atob(raw); const len = binary_string.length; const bytes = new Uint8Array(len); for (let i = 0; i < len; i++) {