From b36658153d538930bf28d665b4c216ba739ca2fb Mon Sep 17 00:00:00 2001 From: mic Date: Wed, 18 Feb 2026 22:50:52 +0100 Subject: [PATCH 01/38] en locale string fixed --- _locales/en/messages.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index bdaec663..a7851fe1 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -1048,7 +1048,7 @@ "description": "" }, "Summarize_prompt_prefs_title": { - "message": "Add Summarization Options", + "message": "Summarization Options", "description": "" }, "prompt_summarize": { From 526be7134844b1a44c6f5d764d87fa05842adbb8 Mon Sep 17 00:00:00 2001 From: mic Date: Wed, 18 Feb 2026 22:57:03 +0100 Subject: [PATCH 02/38] en locales improved --- _locales/en/messages.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index a7851fe1..94bc215e 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -1288,7 +1288,7 @@ "description": "" }, "prefs_OptionText_summarize": { - "message": "Summarize mail", + "message": "Summarize email", "description": "" }, "prefs_OptionText_summarize_use_specific_integration_Info": { @@ -1296,7 +1296,7 @@ "description": "" }, "prefs_OptionText_summarize_Info": { - "message": "If checked, adds an option to context menu to summarize mail.", + "message": "If checked, adds an option to context menu to summarize email.", "description": "" }, "prefs_OptionText_btnManageSummarizeInfo": { From 228e2b410276dbedbbaf49dbb02ff7bb7d019d37 Mon Sep 17 00:00:00 2001 From: mic Date: Wed, 18 Feb 2026 22:58:04 +0100 Subject: [PATCH 03/38] en locales improved --- _locales/en/messages.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 94bc215e..addc715b 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -1296,7 +1296,7 @@ "description": "" }, "prefs_OptionText_summarize_Info": { - "message": "If checked, adds an option to context menu to summarize email.", + "message": "If checked, adds an option to context menu to summarize email(s).", "description": "" }, "prefs_OptionText_btnManageSummarizeInfo": { From 04b69a73c44fa49e6081d66dfd777bcd7c379054 Mon Sep 17 00:00:00 2001 From: Mic Date: Wed, 18 Feb 2026 22:49:10 +0100 Subject: [PATCH 04/38] Translated using Weblate (Italian) Currently translated at 92.7% (437 of 471 strings) Translation: ThunderAI for Thunderbird/main Translate-URL: https://hosted.weblate.org/projects/thunderai/main/it/ --- _locales/it/messages.json | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/_locales/it/messages.json b/_locales/it/messages.json index 25ed2bf6..e8248075 100644 --- a/_locales/it/messages.json +++ b/_locales/it/messages.json @@ -1302,5 +1302,38 @@ }, "prefs_anthropic_temperature_Info": { "message": "Quantità di casualità iniettata nella risposta. Il valore predefinito è 1,0. L'intervallo va da 0,0 a 1,0. Utilizza una temperatura più vicina a 0,0 per compiti analitici o a scelta multipla, e più vicina a 1,0 per compiti creativi e generativi. Nota che, anche con una temperatura di 0,0, i risultati non saranno completamente deterministici." + }, + "placeholder_mail_text_body_or_selected": { + "message": "Corpo dell'email o testo selezionato" + }, + "placeholder_mail_html_body_or_selected": { + "message": "Corpo dell'email o HTML selezionato" + }, + "prefs_OptionText_chatgpt_web_load_wait_time": { + "message": "Tempo di attesa caricamento pagina" + }, + "prefs_OptionText_chatgpt_web_load_wait_time_info": { + "message": "Tempo di attesa in millisecondi per il caricamento della pagina di ChatGPT prima di caricare i contenuti aggiuntivi. Il valore predefinito è 1000ms. Se viene definito un Custom GPT o un Progetto, verranno aggiunti ulteriori 1000ms a questo valore." + }, + "prompt_get_calendar_event_from_clipboard": { + "message": "Aggiungi un evento a calendario dagli appunti" + }, + "clipboard_read_error": { + "message": "Impossibile leggere il contenuto copiato negli appunti. Verifica i permessi." + }, + "clipboard_empty_error": { + "message": "Gli appunti sono vuoti. Copia prima del testo." + }, + "clipboard_permission_denied": { + "message": "Accesso agli appunti negato. Riattiva la funzione nelle impostazioni per concedere il permesso." + }, + "clipboard_permission_error": { + "message": "Errore durante la richiesta dei permessi per gli appunti. Riprova." + }, + "prefs_OptionText_get_calendar_event_from_clipboard": { + "message": "Ottieni un evento del calendario dagli appunti" + }, + "prefs_OptionText_get_calendar_event_from_clipboard_Info": { + "message": "Mostra una voce di menu aggiuntiva per creare eventi di calendario dal contenuto di testo negli appunti." } } From 79bbcda6caed2195910486164b1b121504143971 Mon Sep 17 00:00:00 2001 From: Mic Date: Wed, 18 Feb 2026 22:56:14 +0100 Subject: [PATCH 05/38] Translated using Weblate (Italian) Currently translated at 95.5% (450 of 471 strings) Translation: ThunderAI for Thunderbird/main Translate-URL: https://hosted.weblate.org/projects/thunderai/main/it/ --- _locales/it/messages.json | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/_locales/it/messages.json b/_locales/it/messages.json index e8248075..fbd42e06 100644 --- a/_locales/it/messages.json +++ b/_locales/it/messages.json @@ -1335,5 +1335,44 @@ }, "prefs_OptionText_get_calendar_event_from_clipboard_Info": { "message": "Mostra una voce di menu aggiuntiva per creare eventi di calendario dal contenuto di testo negli appunti." + }, + "Summarize_prompt_prefs_title": { + "message": "Impostazioni riassunto" + }, + "prompt_summarize": { + "message": "Riassumi email" + }, + "prompt_summarize_full_text": { + "message": "Sei un assistente che riassume conversazioni via email.\n\nDato un thread di email, produci un riassunto conciso e accurato che includa:\n\n- L'argomento principale o lo scopo della conversazione\n- Decisioni chiave, conclusioni o accordi\n- Domande importanti, richieste o punti d'azione\n- Il responsabile per ogni punto d'azione (se indicato)\n\nOmetti saluti, firme, testo citato e scambi ridondanti.\nNon aggiungere supposizioni o informazioni non presenti nelle email.\n\nScrivi il riassunto con un linguaggio chiaro e neutro, adatto a un professionista impegnato." + }, + "prompt_summarize_email_template": { + "message": "Template riassunto email" + }, + "prompt_summarize_email_template_full_text": { + "message": "Da: {%author%}\nA: {%recipients%}\nCC: {%cc_list%}\nOggetto: {%mail_subject%}\nData: {%mail_datetime%}\nAllegati:\n{%mail_attachments_info%}\n\nCorpo del messaggio:\n{%mail_text_body%}" + }, + "prompt_summarize_email_separator": { + "message": "Separatore email" + }, + "prompt_summarize_email_separator_full_text": { + "message": "\n\n---------- PROSSIMA EMAIL ----------\n\n" + }, + "prefs_OptionText_Summarize_infoline2": { + "message": "Puoi modificare il prompt come desideri: il primo campo è il prompt principale, il secondo è il modello per la singola email. L'elenco delle email sarà aggiunto al prompt principale. Le email saranno divise dal separatore specificato nel terzo campo." + }, + "prefs_OptionText_Summarize_main_prompt": { + "message": "Il prompt principale che descrive l'attività da eseguire su tutte le email selezionate:" + }, + "prefs_OptionText_Summarize_email_template": { + "message": "Il modello per la singola email:" + }, + "prefs_OptionText_Summarize_email_separator": { + "message": "Il separatore tra le email:" + }, + "prefs_OptionText_get_calendar_event_use_specific_integration_Info": { + "message": "Se selezionato, il Modello e l'API specificati di seguito verranno utilizzati per creare gli eventi di calendario, indipendentemente da quelli scelti nella pagina delle opzioni di ThunderAI." + }, + "prefs_OptionText_summarize": { + "message": "Riassumi email" } } From a0713210551fbe42d19d65beac81b79a0c46983e Mon Sep 17 00:00:00 2001 From: Mic Date: Wed, 18 Feb 2026 22:58:17 +0100 Subject: [PATCH 06/38] Translated using Weblate (Italian) Currently translated at 95.7% (451 of 471 strings) Translation: ThunderAI for Thunderbird/main Translate-URL: https://hosted.weblate.org/projects/thunderai/main/it/ --- _locales/it/messages.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/_locales/it/messages.json b/_locales/it/messages.json index fbd42e06..950c46ed 100644 --- a/_locales/it/messages.json +++ b/_locales/it/messages.json @@ -1374,5 +1374,11 @@ }, "prefs_OptionText_summarize": { "message": "Riassumi email" + }, + "prefs_OptionText_summarize_use_specific_integration_Info": { + "message": "Se selezionato, il Modello e l'API specificati di seguito verranno utilizzati per riassumere le email, indipendentemente da quelli scelti nella pagina delle opzioni di ThunderAI." + }, + "prefs_OptionText_summarize_Info": { + "message": "Se selezionato, aggiunge un'opzione al menu contestuale per riassumere le email." } } From f7e7367f60d2df00996cde78f9b9a87601b50106 Mon Sep 17 00:00:00 2001 From: Mic Date: Wed, 18 Feb 2026 23:06:38 +0100 Subject: [PATCH 07/38] Translated using Weblate (Italian) Currently translated at 100.0% (471 of 471 strings) Translation: ThunderAI for Thunderbird/main Translate-URL: https://hosted.weblate.org/projects/thunderai/main/it/ --- _locales/it/messages.json | 61 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 2 deletions(-) diff --git a/_locales/it/messages.json b/_locales/it/messages.json index 950c46ed..00cdb419 100644 --- a/_locales/it/messages.json +++ b/_locales/it/messages.json @@ -31,7 +31,7 @@ "message": "Traduci" }, "prompt_this": { - "message": "Chedi a ChatGPT" + "message": "Invia il testo come prompt" }, "prompt_selection_needed": { "message": "Per procedere è necessario che selezioni del testo!" @@ -172,7 +172,7 @@ "message": "Riprova" }, "chatgpt_sendbutton_not_found_error": { - "message": "Premi il pulsante per inviare il prompt a ChatGPT." + "message": "Premi il pulsante per inviare il prompt." }, "chatgpt_user_not_logged_in": { "message": "Non sei connesso a ChatGPT. Effettua l'accesso con le tue credenziali, chiudi la finestra di ChatGPT e poi ripeti l'azione che avevi tentato. Rimarrai connesso in seguito." @@ -1380,5 +1380,62 @@ }, "prefs_OptionText_summarize_Info": { "message": "Se selezionato, aggiunge un'opzione al menu contestuale per riassumere le email." + }, + "prefs_OptionText_btnManageSummarizeInfo": { + "message": "Gestisci le impostazioni di riassunto" + }, + "Summarize_PageTitle": { + "message": "Gestisci Impostazioni di Riassunto" + }, + "Summarize_info_default": { + "message": "In questa pagina puoi modificare il prompt predefinito utilizzato per riassumere le email." + }, + "Summarize_prompt_text_title": { + "message": "Testo del prompt attuale" + }, + "prefs_OptionText_spamfilter_show_msg_panel": { + "message": "Mostra pannello segnalazione spam" + }, + "prefs_OptionText_spamfilter_show_msg_panel_Info": { + "message": "Se selezionato, verrà mostrato un pannello con il report spam sopra il messaggio." + }, + "SpamReport_infoline": { + "message": "Queste informazioni sono salvate solo per la sessione corrente." + }, + "Spam": { + "message": "Spam" + }, + "Valid": { + "message": "Valido" + }, + "context_menu_mzta-summarize": { + "message": "Riassumi" + }, + "CORS_alternative_2_new": { + "message": "Premi il pulsante qui sotto per concedere le autorizzazioni all'host corrente ed evitare problemi di CORS." + }, + "CORS_give_host_perm": { + "message": "Concedi l'autorizzazione all'host corrente" + }, + "CORS_localhost_warn": { + "message": "Se stai utilizzando localhost o 127.0.0.1 perché il server IA è ospitato sul tuo PC, è necessaria l'autorizzazione ." + }, + "customPrompts_export_include_api_settings": { + "message": "Vuoi includere le impostazioni API nell'esportazione? Attenzione: anche la Chiave API verrà salvata nel file!" + }, + "prefs_OptionText_calendar_no_selection": { + "message": "Non chiedere di selezionare del testo" + }, + "prefs_OptionText_calendar_no_selection_Info": { + "message": "Se questa opzione viene attivata, non sarà necessario selezionare del testo. Verrà utilizzato l'intero corpo del messaggio per creare l'evento di calendario." + }, + "customPrompts_btnCopy": { + "message": "Copia" + }, + "copy_text": { + "message": "copia" + }, + "spam_check_in_progress": { + "message": "Controllo spam in corso..." } } From 3d3581dc26717b014f20d9221c3f894b7258603e Mon Sep 17 00:00:00 2001 From: mic Date: Wed, 18 Feb 2026 23:08:44 +0100 Subject: [PATCH 08/38] version set to 4.0.0pre2 --- manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest.json b/manifest.json index 9260970b..57e7a708 100644 --- a/manifest.json +++ b/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 2, "name": "ThunderAI", "description": "__MSG_extensionDescription__", - "version": "4.0.0pre1", + "version": "4.0.0pre2", "author": "Mic (m@micz.it)", "homepage_url": "https://micz.it/thunderbird-addon-thunderai/", "browser_specific_settings": { From 9384c0574e10d11871ad22ab21f3655f6fb8e633 Mon Sep 17 00:00:00 2001 From: bittin1ddc447d824349b2 Date: Thu, 19 Feb 2026 09:58:34 +0100 Subject: [PATCH 09/38] Translated using Weblate (Swedish) Currently translated at 100.0% (471 of 471 strings) Translation: ThunderAI for Thunderbird/main Translate-URL: https://hosted.weblate.org/projects/thunderai/main/sv/ --- _locales/sv/messages.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/_locales/sv/messages.json b/_locales/sv/messages.json index f4066bc8..847ef536 100644 --- a/_locales/sv/messages.json +++ b/_locales/sv/messages.json @@ -1288,7 +1288,7 @@ "message": "Analysera följande e-postmeddelande och avgör om det är skräppost eller inte. Tänk på faktorer som misstänkta sökord, överdrivet reklamspråk, vilseledande ämnesrader, förfrågningar om personlig information och ovanliga avsändaradresser.\nAnge ett värde från 0 (inte skräppost) till 100 (skräppost) och en förklaring på högst 10 ord.\nOm meddelandedata saknas, sätt värdet till 0 (inte skräppost) och ange orsaken.\nGenerera ett svar endast i JSON-format. Inkludera inte ytterligare text eller förklaring; ange endast JSON. Här är formatet som ska användas:\n{\n\"spamValue\": ,\n\"explanation\": \"Kort förklaring av ditt resonemang\"\n}\nHär är e-postinformationen:\nAvsändare: \"{%author%}\"\nÄmne: \"{%mail_subject%}\"\nHtml-text: \"{%mail_html_body%}\"" }, "Summarize_prompt_prefs_title": { - "message": "Lägg till sammanfattningsalternativ" + "message": "Sammanfattningsalternativ" }, "prompt_summarize": { "message": "Sammanfatta det här e-postmeddelandet eller dessa e-postmeddelanden" @@ -1321,13 +1321,13 @@ "message": "Avgränsaren mellan e-postmeddelanden:" }, "prefs_OptionText_summarize": { - "message": "Sammanfatta e-postmeddelande" + "message": "Sammanfatta epostmeddelande" }, "prefs_OptionText_summarize_use_specific_integration_Info": { "message": "Om markerat kommer modellen och API:et som anges nedan att användas för att sammanfatta e-postmeddelanden, oavsett vilket som valts på ThunderAI-alternativsidan." }, "prefs_OptionText_summarize_Info": { - "message": "Om markerad läggs ett alternativ till i snabbmenyn för att sammanfatta e-post." + "message": "Om markerad läggs ett alternativ till i snabbmenyn för att sammanfatta epost(meddelanden)." }, "prefs_OptionText_btnManageSummarizeInfo": { "message": "Hantera sammanfattningsinställningar" From aa1cc73a1a8bab2c6d89a43affba6a310c56c1c1 Mon Sep 17 00:00:00 2001 From: mic Date: Thu, 19 Feb 2026 22:21:48 +0100 Subject: [PATCH 10/38] added tom-select version check --- .../workflows/tom-select-release-check.yml | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 .github/workflows/tom-select-release-check.yml diff --git a/.github/workflows/tom-select-release-check.yml b/.github/workflows/tom-select-release-check.yml new file mode 100644 index 00000000..c9fe6711 --- /dev/null +++ b/.github/workflows/tom-select-release-check.yml @@ -0,0 +1,54 @@ +name: Check External Release + +on: + schedule: + - cron: '0 0 * * *' # Check every day at midnight + workflow_dispatch: # Allows manual triggering for testing purposes + +permissions: + contents: read + issues: write + +jobs: + check-and-notify: + runs-on: ubuntu-latest + steps: + - name: Get latest release from external repo + id: get_release + run: | + REPO_TARGET="orchidjs/tom-select" + LATEST_TAG=$(curl -s https://api.github.com/repos/$REPO_TARGET/releases/latest | jq -r .tag_name) + + if [ "$LATEST_TAG" == "null" ] || [ -z "$LATEST_TAG" ]; then + echo "Error: unable to fetch tag or no release found." + exit 1 + fi + + echo "tag=$LATEST_TAG" >> $GITHUB_OUTPUT + echo "target=$REPO_TARGET" >> $GITHUB_OUTPUT + + - name: Check if Issue already exists and create it + uses: actions/github-script@v7 + with: + script: | + const latestTag = "${{ steps.get_release.outputs.tag }}"; + const targetRepo = "${{ steps.get_release.outputs.target }}"; + const { owner, repo } = context.repo; + const issueTitle = `Update Tom Select to version ${latestTag}`; + + // Search through issues (both open and closed for safety) + const response = await github.rest.search.issuesAndPullRequests({ + q: `repo:${owner}/${repo} is:issue "${issueTitle}"`, + }); + + if (response.data.total_count > 0) { + core.info(`The issue for version ${latestTag} already exists. No action taken.`); + } else { + await github.rest.issues.create({ + owner, + repo, + title: issueTitle, + body: `Update Tom Select to version **${latestTag}**. https://github.com/orchidjs/tom-select/releases` + }); + core.info(`New issue created for version ${latestTag}.`); + } From ec0a955feb97cf462f0299b0b09f9f7e55f34c0e Mon Sep 17 00:00:00 2001 From: Mic Date: Thu, 19 Feb 2026 22:23:21 +0100 Subject: [PATCH 11/38] Rename workflow to Check Tom-Select Latest Release --- .github/workflows/tom-select-release-check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tom-select-release-check.yml b/.github/workflows/tom-select-release-check.yml index c9fe6711..f556c964 100644 --- a/.github/workflows/tom-select-release-check.yml +++ b/.github/workflows/tom-select-release-check.yml @@ -1,4 +1,4 @@ -name: Check External Release +name: Check Tom-Select Latest Release on: schedule: From fc47603f1f4e2156686e15800785ae98149f2d1c Mon Sep 17 00:00:00 2001 From: mic Date: Thu, 19 Feb 2026 22:28:04 +0100 Subject: [PATCH 12/38] tomselect updated to 2.5.1 see #665 --- VENDORS.md | 2 +- pages/_lib/tom-select.base.js | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/VENDORS.md b/VENDORS.md index f0c79411..cd5cd651 100644 --- a/VENDORS.md +++ b/VENDORS.md @@ -2,7 +2,7 @@ file: pages\_lib\list.js source: https://raw.githubusercontent.com/javve/list.js/v2.3.1/dist/list.js file: pages\_lib\tom-select.base.js -source: https://cdn.jsdelivr.net/npm/tom-select@2.4.6/dist/js/tom-select.base.js +source: https://cdn.jsdelivr.net/npm/tom-select@2.5.1/dist/js/tom-select.base.js file: js\lib\diff.js source: https://cdnjs.cloudflare.com/ajax/libs/jsdiff/7.0.0/diff.js \ No newline at end of file diff --git a/pages/_lib/tom-select.base.js b/pages/_lib/tom-select.base.js index a79fe394..8e42b70b 100644 --- a/pages/_lib/tom-select.base.js +++ b/pages/_lib/tom-select.base.js @@ -1,5 +1,5 @@ /** -* Tom Select v2.4.6 +* Tom Select v2.5.1 * Licensed under the Apache License, Version 2.0 (the "License"); */ @@ -1502,6 +1502,7 @@ create: null, createOnBlur: false, createFilter: null, + clearAfterSelect: false, highlight: true, openOnFocus: true, shouldOpen: null, @@ -2444,6 +2445,8 @@ self.createItem(null, () => { if (self.settings.closeAfterSelect) { self.close(); + } else if (self.settings.clearAfterSelect) { + self.setTextboxValue(); } }); } else { @@ -2453,6 +2456,8 @@ self.addItem(value); if (self.settings.closeAfterSelect) { self.close(); + } else if (self.settings.clearAfterSelect) { + self.setTextboxValue(); } if (!self.settings.hideSelected && evt.type && /click/.test(evt.type)) { self.setActiveOption(option); @@ -2884,6 +2889,11 @@ // perform search if (query !== self.lastQuery) { self.lastQuery = query; + // temp fix for https://github.com/orchidjs/tom-select/issues/987 + // UI crashed when more than 30 same chars in a row, prevent search and return empt result + if (/(.)\1{15,}/.test(query)) { + query = ''; + } result = self.sifter.search(query, Object.assign(options, { score: calculateScore })); @@ -3446,6 +3456,11 @@ } else if (!self.isPending) { self.positionDropdown(); } + + //remove input value when enabled + if (self.settings.clearAfterSelect) { + self.setTextboxValue(); + } self.trigger('item_add', hashed, item); if (!self.isPending) { self.updateOriginalInput({ From b2abad4b958bcfa49c88767b09bfd35cdfa20433 Mon Sep 17 00:00:00 2001 From: Mic Date: Thu, 19 Feb 2026 22:29:52 +0100 Subject: [PATCH 13/38] Enhance issue body with CDN links for Tom Select Updated the issue body to include CDN links for the latest Tom Select version. --- .github/workflows/tom-select-release-check.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tom-select-release-check.yml b/.github/workflows/tom-select-release-check.yml index f556c964..6e7c597a 100644 --- a/.github/workflows/tom-select-release-check.yml +++ b/.github/workflows/tom-select-release-check.yml @@ -48,7 +48,11 @@ jobs: owner, repo, title: issueTitle, - body: `Update Tom Select to version **${latestTag}**. https://github.com/orchidjs/tom-select/releases` + body: `Update Tom Select to version **${latestTag}**. + + https://cdn.jsdelivr.net/npm/tom-select@${latestTag}/dist/js/tom-select.base.js + + https://cdn.jsdelivr.net/npm/tom-select@${latestTag}/dist/css/tom-select.default.min.css` }); core.info(`New issue created for version ${latestTag}.`); } From bcc7a5f62b03e219d095c426f7c98fc76a8f7cfc Mon Sep 17 00:00:00 2001 From: Mic Date: Thu, 19 Feb 2026 22:30:59 +0100 Subject: [PATCH 14/38] Add reminder for VENDORS.md update in release check Added a reminder to update the VENDORS.md file when updating Tom Select. --- .github/workflows/tom-select-release-check.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tom-select-release-check.yml b/.github/workflows/tom-select-release-check.yml index 6e7c597a..a0f1002e 100644 --- a/.github/workflows/tom-select-release-check.yml +++ b/.github/workflows/tom-select-release-check.yml @@ -52,7 +52,9 @@ jobs: https://cdn.jsdelivr.net/npm/tom-select@${latestTag}/dist/js/tom-select.base.js - https://cdn.jsdelivr.net/npm/tom-select@${latestTag}/dist/css/tom-select.default.min.css` + https://cdn.jsdelivr.net/npm/tom-select@${latestTag}/dist/css/tom-select.default.min.css + + Remeber also to update the VENDORS.md file.` }); core.info(`New issue created for version ${latestTag}.`); } From f0c9777ace3c7077b1dce0da582e46268d8c2ff6 Mon Sep 17 00:00:00 2001 From: mic Date: Thu, 19 Feb 2026 22:54:52 +0100 Subject: [PATCH 15/38] thunderstats link added. see #663 --- _locales/en/messages.json | 8 ++++++++ images/thunderstats.png | Bin 0 -> 616 bytes options/mzta-options.css | 23 ++++++++++++++++++++++- options/mzta-options.html | 5 +++++ 4 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 images/thunderstats.png diff --git a/_locales/en/messages.json b/_locales/en/messages.json index addc715b..817bfe66 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -1892,5 +1892,13 @@ "spam_check_in_progress": { "message": "Spam check in progress...", "description": "" + }, + "prefs_THStats_1": { + "message": "Do you want beautiful statistics about your emails?", + "description": "" + }, + "prefs_THStats_2": { + "message": "Click here! Try ThunderStats!", + "description": "" } } diff --git a/images/thunderstats.png b/images/thunderstats.png new file mode 100644 index 0000000000000000000000000000000000000000..c172e8a6996793a35462656b9f78a26c7ab2c897 GIT binary patch literal 616 zcmV-u0+;=XP) zlQ-lcF!vrf%kEoU(0qmy6Ku;IAFp*#7? zw^)y<3mx!W%)!;BB3YCXT`ORlEl5xjW%!DIOa+0%*Ktf2C_TWdP2<}<+OPummKAu~ zRWvshAS4apw1VKW1;M0(K-h*K5i5M9Ssb~I*_j3Gsr^VTl2e)J8gmW}9v5QQRu$Ww z8EkIM<9o`2K-7)}hUbF~`1m5HIi4&%|D41)bCI=gVZUM*qg}gAgFU@kcY9mOlFG{X z@=eYy&f`PKmw#DO%ahzUy`IM;t$9r4e|?SX`hEe#;??@|u96u50000
__MSG_prefs_SurveyLinkText__
__MSG_prefs_SurveyLinkText2__
+ + +
__MSG_prefs_THStats_1__ __MSG_prefs_THStats_2__
+ +
__MSG_prefs_OptionText_owl_warning__ __MSG_more_info_string__
From a59d346d42ba76759635efc40516e1965891dd57 Mon Sep 17 00:00:00 2001 From: Mic Date: Thu, 19 Feb 2026 23:35:32 +0100 Subject: [PATCH 16/38] Translated using Weblate (French) Currently translated at 100.0% (471 of 471 strings) Translation: ThunderAI for Thunderbird/main Translate-URL: https://hosted.weblate.org/projects/thunderai/main/fr/ --- _locales/fr/messages.json | 135 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) diff --git a/_locales/fr/messages.json b/_locales/fr/messages.json index 6a3ef008..8c9d66f8 100644 --- a/_locales/fr/messages.json +++ b/_locales/fr/messages.json @@ -1302,5 +1302,140 @@ }, "reset": { "message": "Réinitialiser" + }, + "placeholder_mail_text_body_or_selected": { + "message": "Corps de l'e-mail ou texte sélectionné" + }, + "placeholder_mail_html_body_or_selected": { + "message": "Corps de l'e-mail ou HTML sélectionné" + }, + "prefs_OptionText_chatgpt_web_load_wait_time": { + "message": "Délai d'attente pour le chargement de la page" + }, + "prefs_OptionText_chatgpt_web_load_wait_time_info": { + "message": "Temps en millisecondes à attendre pour le chargement de la page ChatGPT avant de charger le contenu supplémentaire. La valeur par défaut est 1000ms. Si un GPT personnalisé ou un Projet est défini, 1000ms supplémentaires seront ajoutés à cette valeur." + }, + "prompt_get_calendar_event_from_clipboard": { + "message": "Ajouter un événement de calendrier depuis le presse-papiers" + }, + "clipboard_read_error": { + "message": "Impossible de lire le presse-papiers. Veuillez vérifier les autorisations." + }, + "clipboard_empty_error": { + "message": "Le presse-papiers est vide. Veuillez d'abord copier du texte." + }, + "clipboard_permission_denied": { + "message": "L'autorisation d'accès au presse-papiers a été refusée. Veuillez réactiver la fonctionnalité dans les paramètres per accorder l'autorisation." + }, + "clipboard_permission_error": { + "message": "Erreur lors de la demande d'autorisation du presse-papiers. Veuillez réessayer." + }, + "prefs_OptionText_get_calendar_event_from_clipboard": { + "message": "Obtenir l'événement de calendrier depuis le presse-papiers" + }, + "prefs_OptionText_get_calendar_event_from_clipboard_Info": { + "message": "Afficher un élément de menu supplémentaire pour créer des événements de calendrier à partir du contenu textuel du presse-papiers." + }, + "Summarize_prompt_prefs_title": { + "message": "Options de résumé" + }, + "prompt_summarize": { + "message": "Résumer cet e-mail ou ces e-mails" + }, + "prompt_summarize_full_text": { + "message": "Vous êtes un assistant qui résume les conversations par e-mail.\n\nÀ partir d'un fil de discussion, produisez un résumé concis et précis qui capture :\n\n- Le sujet principal ou l'objet de la conversation.\n- Les décisions clés, conclusions ou accords.\n- Les questions importantes, requêtes ou points à traiter.\n- Le responsable de chaque action à entreprendre (si précisé).\n\nOmettez les salutations, les signatures, le texte cité et les échanges redondants.\nN'ajoutez pas d'hypothèses ou d'informations non présentes dans les e-mails.\n\nRédigez le résumé dans un langage clair et neutre, adapté à un professionnel occupé." + }, + "prompt_summarize_email_template": { + "message": "Résumé du modèle d'e-mail" + }, + "prompt_summarize_email_template_full_text": { + "message": "De : {%author%}\nÀ : {%recipients%}\nCopie : {%cc_list%}\nObjet : {%mail_subject%}\nDate : {%mail_datetime%}\nPièces jointes :\n{%mail_attachments_info%}\n\nCorps du message :\n{%mail_text_body%}" + }, + "prompt_summarize_email_separator": { + "message": "Séparateur d'e-mail" + }, + "prompt_summarize_email_separator_full_text": { + "message": "\n\n---------- E-MAIL SUIVANTE ----------\n\n" + }, + "prefs_OptionText_Summarize_infoline2": { + "message": "Vous pouvez modifier l’instruction (prompt) comme vous le souhaitez : le premier champ est l’instruction principale, le deuxième est le modèle pour un e-mail individuel. La liste des e-mails sera ajoutée à la suite de l’instruction principale. Les e-mails seront séparés par le séparateur spécifié dans le troisième champ." + }, + "prefs_OptionText_Summarize_main_prompt": { + "message": "L'instruction principale décrivant la tâche à effectuer sur tous les e-mails sélectionnés :" + }, + "prefs_OptionText_Summarize_email_template": { + "message": "Le modèle pour un e-mail unique :" + }, + "prefs_OptionText_Summarize_email_separator": { + "message": "Le séparateur entre les e-mails :" + }, + "prefs_OptionText_get_calendar_event_use_specific_integration_Info": { + "message": "Si coché, le Modèle et l'API spécifiés ci-dessous seront utilisés pour créer des événements de calendrier, quel que soit celui choisi dans la page des options de ThunderAI." + }, + "prefs_OptionText_summarize": { + "message": "Résumer l'e-mail" + }, + "prefs_OptionText_summarize_use_specific_integration_Info": { + "message": "Si coché, le Modèle et l'API spécifiés ci-dessous seront utilisés pour résumer les e-mails, quel que soit celui choisi dans la page des options de ThunderAI." + }, + "prefs_OptionText_summarize_Info": { + "message": "Si coché, ajoute une option au menu contextuel pour résumer l'e-mail." + }, + "prefs_OptionText_btnManageSummarizeInfo": { + "message": "Gérer les paramètres de résumé" + }, + "Summarize_PageTitle": { + "message": "Gestion des paramètres de résumé" + }, + "Summarize_info_default": { + "message": "Sur cette page, vous pouvez modifier le prompt par défaut utilisé pour résumer les e-mails." + }, + "Summarize_prompt_text_title": { + "message": "Texte actuel du prompt" + }, + "prefs_OptionText_spamfilter_show_msg_panel": { + "message": "Afficher le panneau de rapport de spam" + }, + "prefs_OptionText_spamfilter_show_msg_panel_Info": { + "message": "Si coché, un panneau avec le rapport de spam s'affichera au-dessus du message." + }, + "SpamReport_infoline": { + "message": "Ces informations ne sont enregistrées que pour la session en cours." + }, + "Spam": { + "message": "Indésirables" + }, + "Valid": { + "message": "Valide" + }, + "context_menu_mzta-summarize": { + "message": "Résumer" + }, + "CORS_alternative_2_new": { + "message": "Appuyez sur le bouton ci-dessous pour donner l'autorisation à l'hôte actuel afin d'éviter tout problème CORS." + }, + "CORS_give_host_perm": { + "message": "Donner l'autorisation à l'hôte actuel" + }, + "CORS_localhost_warn": { + "message": "Si vous utilisez localhost ou 127.0.0.1 parce que le serveur d'IA est hébergé sur votre PC, l'autorisation est requise." + }, + "customPrompts_export_include_api_settings": { + "message": "Voulez-vous inclure les paramètres API dans l'exportation ? Attention, la clé API sera également enregistrée dans le fichier !" + }, + "prefs_OptionText_calendar_no_selection": { + "message": "Ne pas demander de sélectionner du texte" + }, + "prefs_OptionText_calendar_no_selection_Info": { + "message": "Si coché, il n'est pas nécessaire de sélectionner du texte. Le corps complet du message sera utilisé pour créer l'événement de calendrier." + }, + "spam_check_in_progress": { + "message": "Analyse antispam en cours..." + }, + "customPrompts_btnCopy": { + "message": "Copier" + }, + "copy_text": { + "message": "copie" } } From 8380970da376bc08c2fc031a965fe3c5233f9a9e Mon Sep 17 00:00:00 2001 From: Mic Date: Thu, 19 Feb 2026 23:39:56 +0100 Subject: [PATCH 17/38] Translated using Weblate (French) Currently translated at 100.0% (473 of 473 strings) Translation: ThunderAI for Thunderbird/main Translate-URL: https://hosted.weblate.org/projects/thunderai/main/fr/ --- _locales/fr/messages.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/_locales/fr/messages.json b/_locales/fr/messages.json index 8c9d66f8..b823a370 100644 --- a/_locales/fr/messages.json +++ b/_locales/fr/messages.json @@ -1437,5 +1437,11 @@ }, "copy_text": { "message": "copie" + }, + "prefs_THStats_1": { + "message": "Voulez-vous de belles statistiques sur vos e-mails ?" + }, + "prefs_THStats_2": { + "message": "Cliquez ici ! Essayez ThunderStats !" } } From 3c45d136fdd9a15d4d568c8d00f1e504a808d704 Mon Sep 17 00:00:00 2001 From: Mic Date: Thu, 19 Feb 2026 23:39:32 +0100 Subject: [PATCH 18/38] Translated using Weblate (Italian) Currently translated at 100.0% (473 of 473 strings) Translation: ThunderAI for Thunderbird/main Translate-URL: https://hosted.weblate.org/projects/thunderai/main/it/ --- _locales/it/messages.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/_locales/it/messages.json b/_locales/it/messages.json index 00cdb419..5054722a 100644 --- a/_locales/it/messages.json +++ b/_locales/it/messages.json @@ -1437,5 +1437,11 @@ }, "spam_check_in_progress": { "message": "Controllo spam in corso..." + }, + "prefs_THStats_1": { + "message": "Desideri delle belle statistiche sulle tue email?" + }, + "prefs_THStats_2": { + "message": "Clicca qui! Prova ThunderStats!" } } From 2e89ddef65f93d0b756902233bfcf764d2eba688 Mon Sep 17 00:00:00 2001 From: mic Date: Thu, 19 Feb 2026 23:49:44 +0100 Subject: [PATCH 19/38] disablig btnNew when copying. see #598 --- pages/customprompts/mzta-custom-prompts.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pages/customprompts/mzta-custom-prompts.js b/pages/customprompts/mzta-custom-prompts.js index 8e45ac8c..cd9e776e 100644 --- a/pages/customprompts/mzta-custom-prompts.js +++ b/pages/customprompts/mzta-custom-prompts.js @@ -1020,7 +1020,8 @@ function handleCopyClick(e) { // Show form document.getElementById('formNew').style.display = 'block'; - + document.getElementById('btnNew').disabled = true; + // Scroll to top window.scrollTo({ top: 0, From 48b5dc0f752884212196c8186ac319361ece68df Mon Sep 17 00:00:00 2001 From: Andreas Pettersson Date: Fri, 20 Feb 2026 16:21:14 +0100 Subject: [PATCH 20/38] Translated using Weblate (Swedish) Currently translated at 100.0% (473 of 473 strings) Translation: ThunderAI for Thunderbird/main Translate-URL: https://hosted.weblate.org/projects/thunderai/main/sv/ --- _locales/sv/messages.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/_locales/sv/messages.json b/_locales/sv/messages.json index 847ef536..325dbc42 100644 --- a/_locales/sv/messages.json +++ b/_locales/sv/messages.json @@ -1421,5 +1421,11 @@ }, "spam_check_in_progress": { "message": "Skräppostkontroll pågår..." + }, + "prefs_THStats_1": { + "message": "Vill du ha snygg statistik om dina e-postmeddelanden?" + }, + "prefs_THStats_2": { + "message": "Klicka här! Testa ThunderStats!" } } From 6aca668d11862a2a168114dfa042cb383521693c Mon Sep 17 00:00:00 2001 From: Mic Date: Sat, 21 Feb 2026 10:30:18 +0100 Subject: [PATCH 21/38] Translated using Weblate (German) Currently translated at 100.0% (473 of 473 strings) Translation: ThunderAI for Thunderbird/main Translate-URL: https://hosted.weblate.org/projects/thunderai/main/de/ --- _locales/de/messages.json | 141 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) diff --git a/_locales/de/messages.json b/_locales/de/messages.json index 7515b3a0..09aba133 100644 --- a/_locales/de/messages.json +++ b/_locales/de/messages.json @@ -1302,5 +1302,146 @@ }, "prefs_anthropic_temperature_Info": { "message": "Grad der Zufälligkeit in der Antwort. Der Standardwert ist 1,0. Der Bereich liegt zwischen 0,0 und 1,0. Verwenden Sie eine Temperatur näher an 0,0 für analytische Aufgaben oder Multiple-Choice-Fragen und näher an 1,0 für kreative und generative Aufgaben. Beachten Sie, dass die Ergebnisse selbst bei einer Temperatur von 0,0 nicht vollständig deterministisch sind." + }, + "placeholder_mail_text_body_or_selected": { + "message": "E-Mail-Inhalt oder markierter Text" + }, + "placeholder_mail_html_body_or_selected": { + "message": "E-Mail-Inhalt oder markiertes HTML" + }, + "prefs_OptionText_chatgpt_web_load_wait_time": { + "message": "Wartezeit für das Laden der Seite" + }, + "prefs_OptionText_chatgpt_web_load_wait_time_info": { + "message": "Wartezeit in Millisekunden, bis die ChatGPT-Seite geladen ist, bevor zusätzliche Inhalte geladen werden. Der Standardwert beträgt 1000 ms. Falls un Custom GPT oder ein Project definiert ist, werden diesem Wert zusätzliche 1000 ms hinzugefügt." + }, + "prompt_get_calendar_event_from_clipboard": { + "message": "Termin aus Zwischenablage erstellen" + }, + "clipboard_read_error": { + "message": "Zwischenablage konnte nicht gelesen werden. Bitte Berechtigungen prüfen." + }, + "clipboard_empty_error": { + "message": "Zwischenablage leer. Bitte kopieren Sie zuerst einen Text." + }, + "clipboard_permission_denied": { + "message": "Zugriff auf die Zwischenablage wurde verweigert. Bitte aktiviere die Funktion in den Einstellungen erneut, um die Berechtigung zu erteilen." + }, + "clipboard_permission_error": { + "message": "Fehler bei der Berechtigungsanfrage. Bitte erneut versuchen." + }, + "prefs_OptionText_get_calendar_event_from_clipboard": { + "message": "Termin aus Zwischenablage abrufen" + }, + "prefs_OptionText_get_calendar_event_from_clipboard_Info": { + "message": "Zusätzlichen Menüpunkt einblenden: Kalendertermine aus Zwischenablagen-Text erstellen." + }, + "Summarize_prompt_prefs_title": { + "message": "Zusammenfassungseinstellungen" + }, + "prompt_summarize": { + "message": "Diese E-Mail o. E-Mails zusammenfassen" + }, + "prompt_summarize_full_text": { + "message": "Du bist ein Assistent, der E-Mail-Konversationen zusammenfasst.\n\nErstelle aus einem E-Mail-Verlauf eine prägnante und präzise Zusammenfassung, die Folgendes enthält:\n\n- Das Hauptthema oder den Zweck der Konversation\n- Wichtige Entscheidungen, Schlussfolgerungen oder Vereinbarungen\n- Wichtige Fragen, Anfragen oder Aufgaben (Action Items)\n- Die verantwortliche Person für jede Aufgabe (falls angegeben)\n\nLasse Begrüßungen, Signaturen, zitierten Text und redundantes Hin- und Her weg.\nFüge keine Annahmen oder Informationen hinzu, die nicht in den E-Mails enthalten sind.\n\nVerfasse die Zusammenfassung in einer klaren, neutralen Sprache, die für vielbeschäftigte Fachkräfte geeignet ist." + }, + "prompt_summarize_email_template": { + "message": "Vorlage für E-Mail-Zusammenfassung" + }, + "prompt_summarize_email_template_full_text": { + "message": "Von: {%author%}\nAn: {%recipients%}\nCC: {%cc_list%}\nBetreff: {%mail_subject%}\nDatum: {%mail_datetime%}\nAnhänge:\n{%mail_attachments_info%}\n\nInhalt:\n{%mail_text_body%}" + }, + "prompt_summarize_email_separator": { + "message": "E-Mail-Separator" + }, + "prompt_summarize_email_separator_full_text": { + "message": "\n\n---------- NÄCHSTE E-MAIL ----------\n\n" + }, + "prefs_OptionText_Summarize_infoline2": { + "message": "Sie können den Prompt nach Belieben anpassen: Das erste Feld ist der Haupt-Prompt, das zweite Feld ist die Vorlage für eine einzelne E-Mail. Die Liste der E-Mails wird an den Haupt-Prompt angehängt. Die E-Mails werden durch das im dritten Feld angegebene Trennzeichen voneinander getrennt." + }, + "prefs_OptionText_Summarize_main_prompt": { + "message": "Der Haupt-Prompt, der die Aufgabe für alle ausgewählten E-Mails beschreibt:" + }, + "prefs_OptionText_Summarize_email_template": { + "message": "Die Vorlage für eine einzelne E-Mail:" + }, + "prefs_OptionText_Summarize_email_separator": { + "message": "Das Trennzeichen zwischen E-Mails:" + }, + "prefs_OptionText_get_calendar_event_use_specific_integration_Info": { + "message": "Wenn aktiviert, werden das unten angegebene Modell und die API zum Erstellen von Kalenderereignissen verwendet, unabhängig von der Auswahl auf der ThunderAI-Optionsseite." + }, + "prefs_OptionText_summarize": { + "message": "E-Mail zusammenfassen" + }, + "prefs_OptionText_summarize_use_specific_integration_Info": { + "message": "Wenn aktiviert, werden das unten angegebene Modell und die API zum Zusammenfassen von E-Mails verwendet, unabhängig von der Auswahl auf der ThunderAI-Optionsseite." + }, + "prefs_OptionText_summarize_Info": { + "message": "Wenn aktiviert, wird dem Kontextmenü eine Option zum Zusammenfassen von E-Mails hinzugefügt." + }, + "prefs_OptionText_btnManageSummarizeInfo": { + "message": "Zusammenfassung verwalten" + }, + "Summarize_PageTitle": { + "message": "Zusammenfassungseinstellungen verwalten" + }, + "Summarize_info_default": { + "message": "Auf dieser Seite können Sie den Standard-Prompt für die Zusammenfassung von E-Mails bearbeiten." + }, + "Summarize_prompt_text_title": { + "message": "Aktueller Prompt-Text" + }, + "prefs_OptionText_spamfilter_show_msg_panel": { + "message": "Spam-Bericht-Panel anzeigen" + }, + "prefs_OptionText_spamfilter_show_msg_panel_Info": { + "message": "Wenn aktiviert, wird oben über der Nachricht ein Panel mit dem Spam-Bericht angezeigt." + }, + "SpamReport_infoline": { + "message": "Diese Informationen werden nur für die aktuelle Sitzung gespeichert." + }, + "Spam": { + "message": "Spam" + }, + "Valid": { + "message": "Zulässig" + }, + "context_menu_mzta-summarize": { + "message": "Zusammenfassen" + }, + "CORS_alternative_2_new": { + "message": "Klicken Sie auf die untenstehende Schaltfläche, um dem aktuellen Host die Berechtigung zu erteilen und CORS-Probleme zu vermeiden." + }, + "CORS_give_host_perm": { + "message": "Berechtigung für den aktuellen Host erteilen" + }, + "CORS_localhost_warn": { + "message": "Wenn Sie localhost oder 127.0.0.1 verwenden, da der KI-Server auf Ihrem PC gehostet wird, ist die Berechtigung erforderlich." + }, + "customPrompts_export_include_api_settings": { + "message": "Möchten Sie die API-Einstellungen in den Export einbeziehen? Bitte beachten Sie, dass auch der API-Schlüssel in der Datei gespeichert wird!" + }, + "prefs_OptionText_calendar_no_selection": { + "message": "Nicht zur Textauswahl auffordern" + }, + "prefs_OptionText_calendar_no_selection_Info": { + "message": "Wenn aktiviert, ist keine Textauswahl erforderlich. Der gesamte Nachrichtentext wird verwendet, um das Kalenderereignis zu erstellen." + }, + "customPrompts_btnCopy": { + "message": "Kopieren" + }, + "copy_text": { + "message": "kopie" + }, + "spam_check_in_progress": { + "message": "Spam-Prüfung läuft..." + }, + "prefs_THStats_1": { + "message": "Möchtest du schöne Statistiken zu deinen E-Mails erhalten?" + }, + "prefs_THStats_2": { + "message": "Hier klicken! Probiere ThunderStats aus!" } } From 67a922ee02d872a650af604c18dbb72776d23cca Mon Sep 17 00:00:00 2001 From: mic Date: Sun, 22 Feb 2026 09:35:42 +0100 Subject: [PATCH 22/38] onboarding improved --- pages/onboarding/onboarding.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pages/onboarding/onboarding.html b/pages/onboarding/onboarding.html index 904a6610..953e3bef 100644 --- a/pages/onboarding/onboarding.html +++ b/pages/onboarding/onboarding.html @@ -29,7 +29,7 @@

Welcome to ThunderAI!
This add-on is designed to enhance your email management with the power of AI. -
With ThunderAI, you can streamline your inbox, generate smart replies, summarize emails, and much more—all with the help of artificial intelligence. +
With ThunderAI, you can streamline your inbox, generate smart replies, summarize emails, automatically add tags and filter spam, and much more, all with the help of artificial intelligence.

On this page, you'll find an overview of the key features available to help you make the most of ThunderAI.
Get ready to experience a smarter, more efficient way to handle your emails!

Let's see how to make best use of this add-on! @@ -55,12 +55,12 @@

Defining your Custom Prompts

Managing Custom Prompts

- From the options page you can open the Custom Prompts page. + From the options page you can open the Custom Prompts page.
From there you can add your prompts, and also disable the default ones.
You can find more info here.

- While defining your own prompts you can also use data placeholders, that will be substituted with the corresponding information when using the prompt. + While defining your own prompts you can also use data placeholders, that will be substituted with the corresponding information when using the prompt.
You can find more info here.

From e8e6c86be1a86c81766b8ec4da46a1d85e8f681e Mon Sep 17 00:00:00 2001 From: mic Date: Sun, 22 Feb 2026 22:22:22 +0100 Subject: [PATCH 23/38] getMailHeader now returns always a string. sanitizeMailHeaders method added. see #672 --- js/mzta-utils.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/js/mzta-utils.js b/js/mzta-utils.js index 67ce0823..601a082c 100644 --- a/js/mzta-utils.js +++ b/js/mzta-utils.js @@ -194,7 +194,8 @@ export async function getMailHeader(curr_message, mail_header_id) { let full_message = await browser.messages.getFull(curr_message.id); // console.log(">>>>>>>>>>>> getMailHeader full_message: " + JSON.stringify(full_message)); if(full_message.hasOwnProperty("headers") && Object.keys(full_message.headers).some(header => header.toLowerCase() === mail_header_id.toLowerCase())){ - mail_header_value = full_message.headers[Object.keys(full_message.headers).find(header => header.toLowerCase() === mail_header_id.toLowerCase())]; + const raw_value = full_message.headers[Object.keys(full_message.headers).find(header => header.toLowerCase() === mail_header_id.toLowerCase())]; + mail_header_value = Array.isArray(raw_value) ? raw_value.join(", ") : raw_value; } // console.log(">>>>>>>>>>>> getMailHeader mail_header_value: " + mail_header_value) return mail_header_value; @@ -205,6 +206,12 @@ export function sanitizeHtml(input) { return input.replace(/<(?!br\s*\/?)[^>]+>/gi, ''); } +export function sanitizeMailHeaders(input){ + console.log(">>>>>>>>>>>> sanitizeMailHeaders input: " + JSON.stringify(input)); + if(!input) return ''; + return input.replace(//g, '>'); +} + export function stripHtmlKeepLines(htmlString) { // Replaces

tags with a newline at the beginning // and removes all other HTML tags From 3510636eb36ee97dfdf67e596157738980951bfc Mon Sep 17 00:00:00 2001 From: mic Date: Sun, 22 Feb 2026 22:23:24 +0100 Subject: [PATCH 24/38] using sanitizeMailHeaders when needed. see #672 --- js/mzta-placeholders.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/js/mzta-placeholders.js b/js/mzta-placeholders.js index bfb841c7..ad169f8d 100644 --- a/js/mzta-placeholders.js +++ b/js/mzta-placeholders.js @@ -17,7 +17,10 @@ */ import { prefs_default } from '../options/mzta-options-default.js'; -import { getMailHeader } from './mzta-utils.js'; +import { + getMailHeader, + sanitizeMailHeaders + } from './mzta-utils.js'; /* ================= PLACEHOLDERS PROPERTIES ======================================== @@ -509,7 +512,7 @@ export const placeholdersUtils = { finalSubs['mail_folder_path'] = placeholdersUtils.failSafePlaceholders(curr_message.folder?.path); break; case 'mail_headers': - finalSubs['mail_headers:' + currPH.custom_value] = placeholdersUtils.failSafePlaceholders(await getMailHeader(curr_message, currPH.custom_value)); + finalSubs['mail_headers:' + currPH.custom_value] = placeholdersUtils.failSafePlaceholders(sanitizeMailHeaders(await getMailHeader(curr_message, currPH.custom_value))); break; case 'selected_text': finalSubs['selected_text'] = placeholdersUtils.failSafePlaceholders(selection_text); @@ -518,13 +521,13 @@ export const placeholdersUtils = { finalSubs['selected_html'] = placeholdersUtils.failSafePlaceholders(selection_html); break; case 'author': - finalSubs['author'] = placeholdersUtils.failSafePlaceholders(curr_message.author); + finalSubs['author'] = placeholdersUtils.failSafePlaceholders(sanitizeMailHeaders(curr_message.author)); break; case 'recipients': - finalSubs['recipients'] = placeholdersUtils.failSafePlaceholders(curr_message.recipients?.join(", ")); + finalSubs['recipients'] = placeholdersUtils.failSafePlaceholders(sanitizeMailHeaders(curr_message.recipients?.join(", "))); break; case 'cc_list': - finalSubs['cc_list'] = placeholdersUtils.failSafePlaceholders(curr_message.ccList?.join(", ")); + finalSubs['cc_list'] = placeholdersUtils.failSafePlaceholders(sanitizeMailHeaders(curr_message.ccList?.join(", "))); break; case 'junk_score': finalSubs['junk_score'] = placeholdersUtils.failSafePlaceholders(curr_message.junkScore); From a8a04df0a8c260c646f7f2beeaee4329856aff9b Mon Sep 17 00:00:00 2001 From: mic Date: Sun, 22 Feb 2026 22:26:10 +0100 Subject: [PATCH 25/38] version set to 3.8.5. release notes updated --- CHANGELOG.md | 4 ++++ manifest.json | 2 +- options/mzta-release-notes.html | 4 ++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bdfdc8c2..e2d3a870 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ +

Version 3.8.5 - 22/02/2026

+
    +
  • Fix: Correctly showing email addresses when using mail headers in data placeholders [#672].
  • +

Version 3.8.4 - 10/02/2026

  • [ChatGPT Web] Fix: Correctly importing the selected text into the compose windows also when ChatGPT shows the advanced mail editor in the response [#646].
  • diff --git a/manifest.json b/manifest.json index 5c77e980..e5f5608a 100644 --- a/manifest.json +++ b/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 2, "name": "ThunderAI", "description": "__MSG_extensionDescription__", - "version": "3.8.4", + "version": "3.8.5", "author": "Mic (m@micz.it)", "homepage_url": "https://micz.it/thunderbird-addon-thunderai/", "browser_specific_settings": { diff --git a/options/mzta-release-notes.html b/options/mzta-release-notes.html index 33f60cf8..d97949b5 100644 --- a/options/mzta-release-notes.html +++ b/options/mzta-release-notes.html @@ -7,6 +7,10 @@

    ThunderAI Release Notes

    +

    Version 3.8.5 - 22/02/2026

    +
      +
    • Fix: Correctly showing email addresses when using mail headers in data placeholders [#672].
    • +

    Version 3.8.4 - 10/02/2026

    • [ChatGPT Web] Fix: Correctly importing the selected text into the compose windows also when ChatGPT shows the advanced mail editor in the response [#646].
    • From 470b78ce907cdcbd971e0e718ae10a84911978ec Mon Sep 17 00:00:00 2001 From: mic Date: Sun, 22 Feb 2026 22:39:59 +0100 Subject: [PATCH 26/38] checking for the correct placeholder before activating the no selection option in get calendar event. see #670 --- _locales/en/messages.json | 4 ++++ pages/get-calendar-event/mzta-get-calendar-event.js | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 817bfe66..c6aacb70 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -1881,6 +1881,10 @@ "message": "If checked there is no need to select some text. The full message body will be used to get the calendar event.", "description": "" }, + "prefs_OptionText_calendar_no_selection_missing_placeholder": { + "message": "The prompt must contain the placeholder {%mail_text_body_or_selected%} or {%mail_html_body_or_selected%} to enable this option. Please add one of these placeholders to the prompt or reset it to the default.", + "description": "" + }, "customPrompts_btnCopy": { "message": "Copy", "description": "" diff --git a/pages/get-calendar-event/mzta-get-calendar-event.js b/pages/get-calendar-event/mzta-get-calendar-event.js index 7dc9a0e9..ca3c8ef7 100644 --- a/pages/get-calendar-event/mzta-get-calendar-event.js +++ b/pages/get-calendar-event/mzta-get-calendar-event.js @@ -98,6 +98,15 @@ document.addEventListener('DOMContentLoaded', async () => { }); get_calendar_event_no_selection.addEventListener('change', async (event) => { + if (event.target.checked) { + const currentPromptText = get_calendar_event_textarea.value; + const hasBodyOrSelected = currentPromptText.includes('{%mail_text_body_or_selected%}') || currentPromptText.includes('{%mail_html_body_or_selected%}'); + if (!hasBodyOrSelected) { + alert(browser.i18n.getMessage('prefs_OptionText_calendar_no_selection_missing_placeholder')); + event.target.checked = false; + return; + } + } specialPrompts.find(prompt => prompt.id === 'prompt_get_calendar_event').need_selected = event.target.checked ? '0' : '1'; await setSpecialPrompts(specialPrompts); browser.runtime.sendMessage({command: "reload_menus"}); From 9894c2114cfb6d29b13791a2eeeee181f7173360 Mon Sep 17 00:00:00 2001 From: mic Date: Sun, 22 Feb 2026 22:53:36 +0100 Subject: [PATCH 27/38] svg added when receiving text. see #671 --- api_webchat/messageInput.js | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/api_webchat/messageInput.js b/api_webchat/messageInput.js index 2907174f..335de65d 100644 --- a/api_webchat/messageInput.js +++ b/api_webchat/messageInput.js @@ -66,6 +66,13 @@ messagesInputStyle.textContent = ` border-radius: 5px; padding: 5px; background: #F2F2F2; + display: flex; + align-items: center; + gap: 3px; + } + #statusLoggerImg{ + display: none; + vertical-align: middle; } #mzta-custom_text{ padding:10px; @@ -183,8 +190,14 @@ messageInputTemplate.content.appendChild(stopButton); const statusLogger = document.createElement('div'); statusLogger.id = 'statusLogger'; -statusLogger.textContent = ''; statusLogger.style.display = 'none'; +const statusLoggerImg = document.createElement('img'); +statusLoggerImg.id = 'statusLoggerImg'; +statusLoggerImg.src = browser.runtime.getURL('/popup/mzta-loading.svg'); +statusLogger.appendChild(statusLoggerImg); +const statusLoggerText = document.createElement('span'); +statusLoggerText.id = 'statusLoggerText'; +statusLogger.appendChild(statusLoggerText); messageInputTemplate.content.appendChild(statusLogger); //div per custom text @@ -227,6 +240,8 @@ class MessageInput extends HTMLElement { this._sendButton = shadowRoot.querySelector('#sendButton'); this._stopButton = shadowRoot.querySelector('#stopButton'); this._statusLogger = shadowRoot.querySelector('#statusLogger'); + this._statusLoggerImg = shadowRoot.querySelector('#statusLoggerImg'); + this._statusLoggerText = shadowRoot.querySelector('#statusLoggerText'); this._messageInputField.addEventListener('keydown', this._handleKeyDown.bind(this)); this._sendButton.addEventListener('click', this._handleClick.bind(this)); @@ -284,15 +299,16 @@ class MessageInput extends HTMLElement { } setStatusMessage(message) { - this._statusLogger.textContent = message; + this._statusLoggerText.textContent = message; } showStatusMessage() { - this._statusLogger.style.display = 'block'; + this._statusLogger.style.display = 'flex'; } hideStatusMessage() { this._statusLogger.style.display = 'none'; + this._statusLoggerImg.style.display = 'none'; } _handleKeyDown(event) { @@ -328,6 +344,7 @@ class MessageInput extends HTMLElement { this.messagesAreaComponent.appendUserMessage(messageContent); } this.setStatusMessage(browser.i18n.getMessage('WaitingServerResponse') + '...'); + this._statusLoggerImg.style.display = 'inline'; this.showStatusMessage(); this.worker.postMessage({ type: 'chatMessage', message: messageContent }); } From cad0cc59ccc9c8797f0b663f5937c2264554e63c Mon Sep 17 00:00:00 2001 From: mic Date: Sun, 22 Feb 2026 22:56:08 +0100 Subject: [PATCH 28/38] mzta-loading.svg moved in /images/ --- api_webchat/messageInput.js | 2 +- {popup => images}/mzta-loading.svg | 2 +- popup/mzta-popup.html | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) rename {popup => images}/mzta-loading.svg (98%) diff --git a/api_webchat/messageInput.js b/api_webchat/messageInput.js index 335de65d..567339ee 100644 --- a/api_webchat/messageInput.js +++ b/api_webchat/messageInput.js @@ -193,7 +193,7 @@ statusLogger.id = 'statusLogger'; statusLogger.style.display = 'none'; const statusLoggerImg = document.createElement('img'); statusLoggerImg.id = 'statusLoggerImg'; -statusLoggerImg.src = browser.runtime.getURL('/popup/mzta-loading.svg'); +statusLoggerImg.src = browser.runtime.getURL('/images/mzta-loading.svg'); statusLogger.appendChild(statusLoggerImg); const statusLoggerText = document.createElement('span'); statusLoggerText.id = 'statusLoggerText'; diff --git a/popup/mzta-loading.svg b/images/mzta-loading.svg similarity index 98% rename from popup/mzta-loading.svg rename to images/mzta-loading.svg index 27b59d6a..9dec98ab 100644 --- a/popup/mzta-loading.svg +++ b/images/mzta-loading.svg @@ -7,4 +7,4 @@ - \ No newline at end of file + diff --git a/popup/mzta-popup.html b/popup/mzta-popup.html index 1abeead3..02caba36 100644 --- a/popup/mzta-popup.html +++ b/popup/mzta-popup.html @@ -19,9 +19,9 @@
     
    -
    +
    -
    +
    From c2e2336f4d806507da2dc3d7fdde9e51fa1a2020 Mon Sep 17 00:00:00 2001 From: mic Date: Sun, 22 Feb 2026 23:07:51 +0100 Subject: [PATCH 29/38] Added "Antispam by ThunderAI" --- _locales/en/messages.json | 4 ++++ js/mzta-compose-script.js | 12 +++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index c6aacb70..bfc1d731 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -1897,6 +1897,10 @@ "message": "Spam check in progress...", "description": "" }, + "antispam_by": { + "message": "Antispam by", + "description": "" + }, "prefs_THStats_1": { "message": "Do you want beautiful statistics about your emails?", "description": "" diff --git a/js/mzta-compose-script.js b/js/mzta-compose-script.js index e30298fd..7dfd4168 100644 --- a/js/mzta-compose-script.js +++ b/js/mzta-compose-script.js @@ -641,8 +641,13 @@ switch (message.command) { loadingImg.src = browser.runtime.getURL("/images/loading.gif"); loadingImg.style.cssText = "height: 16px; width: 16px;"; + const brandingProgress = document.createElement('span'); + brandingProgress.textContent = browser.i18n.getMessage("antispam_by") + " ThunderAI"; + brandingProgress.style.cssText = 'margin-left: auto; font-style: italic; font-size: 11px; opacity: 0.7;'; + containerProgress.appendChild(loadingImg); containerProgress.appendChild(textProgress); + containerProgress.appendChild(brandingProgress); document.body.insertBefore(containerProgress, document.body.firstChild); return Promise.resolve(true); @@ -693,9 +698,13 @@ switch (message.command) { reasonText.textContent = browser.i18n.getMessage("Explanation") + ": " + data.explanation; } + const branding = document.createElement('span'); + branding.textContent = browser.i18n.getMessage("antispam_by") + " ThunderAI"; + branding.style.cssText = 'margin-left: auto; font-style: italic; font-size: 11px; opacity: 0.7;'; + const closeBtn = document.createElement('span'); closeBtn.textContent = '×'; - closeBtn.style.cssText = 'margin-left: auto; cursor: pointer; font-weight: bold; font-size: 16px; padding: 0 5px;'; + closeBtn.style.cssText = 'cursor: pointer; font-weight: bold; font-size: 16px; padding: 0 5px;'; closeBtn.title = browser.i18n.getMessage("chatgpt_win_close"); closeBtn.onclick = function() { container.remove(); @@ -704,6 +713,7 @@ switch (message.command) { container.appendChild(scoreText); container.appendChild(reasonText); + container.appendChild(branding); container.appendChild(closeBtn); document.body.insertBefore(container, document.body.firstChild); From fe5f1db7b6cdc1ee7a72bdc37d0a1cddf33776e0 Mon Sep 17 00:00:00 2001 From: Andreas Pettersson Date: Mon, 23 Feb 2026 16:52:53 +0100 Subject: [PATCH 30/38] Translated using Weblate (Swedish) Currently translated at 100.0% (475 of 475 strings) Translation: ThunderAI for Thunderbird/main Translate-URL: https://hosted.weblate.org/projects/thunderai/main/sv/ --- _locales/sv/messages.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/_locales/sv/messages.json b/_locales/sv/messages.json index 325dbc42..90f0ea9f 100644 --- a/_locales/sv/messages.json +++ b/_locales/sv/messages.json @@ -1427,5 +1427,11 @@ }, "prefs_THStats_2": { "message": "Klicka här! Testa ThunderStats!" + }, + "antispam_by": { + "message": "Antispam av" + }, + "prefs_OptionText_calendar_no_selection_missing_placeholder": { + "message": "Prompten måste innehålla platshållaren {%mail_text_body_or_selected%} eller {%mail_html_body_or_selected%} för att aktivera det här alternativet. Lägg till en av dessa platshållare i prompten eller återställ den till standard." } } From e65699386c3868fe1382c3fdd39e814733a2674e Mon Sep 17 00:00:00 2001 From: Mic Date: Mon, 23 Feb 2026 12:14:08 +0100 Subject: [PATCH 31/38] Translated using Weblate (French) Currently translated at 100.0% (475 of 475 strings) Translation: ThunderAI for Thunderbird/main Translate-URL: https://hosted.weblate.org/projects/thunderai/main/fr/ --- _locales/fr/messages.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/_locales/fr/messages.json b/_locales/fr/messages.json index b823a370..dc41a8e9 100644 --- a/_locales/fr/messages.json +++ b/_locales/fr/messages.json @@ -1443,5 +1443,11 @@ }, "prefs_THStats_2": { "message": "Cliquez ici ! Essayez ThunderStats !" + }, + "prefs_OptionText_calendar_no_selection_missing_placeholder": { + "message": "L'invite doit contenir l'espace réservé {%mail_text_body_or_selected%} ou {%mail_html_body_or_selected%} pour activer cette option. Veuillez ajouter l'un de ces espaces réservés à l'invite ou rétablir la valeur par défaut." + }, + "antispam_by": { + "message": "Antispam par" } } From 6dc7b052c15a45c8b005e4af88a0a0072b05d3fc Mon Sep 17 00:00:00 2001 From: Mic Date: Mon, 23 Feb 2026 12:13:57 +0100 Subject: [PATCH 32/38] Translated using Weblate (German) Currently translated at 100.0% (475 of 475 strings) Translation: ThunderAI for Thunderbird/main Translate-URL: https://hosted.weblate.org/projects/thunderai/main/de/ --- _locales/de/messages.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/_locales/de/messages.json b/_locales/de/messages.json index 09aba133..66367494 100644 --- a/_locales/de/messages.json +++ b/_locales/de/messages.json @@ -1443,5 +1443,11 @@ }, "prefs_THStats_2": { "message": "Hier klicken! Probiere ThunderStats aus!" + }, + "prefs_OptionText_calendar_no_selection_missing_placeholder": { + "message": "Der Prompt muss den Platzhalter {%mail_text_body_or_selected%} oder {%mail_html_body_or_selected%} enthalten, um diese Option zu aktivieren. Bitte fügen Sie einen dieser Platzhalter zum Prompt hinzu oder setzen Sie ihn auf den Standardwert zurück." + }, + "antispam_by": { + "message": "Antispam von" } } From c569795098189f3c080d9889f3ee6b8e920a3248 Mon Sep 17 00:00:00 2001 From: Mic Date: Mon, 23 Feb 2026 12:13:38 +0100 Subject: [PATCH 33/38] Translated using Weblate (Italian) Currently translated at 100.0% (475 of 475 strings) Translation: ThunderAI for Thunderbird/main Translate-URL: https://hosted.weblate.org/projects/thunderai/main/it/ --- _locales/it/messages.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/_locales/it/messages.json b/_locales/it/messages.json index 5054722a..5bd0eb19 100644 --- a/_locales/it/messages.json +++ b/_locales/it/messages.json @@ -1443,5 +1443,11 @@ }, "prefs_THStats_2": { "message": "Clicca qui! Prova ThunderStats!" + }, + "prefs_OptionText_calendar_no_selection_missing_placeholder": { + "message": "Il prompt deve contenere il segnaposto {%mail_text_body_or_selected%} o {%mail_html_body_or_selected%} per abilitare questa opzione. Per favore, aggiungi uno di questi segnaposto al prompt o ripristina quello predefinito." + }, + "antispam_by": { + "message": "Antispam di" } } From 4f84da425636ac91494f6b70f3b8de1052ce37cc Mon Sep 17 00:00:00 2001 From: mic Date: Mon, 23 Feb 2026 21:55:10 +0100 Subject: [PATCH 34/38] Fixes ported from v3.8.5. --- js/mzta-placeholders.js | 13 ++++++++----- js/mzta-utils.js | 9 ++++++++- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/js/mzta-placeholders.js b/js/mzta-placeholders.js index c666e858..48de04a3 100644 --- a/js/mzta-placeholders.js +++ b/js/mzta-placeholders.js @@ -17,7 +17,10 @@ */ import { prefs_default } from '../options/mzta-options-default.js'; -import { getMailHeader } from './mzta-utils.js'; +import { + getMailHeader, + sanitizeMailHeaders + } from './mzta-utils.js'; /* ================= PLACEHOLDERS PROPERTIES ======================================== @@ -545,7 +548,7 @@ export const placeholdersUtils = { finalSubs['mail_folder_path'] = placeholdersUtils.failSafePlaceholders(curr_message.folder?.path); break; case 'mail_headers': - finalSubs['mail_headers:' + currPH.custom_value] = placeholdersUtils.failSafePlaceholders(await getMailHeader(curr_message, currPH.custom_value)); + finalSubs['mail_headers:' + currPH.custom_value] = placeholdersUtils.failSafePlaceholders(sanitizeMailHeaders(await getMailHeader(curr_message, currPH.custom_value))); break; case 'selected_text': finalSubs['selected_text'] = placeholdersUtils.failSafePlaceholders(selection_text); @@ -560,13 +563,13 @@ export const placeholdersUtils = { finalSubs['mail_html_body_or_selected'] = placeholdersUtils.failSafePlaceholders(selection_html || msg_text?.html); break; case 'author': - finalSubs['author'] = placeholdersUtils.failSafePlaceholders(curr_message.author); + finalSubs['author'] = placeholdersUtils.failSafePlaceholders(sanitizeMailHeaders(curr_message.author)); break; case 'recipients': - finalSubs['recipients'] = placeholdersUtils.failSafePlaceholders(curr_message.recipients?.join(", ")); + finalSubs['recipients'] = placeholdersUtils.failSafePlaceholders(sanitizeMailHeaders(curr_message.recipients?.join(", "))); break; case 'cc_list': - finalSubs['cc_list'] = placeholdersUtils.failSafePlaceholders(curr_message.ccList?.join(", ")); + finalSubs['cc_list'] = placeholdersUtils.failSafePlaceholders(sanitizeMailHeaders(curr_message.ccList?.join(", "))); break; case 'junk_score': finalSubs['junk_score'] = placeholdersUtils.failSafePlaceholders(curr_message.junkScore); diff --git a/js/mzta-utils.js b/js/mzta-utils.js index a8aabdb2..ab8d7ef5 100644 --- a/js/mzta-utils.js +++ b/js/mzta-utils.js @@ -207,7 +207,8 @@ export async function getMailHeader(curr_message, mail_header_id) { let full_message = await browser.messages.getFull(curr_message.id); // console.log(">>>>>>>>>>>> getMailHeader full_message: " + JSON.stringify(full_message)); if(full_message.hasOwnProperty("headers") && Object.keys(full_message.headers).some(header => header.toLowerCase() === mail_header_id.toLowerCase())){ - mail_header_value = full_message.headers[Object.keys(full_message.headers).find(header => header.toLowerCase() === mail_header_id.toLowerCase())]; + const raw_value = full_message.headers[Object.keys(full_message.headers).find(header => header.toLowerCase() === mail_header_id.toLowerCase())]; + mail_header_value = Array.isArray(raw_value) ? raw_value.join(", ") : raw_value; } // console.log(">>>>>>>>>>>> getMailHeader mail_header_value: " + mail_header_value) return mail_header_value; @@ -218,6 +219,12 @@ export function sanitizeHtml(input) { return input.replace(/<(?!br\s*\/?)[^>]+>/gi, ''); } +export function sanitizeMailHeaders(input){ + console.log(">>>>>>>>>>>> sanitizeMailHeaders input: " + JSON.stringify(input)); + if(!input) return ''; + return input.replace(//g, '>'); +} + export function stripHtmlKeepLines(htmlString) { // Replaces

    tags with a newline at the beginning // and removes all other HTML tags From a355dfb6d6c4f2f885e6baf8d0071ecf6760c16f Mon Sep 17 00:00:00 2001 From: Mic Date: Mon, 23 Feb 2026 21:59:34 +0100 Subject: [PATCH 35/38] Add 'enhancement' label to new issue creation Added 'enhancement' label to the issue creation in the workflow. --- .github/workflows/tom-select-release-check.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tom-select-release-check.yml b/.github/workflows/tom-select-release-check.yml index a0f1002e..1ba3394b 100644 --- a/.github/workflows/tom-select-release-check.yml +++ b/.github/workflows/tom-select-release-check.yml @@ -48,13 +48,14 @@ jobs: owner, repo, title: issueTitle, + labels: ['enhancement'], body: `Update Tom Select to version **${latestTag}**. https://cdn.jsdelivr.net/npm/tom-select@${latestTag}/dist/js/tom-select.base.js https://cdn.jsdelivr.net/npm/tom-select@${latestTag}/dist/css/tom-select.default.min.css - Remeber also to update the VENDORS.md file.` + Remember also to update the VENDORS.md file.` }); core.info(`New issue created for version ${latestTag}.`); } From 49c5791d644b623589e17c62b97903f6fe96edc9 Mon Sep 17 00:00:00 2001 From: mic Date: Mon, 23 Feb 2026 22:15:35 +0100 Subject: [PATCH 36/38] tom select updated to version 3.5.2. fixes #673 --- pages/_lib/tom-select.base.js | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/pages/_lib/tom-select.base.js b/pages/_lib/tom-select.base.js index 8e42b70b..2d1c3390 100644 --- a/pages/_lib/tom-select.base.js +++ b/pages/_lib/tom-select.base.js @@ -1,5 +1,5 @@ /** -* Tom Select v2.5.1 +* Tom Select v2.5.2 * Licensed under the Apache License, Version 2.0 (the "License"); */ @@ -2906,7 +2906,7 @@ if (self.settings.hideSelected) { result.items = result.items.filter(item => { let hashed = hash_key(item.id); - return !(hashed && self.items.indexOf(hashed) !== -1); + return !(hashed !== null && self.items.indexOf(hashed) !== -1); }); } return result; @@ -2985,6 +2985,13 @@ optgroup = optgroups[j]; let order = option.$order; let self_optgroup = self.optgroups[optgroup]; + if (self_optgroup === undefined && typeof self.settings.optionGroupRegister === 'function') { + var regGroup; + if (regGroup = self.settings.optionGroupRegister.apply(self, [optgroup])) { + self.registerOptionGroup(regGroup); + } + } + self_optgroup = self.optgroups[optgroup]; if (self_optgroup === undefined) { optgroup = ''; } else { @@ -3444,6 +3451,11 @@ } } + //remove input value when enabled + if (self.settings.clearAfterSelect) { + self.setTextboxValue(); + } + // refreshOptions after setActiveOption(), // otherwise setActiveOption() will be called by refreshOptions() with the wrong value if (!self.isPending && !self.settings.closeAfterSelect) { @@ -3456,11 +3468,6 @@ } else if (!self.isPending) { self.positionDropdown(); } - - //remove input value when enabled - if (self.settings.clearAfterSelect) { - self.setTextboxValue(); - } self.trigger('item_add', hashed, item); if (!self.isPending) { self.updateOriginalInput({ From d3246417a9e59614d17b0b4ab357e84f558c1272 Mon Sep 17 00:00:00 2001 From: Mic Date: Tue, 24 Feb 2026 21:03:39 +0100 Subject: [PATCH 37/38] Change cron schedule to check daily at 19:00 --- .github/workflows/tom-select-release-check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tom-select-release-check.yml b/.github/workflows/tom-select-release-check.yml index 1ba3394b..eb51f281 100644 --- a/.github/workflows/tom-select-release-check.yml +++ b/.github/workflows/tom-select-release-check.yml @@ -2,7 +2,7 @@ name: Check Tom-Select Latest Release on: schedule: - - cron: '0 0 * * *' # Check every day at midnight + - cron: '0 19 * * *' # Check every day at 19:00 workflow_dispatch: # Allows manual triggering for testing purposes permissions: From fb6b1d6b8e61f580e3fac7f78c73f516c31e84c1 Mon Sep 17 00:00:00 2001 From: mic Date: Tue, 24 Feb 2026 21:26:22 +0100 Subject: [PATCH 38/38] GEMINI.md renamed in CLAUDE.md --- GEMINI.md => CLAUDE.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename GEMINI.md => CLAUDE.md (100%) diff --git a/GEMINI.md b/CLAUDE.md similarity index 100% rename from GEMINI.md rename to CLAUDE.md