From fa885f44ddef3d4e6d68e01353ed684ace1e8edc Mon Sep 17 00:00:00 2001 From: Mic Date: Sun, 12 Apr 2026 22:10:00 +0200 Subject: [PATCH] improved multipart html body decoding --- js/mzta-utils.js | 44 +++++++++++++++++++++++++++++--------------- mzta-background.js | 4 ++-- 2 files changed, 31 insertions(+), 17 deletions(-) diff --git a/js/mzta-utils.js b/js/mzta-utils.js index 549d7502..9f49155f 100644 --- a/js/mzta-utils.js +++ b/js/mzta-utils.js @@ -146,38 +146,52 @@ export async function getMailSubject(tab){ } function extractTextParts(fullMessage) { - const textParts = []; - + const textParts = [] function walkParts(parts) { for (const part of parts) { if (part.parts && part.parts.length > 0) { - // Recursively walk through sub-parts - walkParts(part.parts); - } else { - // Check if contentType starts with "text/" - if (part.contentType && part.contentType.startsWith("text/")) { - textParts.push(part); - } + walkParts(part.parts) + } + // console.log(">>>>>>>>>>>> extractTextParts: part.contentType: " + part.contentType + ", part.decryptionStatus: " + part.decryptionStatus + ", part.body: " + part.body); + if (part.contentType && part.contentType.startsWith('text/')) { + textParts.push(part) } } } - if (fullMessage.parts && fullMessage.parts.length > 0) { - walkParts(fullMessage.parts); + walkParts(fullMessage.parts) } + return textParts +} - return textParts; +function smartDecode(buf) { + try { + return new TextDecoder('utf-8', { fatal: true }).decode(buf); + } catch (e) { + return new TextDecoder('windows-1252').decode(buf); + } } -export function getMailBody(fullMessage){ +export async function getMailBody(fullMessage, messageId) { const textParts = extractTextParts(fullMessage); let text = ""; let html = ""; + // console.log(">>>>>>>>>>>>>> getMailBody: textParts: " + JSON.stringify(textParts)); + // console.log(">>>>>>>>>>>>>> getMailBody: fullMessage: " + JSON.stringify(fullMessage)); for (const part of textParts) { + let body = part.body; + if ((body === undefined || body === "") && messageId && part.partName) { + const file = await browser.messages.getAttachmentFile(messageId, part.partName); + const buf = await file.arrayBuffer(); + //const buf = new TextDecoder('utf-8').decode(buf); + body = smartDecode(buf); + } if (part.contentType === "text/plain") { - text += part.body; + // console.log(">>>>>>>>>>>>>> getMailBody: part.body (TEXT): " + body); + text += body ?? ""; } else if (part.contentType === "text/html") { - html += part.body; + // console.log(">>>>>>>>>>>>>> getMailBody: part.body (HTML): " + (body ? body.substring(0, 80) : body)); + html += body ?? ""; } } if(html === "") { diff --git a/mzta-background.js b/mzta-background.js index fdd583b8..b1501aab 100644 --- a/mzta-background.js +++ b/mzta-background.js @@ -799,7 +799,7 @@ async function _generateSpamReportForMessage(headerMessageId, options = {}) { } message = messageResult.messages[0]; curr_fullMessage = await browser.messages.getFull(message.id); - msg_text = getMailBody(curr_fullMessage); + msg_text = await getMailBody(curr_fullMessage); body_text = htmlBodyToPlainText(msg_text.html); if (body_text.length == 0) { body_text = msg_text.text.replace(/\s+/g, ' ').trim(); @@ -1729,7 +1729,7 @@ async function processEmails(args) { if (addTagsAuto || spamFilter) { curr_fullMessage = await browser.messages.getFull(message.id); - msg_text = getMailBody(curr_fullMessage); + msg_text = await getMailBody(curr_fullMessage); taLog.log("Starting from the HTML body if present and converting to plain text..."); body_text = htmlBodyToPlainText(msg_text.html); if( body_text.length == 0 ){