From a7a17b7cb5e0a3d340568c5200ca2391edeb6285 Mon Sep 17 00:00:00 2001 From: mic Date: Sun, 15 Feb 2026 10:58:44 +0100 Subject: [PATCH 1/3] processEmails now accepts an obj as argument. see #631 --- mzta-background.js | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/mzta-background.js b/mzta-background.js index 7be949a3..13da6dc1 100644 --- a/mzta-background.js +++ b/mzta-background.js @@ -1041,7 +1041,11 @@ browser.menus.onClicked.addListener( (info, tab) => { _summarize = true; } if(_add_tags || _spamfilter){ - processEmails(getMessages(info.selectedMessages), _add_tags, _spamfilter); + processEmails({ + messages: getMessages(info.selectedMessages), + addTagsAuto: _add_tags, + spamFilter: _spamfilter + }); } if(_summarize) { // info.selectedMessages is of type MessageList @@ -1135,7 +1139,11 @@ const newEmailListener = (folder, messagesList) => { let add_tags_auto_enabled = prefs_init.add_tags && prefs_init.add_tags_auto; - await processEmails(messages, add_tags_auto_enabled, prefs_init.spamfilter); + await processEmails({ + messages: messages, + addTagsAuto: add_tags_auto_enabled, + spamFilter: prefs_init.spamfilter + }); if(prefs_init.spamfilter){ taSpamReport.truncReportData(); @@ -1145,7 +1153,13 @@ const newEmailListener = (folder, messagesList) => { return _newEmailListener(); } -async function processEmails(messages, addTagsAuto, spamFilter) { +async function processEmails(args) { + const { + messages, + addTagsAuto = false, + spamFilter = false + } = args; + taWorkingStatus.startWorking(); let prefs_aats = await browser.storage.sync.get({ From ca2323ba8806e8e38ec8d44c4009f3150f828472 Mon Sep 17 00:00:00 2001 From: mic Date: Sun, 15 Feb 2026 11:08:38 +0100 Subject: [PATCH 2/3] processEmails now also does the summarize. see #631 --- mzta-background.js | 442 ++++++++++++++++++++++----------------------- 1 file changed, 219 insertions(+), 223 deletions(-) diff --git a/mzta-background.js b/mzta-background.js index 13da6dc1..de4c33b4 100644 --- a/mzta-background.js +++ b/mzta-background.js @@ -1040,87 +1040,16 @@ browser.menus.onClicked.addListener( (info, tab) => { if(info.menuItemId === contextMenuID_Summarize) { _summarize = true; } - if(_add_tags || _spamfilter){ + if(_add_tags || _spamfilter || _summarize){ processEmails({ messages: getMessages(info.selectedMessages), addTagsAuto: _add_tags, - spamFilter: _spamfilter + spamFilter: _spamfilter, + summarize: _summarize }); } - if(_summarize) { - // info.selectedMessages is of type MessageList - summarizeEmails(getMessages(info.selectedMessages)); - } }); -async function summarizeEmails(messages) { - taWorkingStatus.startWorking(); - - // we have three prompts, the actual assignment for the LLM, the email - // template prompt, and the email separator prompt - const specialPrompts = await getSpecialPrompts(); - const prompt = specialPrompts.find((prompt) => prompt.id === 'prompt_summarize'); - const prompt_email = specialPrompts.find((prompt) => prompt.id === 'prompt_summarize_email_template'); - const prompt_email_separator = specialPrompts.find((prompt) => prompt.id === 'prompt_summarize_email_separator'); - - const tabs = await browser.tabs.query({ active: true, currentWindow: true }); - const chatgpt_lang = await taPromptUtils.getDefaultLang(prompt); - - // replace placeholders in the prompts the assignment prompt and email - // separator prompt do not have a message as context, so there is only - // limited things to replace - const prompt_string = await taPromptUtils.preparePrompt({ - curr_prompt: prompt, - chatgpt_lang: chatgpt_lang, - }); - const prompt_email_separator_string = await taPromptUtils.preparePrompt({ - curr_prompt: prompt_email_separator, - chatgpt_lang: chatgpt_lang, - }); - - - // assemble all email messages into one string and add the assignment prompt - const messages_list = []; - for await (let curr_message of messages) { - - // extract body of current message as text - const curr_message_full = await browser.messages.getFull(curr_message.id); - const curr_body_full_html = getMailBody(curr_message_full); - const curr_body_full_text = htmlBodyToPlainText(curr_body_full_html.html); - if( curr_body_full_text.length === 0) { - taLog.log("No HTML found in the message body, using plain text..."); - curr_body_full_text = curr_message_full.text; - } - - messages_list.push(await taPromptUtils.preparePrompt({ - curr_prompt: prompt_email, - curr_message: curr_message, - chatgpt_lang: chatgpt_lang, - body_text: curr_body_full_text, - subject_text: curr_message_full.headers.subject, - msg_text: curr_body_full_html, - })); - }; - const messages_string = messages_list.join(prompt_email_separator_string); - - const full_prompt = prompt_string + prompt_email_separator_string + messages_string; - - // console.log(full_prompt); - - // send the prompt to the chat interface - openChatGPT( - full_prompt, - prompt.action, - tabs[0].id, - prompt.name, - prompt.need_custom_text, - prompt - ) - - taWorkingStatus.stopWorking(); - return {ok : '1'}; -} - // Listening for new received emails const newEmailListener = (folder, messagesList) => { @@ -1157,168 +1086,235 @@ async function processEmails(args) { const { messages, addTagsAuto = false, - spamFilter = false + spamFilter = false, + summarize = false } = args; taWorkingStatus.startWorking(); + + if (addTagsAuto || spamFilter) { + let prefs_aats = await browser.storage.sync.get({ + add_tags_maxnum: prefs_default.add_tags_maxnum, + connection_type: prefs_default.connection_type, + add_tags_force_lang: prefs_default.add_tags_force_lang, + default_chatgpt_lang: prefs_default.default_chatgpt_lang, + add_tags_auto_force_existing: prefs_default.add_tags_auto_force_existing, + add_tags_enabled_accounts: prefs_default.add_tags_enabled_accounts, + add_tags_exclusions_exact_match: prefs_default.add_tags_exclusions_exact_match, + add_tags_auto_uselist: prefs_default.add_tags_auto_uselist, + add_tags_auto_uselist_list: prefs_default.add_tags_auto_uselist_list, + spamfilter_enabled_accounts: prefs_default.spamfilter_enabled_accounts, + ...getDynamicSettingsDefaults(['use_specific_integration', 'connection_type']), + do_debug: prefs_default.do_debug, + }); + // console.log(">>>>>>>>>>>>>>>> prefs_aats: " + JSON.stringify(prefs_aats)); + for await (let message of messages) { + let curr_fullMessage = null; + let msg_text = null; + let body_text = ''; - let prefs_aats = await browser.storage.sync.get({ - add_tags_maxnum: prefs_default.add_tags_maxnum, - connection_type: prefs_default.connection_type, - add_tags_force_lang: prefs_default.add_tags_force_lang, - default_chatgpt_lang: prefs_default.default_chatgpt_lang, - add_tags_auto_force_existing: prefs_default.add_tags_auto_force_existing, - add_tags_enabled_accounts: prefs_default.add_tags_enabled_accounts, - add_tags_exclusions_exact_match: prefs_default.add_tags_exclusions_exact_match, - add_tags_auto_uselist: prefs_default.add_tags_auto_uselist, - add_tags_auto_uselist_list: prefs_default.add_tags_auto_uselist_list, - spamfilter_enabled_accounts: prefs_default.spamfilter_enabled_accounts, - ...getDynamicSettingsDefaults(['use_specific_integration', 'connection_type']), - do_debug: prefs_default.do_debug, - }); - // console.log(">>>>>>>>>>>>>>>> prefs_aats: " + JSON.stringify(prefs_aats)); - for await (let message of messages) { - let curr_fullMessage = null; - let msg_text = null; - let body_text = ''; - - if (addTagsAuto || spamFilter) { - curr_fullMessage = await browser.messages.getFull(message.id); - msg_text = 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 ){ - taLog.log("No HTML found in the message body, using plain text..."); - body_text = msg_text.text.replace(/\s+/g, ' ').trim(); - } - } - - if (addTagsAuto) { - if(prefs_aats.add_tags_enabled_accounts.length > 0){ - let accountId = message.folder.accountId; - if(!prefs_aats.add_tags_enabled_accounts.includes(accountId)){ - taLog.log("Account " + accountId + " not enabled for add_tags, skipping..."); - continue; + if (addTagsAuto || spamFilter) { + curr_fullMessage = await browser.messages.getFull(message.id); + msg_text = 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 ){ + taLog.log("No HTML found in the message body, using plain text..."); + body_text = msg_text.text.replace(/\s+/g, ' ').trim(); } } - let specialFullPrompt_add_tags = ''; - let curr_prompt_add_tags = menus.allPrompts.find(p => p.id === 'prompt_add_tags'); - let tags_full_list = await getTagsList(); - // console.log(">>>>>>>>>>>>> curr_prompt_add_tags: " + JSON.stringify(curr_prompt_add_tags)); - let chatgpt_lang = await taPromptUtils.getDefaultLang(curr_prompt_add_tags); - specialFullPrompt_add_tags = await taPromptUtils.preparePrompt({ - curr_prompt: curr_prompt_add_tags, - curr_message: message, - chatgpt_lang: chatgpt_lang, - body_text: body_text, - subject_text: curr_fullMessage.headers.subject, - msg_text: msg_text, - tags_full_list: tags_full_list - }); - specialFullPrompt_add_tags = taPromptUtils.finalizePrompt_add_tags(specialFullPrompt_add_tags, prefs_aats.add_tags_maxnum, prefs_aats.add_tags_force_lang, prefs_aats.default_chatgpt_lang, prefs_aats.add_tags_auto_uselist, prefs_aats.add_tags_auto_uselist_list); - taLog.log("Special prompt: " + specialFullPrompt_add_tags); - // console.log(">>>>>>>>>> curr_prompt_add_tags.model: " + curr_prompt_add_tags.model); - // console.log(">>>>>>>>>>>>>>>>> getConnectionType add_tags:" + JSON.stringify(getConnectionType(prefs_aats, curr_prompt_add_tags, 'add_tags'))); - let cmd_addTags = new mzta_specialCommand({ - prompt: specialFullPrompt_add_tags, - llm: getConnectionType(prefs_aats, curr_prompt_add_tags, 'add_tags'), - custom_model: curr_prompt_add_tags.model ? curr_prompt_add_tags.model : '', - do_debug: prefs_aats.do_debug, - config: curr_prompt_add_tags - }); - await cmd_addTags.initWorker(); - let tags_current_email = []; - try { - tags_current_email = taPromptUtils.getTagsFromResponse(await cmd_addTags.sendPrompt(), prefs_aats.add_tags_auto_uselist, prefs_aats.add_tags_auto_uselist_list); - } catch (err) { - console.error("[ThunderAI | Auto add_tags] Error getting tags: ", err); - } - taLog.log("tags_current_email: " + JSON.stringify(tags_current_email)); - let _data = { messageId: message.id, tags: tags_current_email }; - _assign_tags(_data, !prefs_aats.add_tags_auto_force_existing, prefs_aats.add_tags_exclusions_exact_match); - } - - if (spamFilter) { - if(prefs_aats.spamfilter_enabled_accounts.length > 0){ - let accountId = message.folder.accountId; - if(!prefs_aats.spamfilter_enabled_accounts.includes(accountId)){ - taLog.log("Account " + accountId + " not enabled for spamfilter, skipping..."); - continue; + + if (addTagsAuto) { + if(prefs_aats.add_tags_enabled_accounts.length > 0){ + let accountId = message.folder.accountId; + if(!prefs_aats.add_tags_enabled_accounts.includes(accountId)){ + taLog.log("Account " + accountId + " not enabled for add_tags, skipping..."); + continue; + } } + let specialFullPrompt_add_tags = ''; + let curr_prompt_add_tags = menus.allPrompts.find(p => p.id === 'prompt_add_tags'); + let tags_full_list = await getTagsList(); + // console.log(">>>>>>>>>>>>> curr_prompt_add_tags: " + JSON.stringify(curr_prompt_add_tags)); + let chatgpt_lang = await taPromptUtils.getDefaultLang(curr_prompt_add_tags); + specialFullPrompt_add_tags = await taPromptUtils.preparePrompt({ + curr_prompt: curr_prompt_add_tags, + curr_message: message, + chatgpt_lang: chatgpt_lang, + body_text: body_text, + subject_text: curr_fullMessage.headers.subject, + msg_text: msg_text, + tags_full_list: tags_full_list + }); + specialFullPrompt_add_tags = taPromptUtils.finalizePrompt_add_tags(specialFullPrompt_add_tags, prefs_aats.add_tags_maxnum, prefs_aats.add_tags_force_lang, prefs_aats.default_chatgpt_lang, prefs_aats.add_tags_auto_uselist, prefs_aats.add_tags_auto_uselist_list); + taLog.log("Special prompt: " + specialFullPrompt_add_tags); + // console.log(">>>>>>>>>> curr_prompt_add_tags.model: " + curr_prompt_add_tags.model); + // console.log(">>>>>>>>>>>>>>>>> getConnectionType add_tags:" + JSON.stringify(getConnectionType(prefs_aats, curr_prompt_add_tags, 'add_tags'))); + let cmd_addTags = new mzta_specialCommand({ + prompt: specialFullPrompt_add_tags, + llm: getConnectionType(prefs_aats, curr_prompt_add_tags, 'add_tags'), + custom_model: curr_prompt_add_tags.model ? curr_prompt_add_tags.model : '', + do_debug: prefs_aats.do_debug, + config: curr_prompt_add_tags + }); + await cmd_addTags.initWorker(); + let tags_current_email = []; + try { + tags_current_email = taPromptUtils.getTagsFromResponse(await cmd_addTags.sendPrompt(), prefs_aats.add_tags_auto_uselist, prefs_aats.add_tags_auto_uselist_list); + } catch (err) { + console.error("[ThunderAI | Auto add_tags] Error getting tags: ", err); + } + taLog.log("tags_current_email: " + JSON.stringify(tags_current_email)); + let _data = { messageId: message.id, tags: tags_current_email }; + _assign_tags(_data, !prefs_aats.add_tags_auto_force_existing, prefs_aats.add_tags_exclusions_exact_match); } - let curr_prompt_spamfilter = await getSpamFilterPrompt(); - // console.log(">>>>>>>>>>>>> curr_prompt_spamfilter: " + JSON.stringify(curr_prompt_spamfilter)); - let chatgpt_lang = await taPromptUtils.getDefaultLang(curr_prompt_spamfilter); - let specialFullPrompt_spamfilter = await taPromptUtils.preparePrompt({ - curr_prompt: curr_prompt_spamfilter, - curr_message: message, - chatgpt_lang: chatgpt_lang, - body_text: body_text, - subject_text: curr_fullMessage.headers.subject, - msg_text: msg_text - }); - taLog.log("Special prompt: " + specialFullPrompt_spamfilter); - // console.log(">>>>>>>> Special prompt for spamfilter: " + specialFullPrompt_spamfilter); - let cmd_spamfilter = new mzta_specialCommand({ - prompt: specialFullPrompt_spamfilter, - llm: getConnectionType(prefs_aats, curr_prompt_spamfilter, 'spamfilter'), - custom_model: curr_prompt_spamfilter.model ? curr_prompt_spamfilter.model : '', - do_debug: prefs_aats.do_debug, - config: curr_prompt_spamfilter - }); - await cmd_spamfilter.initWorker(); - let spamfilter_result = ''; - taLog.log("Sending the prompt..."); - try { - spamfilter_result = (await cmd_spamfilter.sendPrompt()).trim(); - } catch (err) { - console.error("[ThunderAI | SpamFilter] Error getting spamfilter: ", err); - } - taLog.log("spamfilter_result: " + spamfilter_result); - let jsonObj = {}; - taLog.log("Decoding the AI response..."); - try { - jsonObj = extractJsonObject(spamfilter_result); - } catch (e) { - console.error("[ThunderAI | SpamFilter] Error extracting JSON from AI response: ", e); - } - taLog.log("SpamFilter jsonObj: " + JSON.stringify(jsonObj)); - - let report_data = {}; - report_data.report_date = new Date(); - report_data.headerMessageId = message.headerMessageId; - report_data.spamValue = jsonObj.spamValue; - report_data.explanation = jsonObj.explanation; - report_data.subject = curr_fullMessage.headers.subject; - report_data.from = curr_fullMessage.headers.from; - report_data.message_date = new Date(message.date); - report_data.moved = false; - report_data.SpamThreshold = prefs_init.spamfilter_threshold; - - if (jsonObj.spamValue >= prefs_init.spamfilter_threshold) { - taLog.log("Marking as spam [" + message.headerMessageId + "]"); - messenger.messages.update(message.id, { junk: true }); - let spamFolder = await messenger.folders.query({ accountId: message.folder.accountId, specialUse: ['junk'] }); - messenger.messages.move([message.id], spamFolder[0].id); - report_data.moved = true; - taLog.log("Marked as spam [" + message.headerMessageId + "]"); - } - - taSpamReport.saveReportData(report_data, message.headerMessageId); - - // Check if the message is currently displayed and update the banner - if (prefs_init.spamfilter_show_msg_panel) { - let tabs = await browser.tabs.query({ active: true, currentWindow: true }); - if (tabs.length > 0) { - let activeTab = tabs[0]; - let displayedMessage = await browser.messageDisplay.getDisplayedMessage(activeTab.id); - if (displayedMessage && displayedMessage.id === message.id) { - browser.tabs.sendMessage(activeTab.id, { command: "showSpamReport", data: report_data }); + + if (spamFilter) { + if(prefs_aats.spamfilter_enabled_accounts.length > 0){ + let accountId = message.folder.accountId; + if(!prefs_aats.spamfilter_enabled_accounts.includes(accountId)){ + taLog.log("Account " + accountId + " not enabled for spamfilter, skipping..."); + continue; + } + } + let curr_prompt_spamfilter = await getSpamFilterPrompt(); + // console.log(">>>>>>>>>>>>> curr_prompt_spamfilter: " + JSON.stringify(curr_prompt_spamfilter)); + let chatgpt_lang = await taPromptUtils.getDefaultLang(curr_prompt_spamfilter); + let specialFullPrompt_spamfilter = await taPromptUtils.preparePrompt({ + curr_prompt: curr_prompt_spamfilter, + curr_message: message, + chatgpt_lang: chatgpt_lang, + body_text: body_text, + subject_text: curr_fullMessage.headers.subject, + msg_text: msg_text + }); + taLog.log("Special prompt: " + specialFullPrompt_spamfilter); + // console.log(">>>>>>>> Special prompt for spamfilter: " + specialFullPrompt_spamfilter); + let cmd_spamfilter = new mzta_specialCommand({ + prompt: specialFullPrompt_spamfilter, + llm: getConnectionType(prefs_aats, curr_prompt_spamfilter, 'spamfilter'), + custom_model: curr_prompt_spamfilter.model ? curr_prompt_spamfilter.model : '', + do_debug: prefs_aats.do_debug, + config: curr_prompt_spamfilter + }); + await cmd_spamfilter.initWorker(); + let spamfilter_result = ''; + taLog.log("Sending the prompt..."); + try { + spamfilter_result = (await cmd_spamfilter.sendPrompt()).trim(); + } catch (err) { + console.error("[ThunderAI | SpamFilter] Error getting spamfilter: ", err); + } + taLog.log("spamfilter_result: " + spamfilter_result); + let jsonObj = {}; + taLog.log("Decoding the AI response..."); + try { + jsonObj = extractJsonObject(spamfilter_result); + } catch (e) { + console.error("[ThunderAI | SpamFilter] Error extracting JSON from AI response: ", e); + } + taLog.log("SpamFilter jsonObj: " + JSON.stringify(jsonObj)); + + let report_data = {}; + report_data.report_date = new Date(); + report_data.headerMessageId = message.headerMessageId; + report_data.spamValue = jsonObj.spamValue; + report_data.explanation = jsonObj.explanation; + report_data.subject = curr_fullMessage.headers.subject; + report_data.from = curr_fullMessage.headers.from; + report_data.message_date = new Date(message.date); + report_data.moved = false; + report_data.SpamThreshold = prefs_init.spamfilter_threshold; + + if (jsonObj.spamValue >= prefs_init.spamfilter_threshold) { + taLog.log("Marking as spam [" + message.headerMessageId + "]"); + messenger.messages.update(message.id, { junk: true }); + let spamFolder = await messenger.folders.query({ accountId: message.folder.accountId, specialUse: ['junk'] }); + messenger.messages.move([message.id], spamFolder[0].id); + report_data.moved = true; + taLog.log("Marked as spam [" + message.headerMessageId + "]"); + } + + taSpamReport.saveReportData(report_data, message.headerMessageId); + + // Check if the message is currently displayed and update the banner + if (prefs_init.spamfilter_show_msg_panel) { + let tabs = await browser.tabs.query({ active: true, currentWindow: true }); + if (tabs.length > 0) { + let activeTab = tabs[0]; + let displayedMessage = await browser.messageDisplay.getDisplayedMessage(activeTab.id); + if (displayedMessage && displayedMessage.id === message.id) { + browser.tabs.sendMessage(activeTab.id, { command: "showSpamReport", data: report_data }); + } } } } } } + + if (summarize) { + // we have three prompts, the actual assignment for the LLM, the email + // template prompt, and the email separator prompt + const specialPrompts = await getSpecialPrompts(); + const prompt = specialPrompts.find((prompt) => prompt.id === 'prompt_summarize'); + const prompt_email = specialPrompts.find((prompt) => prompt.id === 'prompt_summarize_email_template'); + const prompt_email_separator = specialPrompts.find((prompt) => prompt.id === 'prompt_summarize_email_separator'); + + const tabs = await browser.tabs.query({ active: true, currentWindow: true }); + const chatgpt_lang = await taPromptUtils.getDefaultLang(prompt); + + // replace placeholders in the prompts the assignment prompt and email + // separator prompt do not have a message as context, so there is only + // limited things to replace + const prompt_string = await taPromptUtils.preparePrompt({ + curr_prompt: prompt, + chatgpt_lang: chatgpt_lang, + }); + const prompt_email_separator_string = await taPromptUtils.preparePrompt({ + curr_prompt: prompt_email_separator, + chatgpt_lang: chatgpt_lang, + }); + + + // assemble all email messages into one string and add the assignment prompt + const messages_list = []; + for await (let curr_message of messages) { + + // extract body of current message as text + const curr_message_full = await browser.messages.getFull(curr_message.id); + const curr_body_full_html = getMailBody(curr_message_full); + let curr_body_full_text = htmlBodyToPlainText(curr_body_full_html.html); + if( curr_body_full_text.length === 0) { + taLog.log("No HTML found in the message body, using plain text..."); + curr_body_full_text = curr_message_full.text; + } + + messages_list.push(await taPromptUtils.preparePrompt({ + curr_prompt: prompt_email, + curr_message: curr_message, + chatgpt_lang: chatgpt_lang, + body_text: curr_body_full_text, + subject_text: curr_message_full.headers.subject, + msg_text: curr_body_full_html, + })); + }; + const messages_string = messages_list.join(prompt_email_separator_string); + + const full_prompt = prompt_string + prompt_email_separator_string + messages_string; + + // console.log(full_prompt); + + // send the prompt to the chat interface + openChatGPT( + full_prompt, + prompt.action, + tabs[0].id, + prompt.name, + prompt.need_custom_text, + prompt + ); + } + taWorkingStatus.stopWorking(); } From fb83ad86fdaddc28c42bc45c5d5d66a81c68f4c2 Mon Sep 17 00:00:00 2001 From: mic Date: Sun, 15 Feb 2026 22:04:37 +0100 Subject: [PATCH 3/3] info comment added --- mzta-background.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mzta-background.js b/mzta-background.js index de4c33b4..14ddacdc 100644 --- a/mzta-background.js +++ b/mzta-background.js @@ -1092,6 +1092,9 @@ async function processEmails(args) { taWorkingStatus.startWorking(); + // We keep two different loops, one for addTagsAuto and spamFilter and one for summarize + // because summarize is never called when an email is received, but only when using the context menu item + if (addTagsAuto || spamFilter) { let prefs_aats = await browser.storage.sync.get({ add_tags_maxnum: prefs_default.add_tags_maxnum,