Mail Support Assistant
Mail Support Assistant är ett adminkonfigurerat supportmailflöde för Tools och den fristående PHP-klienten som ligger under public/tornevall-tools-mail-assistant.
Vad den gör
- lagrar IMAP-mailboxar i Tools admin
- lagrar regelstyrd matchning på From, To, Subject och valfri body-text
- tillåter per regel statiska autosvar eller Tools/OpenAI-stödda svar
- stöder per regel egen avsändare, BCC, footer, responder/persona/mood/custom instruction, vald AI-modell och reasoning effort
- stöder mailboxnivåns AI-triage för omatchade mail med sorterade add-row If... + Instructions...-regler plus en strikt mailboxägd sista fallback
- låter den fristående klienten avgöra om ett hanterat mail ska flyttas till en folder eller raderas efter svar
- kan nu synka behandlade mailtrådar tillbaka till Tools som spårade supportärenden, med både trådad Tools-adminvy och publik ärendelänk som kan delas med mottagaren
- varje oläst inkommande mailboxmail som inte redan är markerat som läst eller redan är ett assistentskickat loopmail rapporteras nu också direkt till Tools när standalone-runnern hittar det, redan innan svar/no-match-hanteringen har bestämt slututfallet
- centraliserade Tools-ärenden kan nu också lagra additiva fullständiga inbound-/outbound-bodyfält samt metadata om vilken runner/server som hanterade mailet, så admin kan läsa själva innehållet även när cronjobbet kördes på en annan host
- centraliserade Tools-ärenden kan nu också lagra råa inbound-headers, parsade headerkartor och rå/plain/HTML-varianter av bodyn, så admin kan inspektera hanterade eller ignorerade mail mer som i en riktig fjärrmailklient
- obesvarade eller omatchade synkade trådar hålls nu också tydligt synliga i Tools som uppföljningsärenden, så operatören kan öppna dem senare i stället för att de bara försvinner i standalone-runnerns senaste körningssammanfattning
- den trådade ärendesidan i Tools kan nu också utkastgenerera och skicka ett svar direkt från Tools med ett operatörsinstruktionsfält, en redigerbar svarstext och ett Tools-hostat utskick
- samma trådade ärendesida i Tools har nu också en tillfällig mood-/tonruta samt explicita val för modell och reasoning effort, så operatören kan styra ett manuellt utkast tydligare utan att först ändra mailboxregeln
- hälsning och avslutning normaliseras nu också automatiskt på den Tools-sidiga ärendesidan, så både genererade utkast och slutligt skickade svar inte längre råkar tappa inledande hälsning eller footer/signatur bara för att modellen utelämnade dem en gång
- dessa Tools-svar från den trådade ärendesidan genererar och sparar nu också ett stabilt reply issue-id när ett äldre överlämnat ärende fortfarande saknade ett, så det utgående subjectet åter får samma spårningstagg i stil med
[Ärende MSA-…] i stället för att falla tillbaka till ett vanligt Re:-subject
- när ett relevant oläst mail har lämnats över framgångsrikt till det centraliserade uppföljningsflödet i Tools kan standalone-runnern nu markera mailboxkopian som läst, så samma olästa mail inte fortsätter komma tillbaka bara för att den manuella uppföljningen nu sker i Tools
- gamla synkade trådar kan nu raderas direkt från Tools admins ärendelista/detaljsida, och admins kan också bulkstäda äldre synkade trådar efter ålder/status från samma adminyta
- recent-case-korten på
/admin/mail-support-assistant försvinner nu också direkt när en synkad tråd raderas, i stället för att operatören måste vänta på en full sidomladdning
- kan valfritt skicka ett operatörsmejl efter en körning med en sammanfattning av de mail som inte besvarades
- lämnar orörda mail helt orörda om ingen regel matchar
- håller standalone-runtime helt framework-fri (vanlig PHP, inget Laravel-runtimekrav)
Förutsättningar
Innan Mail Support Assistant faktiskt kan fungera i drift behöver följande vara på plats:
Tools / konto
- ett riktigt Tools- / ToolsAPI-konto på samma Tools-host som ska leverera config/API-anropen
- åtkomst till admin-UI:t på
/admin/mail-support-assistant
- minst en konfigurerad mailbox i Tools admin
- en personlig klienttoken från Tools admin:
provider_mail_support_assistant
- aktiv
- AI-kapabel (
is_ai=1)
- godkänd
provider_openai-access för tokenägaren om någon regel eller omatchad fallback använder AI och ägaren inte är admin
Valfria Tools-krav
- en dedikerad relay-token
provider_mail_support_assistant_mailer om utgående mail ska skickas via POST /api/mail-support-assistant/send-reply
- rättigheten
mail-support-assistant.relay för relay-tokenets ägare när Tools-relay ska tillåtas för icke-admin-användare
Mail / runtime
- fungerande IMAP-uppgifter lagrade i Tools admin för varje mailbox som runnern ska polla
- en nåbar Tools base URL från standalone-runtime
- en vald strategi för utgående transport:
- lokal SMTP
- PHP
mail()
- eget MTA-kommando
- eller Tools relay
- PHP-runtime med nödvändiga extensioner och skrivbar lokal
storage/ för loggar, sammanfattningar och valfri lokal state
Praktisk driftnot
- den fristående klienten hittar inte på mailboxkonfiguration lokalt; mailboxar, regler, responder-defaults, omatchade fallback-rader och större delen av beteendet styrs först i Tools
- om det saknas Tools-konto, giltig klienttoken eller mailboxkonfiguration i Tools admin så har supportassistenten inte tillräckligt underlag för att köra
Support / ändringar / issue tracking
Om du behöver hjälp, vill beställa en ändring eller rapportera problem i den fristående klienten ska du använda GitHub tickets här:
Det repot är rätt plats för runtime-/klientproblem, installationsfrågor och feature requests för den fristående Mail Support Assistant-klienten.
Tools admin-UI
Admin-only-konfiguration finns på:
/admin/mail-support-assistant
Därifrån kan du:
- skapa/uppdatera mailboxar
- lägga till sorterade svarregler per mailbox
- rotera den dedikerade tokenen för standalone-klienten (
provider_mail_support_assistant)
- rotera en dedikerad relay-token (
provider_mail_support_assistant_mailer) för utgående mailskick via Tools
- granska nyligen synkade supportärenden som standalone-assistenten skickat tillbaka in i Tools
- radera en gammal synkad tråd direkt eller bulkstäda äldre synkade trådar efter ålder/status
- öppna ett trådat ärende och besvara det direkt från Tools genom att skapa ett utkast, redigera svarstexten och skicka det via Tools mailtransport
- styra ett direktutkast med en egen tillfällig mood/ton samt explicit modell och reasoning innan utkastet genereras
Mailboxinställningarna har nu också en sektion för generiskt AI-svar på omatchade mail. Där kan admin styra mailboxnivå-fallback för mail som inte träffar någon explicit regel, inklusive:
- aktivera/inaktivera AI-fallback för omatchade mail
- valfri modellöverskrivning för just den mailboxen
- valfri reasoning-överskrivning för just den mailboxen
- valfri mailboxnivå-tröskel för spam score som stoppar svar och lämnar mailet oläst när score är för hög
- en strikt mailboxnivå-fallback med egen kryssruta, allow-condition och sista instruktionstext
- mailboxspecifika add-row If...-regler som beskriver vilka annars omatchade mail som får besvaras före denna sista fallback
- per-rad instruktionstext för dessa avancerade omatchade svar
- valfri per-rad override för footer/modell/reasoning
Tools admin-sidan stöder nu också lättviktig AJAX-sparning för create/update/delete av mailboxar och regler, så vanliga ändringar inte längre måste gå genom en full sidomladdning. Omatchade fallback-IF-rader sparas nu också direkt via AJAX med lokal busy-/success-status under radens knapp, och radering tar bort raden direkt samt återställer tomläget när sista raden tas bort.
Viktig prioritetsregel:
- mailboxnivåns generiska AI-inställningar används bara när ingen regel matchade mailet
- fallbacken för omatchade mail aktiveras nu bara av mailboxens checkbox i Tools-konfigurationen; miljöflaggor räcker inte längre för att slå på den
- om den checkboxen är avstängd får standalone-klienten inte utvärdera några avancerade no-match-rader eller mailboxens sista fallback alls, även om äldre IF-/instruktionstexter fortfarande råkar vara ifyllda
- AI för omatchade mail körs nu först som ett strikt JSON-beslut: standalone-klienten skickar bara svar när AI uttryckligen returnerar ett strukturerat tillåt-beslut med hög säkerhet
- om det varken finns aktiva no-match-rader eller mailboxens egen sista allow-condition/instruktion räknas no-match-AI som ofullständigt konfigurerad och inget fallbacksvar skickas
- no-match-rader körs i
sort_order-ordning och kan falla vidare till senare rader om en tidigare rad avvisas
- efter dessa avancerade rader kan mailboxens egen sista fallback fortfarande köras som sista omatchade väg när checkboxen är aktiv och båda textfälten är ifyllda
- samma fall-through gäller nu också när en enskild no-match-rad träffar ett radlokalt AI-/API-fel; standalone-runnern loggar den felande raden men fortsätter ändå med senare aktiva rader innan den ger upp
- om flera regler matchar samma inkommande mail utvärderar standalone-klienten nu alla matchande regler och väljer först den mest specifika regeln (flest aktiva matchfält, sedan längst sammanlagd matchtext, därefter
sort_order)
- den valda regeln och övriga matchande kandidater sparas nu i standalone-diagnostiken så regelkrockar kan granskas i efterhand
- om en matchad regel har
ai_enabled=true skickar standalone-klienten nu regelns responder/persona/custom instruction/modell/reasoning till Tools som explicita AI-override-fält för just det svaret
- den statiska templaten används bara som fallback om AI-anropet misslyckas eller returnerar ett tomt/icke-användbart svar
- skippade eller obesvarade olästa mail trycks nu också uttryckligen tillbaka till oläst när IMAP-servern stöder att
\\Seen rensas, vilket minskar att fetches råkar lämna fel read-state efter sig
- lokal message-state kan nu också spara lätta tråd-/konversationsutdrag så senare AI-svar kan fortsätta en konversation mer naturligt utan att den historiken används som dedupe-gate
- när
In-Reply-To / References länkar ett uppföljningsmail till en tidigare hanterad konversation kan standalone-runnern nu också återanvända den tidigare matchade regeln eller prioritera den tidigare använda no-match-raden så tråden hålls kvar på samma supportspår
- standalone-genererade svar sparar nu också ett genererat utgående
reply_message_id i lokal state, vilket gör att senare Gmail-/Outlook-följdmail lättare kan kopplas tillbaka till samma konversation även när användaren svarar på assistentens skickade mail i stället för originalmailet
- standalone-genererade svar kan nu också stämpla in ett stabilt ärende-/case-id i ämnesraden (standardformat ungefär
[Ärende MSA-ABC12345]), och senare svar i samma tråd återanvänder samma tagg i stället för att appenda ett nytt ärende-id varje gång konversationen besvaras
- standalone-genererade HTML-svar konverterar nu också vanlig markdown från AI-/operatörstext till riktig HTML-struktur (till exempel rubriker, listor, länkar, betoning och inline-kod) i stället för att visa råa markdown-markörer i det stylade svaret
- om ett uppföljningsmail kommer i ett äldre/trasigare format där användbara
In-Reply-To / References saknas kan standalone-runnern nu ändå prova en fallback via normaliserat subject + samma deltagare innan mailet behandlas som en helt ny no-match-konversation
- om den länkade tidigare konversationen redan godkänts via no-match-AI kan standalone-runnern nu fortsätta direkt på samma tidigare använda no-match-rad för uttryckligt länkade följdmail i stället för att köra om det första allow-condition-steget från början på samma tråd
- rate-limitade AI-fel (
429 / Too Many Attempts) försöks nu om automatiskt innan standalone-klienten ger upp AI-svaret för regeln
- om en AI-aktiverad regel saknar explicit
template_text-fallback skickar standalone-klienten inte längre den gamla generiska meningen Thank you for your message. We have reviewed it. när AI fallerar; svaret avbryts i stället och felet loggas
- klartextmail från kontaktformulär som innehåller body-labels som
From:, Subject:, Sender IP: och Message Body: bevarar nu också själva problemtexten i standalone-sammanfattningar/AI-kontext i stället för att falla ner till bara den första headerliknande raden
- HTML-baserade inkommande mail dekodas nu också till läsbar plain text innan regelmatchning, AI-triage för omatchade mail, bifogade request-sammanfattningar och sparade lokala message copies byggs, så standalone-klienten inte längre beter sig som om bara subject fanns när body kom som HTML
- MIME-bodydekodningen är nu charset-medveten, vilket gör att icke-UTF8 eller på annat sätt trasiga inkommande mail oftare ger användbar body-text i stället för förvanskad AI-/regelmatchningskontext
- multipart-baserade inkommande mail väljer nu också den rikaste läsbara MIME-delen i stället för att alltid behålla första icke-tomma delen, vilket minskar fallen där en kort wrapper- eller stubtext tidigare dolde nästan hela den riktiga bodyn
- när den strikta omatchade fallbacken faktiskt skickar ett svar markerar standalone-runnern mailet som läst direkt så att det inte plockas upp igen av pollningen av olästa mail
Den genererade tokenen sparas som en personlig api_keys-rad och markeras automatiskt som AI-kapabel (is_ai=1).
Direktutkast på ärendesidan i Tools
På den trådade ärendesidan i Tools är direkt-svarsboxen nu avsiktligt uppdelad i fyra operatörsfält:
- Instruction / operator note – huvudinstruktionen för just detta svar
- Mood / tone – en tillfällig ton för detta utkast, till exempel
kort, tydlig, fast
- Model – explicit AI-modell för just detta genererade utkast
- Reasoning effort – explicit resonemangsnivå för just detta genererade utkast
Viktigt beteende:
- dessa tre utkastskontroller påverkar bara utkastgenereringen; de skriver inte permanent över mailboxregelns config
- den slutliga svarstexten kan fortfarande redigeras fritt före skickning
- Tools normaliserar nu hälsning och avslutning automatiskt både på genererade utkast och på det slutligt skickade svaret, så ett saknat
Hej/Hello eller en tappad footer läggs tillbaka före utskick
- den automatiska normaliseringen är tänkt att täcka oavsiktliga bortfall, inte att hindra operatören från att justera själva mitteninnehållet i svaret
Relay-token (provider_mail_support_assistant_mailer) är personliga icke-globala nycklar och är avsedda endast för
POST /api/mail-support-assistant/send-reply. De är inte AI-mottagartokens.
Webbgränssnittet använder nu också mer generiska exempelvärden för vanliga supportflöden, till exempel orderstatus, referensnummer och allmän kundsupport, i stället för specialfallsliknande juridik- eller copyrightexempel.
Trådad ärendespårning
- Tools lagrar nu synkade Mail Support Assistant-konversationer som trådade supportärenden.
- Adminoperatörer kan granska dem direkt från
/admin/mail-support-assistant och därifrån öppna en separat trådad ärendesida.
- Standalone-runnern trycker nu också in varje relevant upptäckt oläst mail i den trådade Tools-vyn direkt när mailet hittas, så operatören fortfarande kan bygga regler eller begära ett manuellt AI-svar senare även när assistenten inte svarade under just den körningen.
- Trådar vars senaste utfall blev omatchat, skippat eller "reply not sent" ligger nu kvar där som tydliga uppföljningsärenden i stället för att bara synas i standalone-diagnostiken för senaste körningen.
- Den trådade ärendesidan kan nu också visa centralt lagrad full body-text/HTML samt vilken runner/server som synkade respektive meddelande.
- Samma trådade ärendesida kan nu också generera AI-utkast från en operatörsinstruktion, skicka det färdiga svaret direkt via Tools eller markera ärendet som manuellt hanterat utan outbound-svar.
- När ett skippat / omatchat /
reply not sent-ärende har lämnats över framgångsrikt till Tools som needs_attention kan standalone-runnern nu markera det mailboxmailet som läst, så uppföljningen centreras i Tools i stället för att mailet återförsökas som oläst om och om igen.
- Standalone-dashboarden kan också länka varje meddelandekort tillbaka till motsvarande Tools-ärende när tråden redan hunnit synkas.
- Utgående assistentsvar kan nu också bifoga en publik ärendelänk till mottagaren när standalone-runtime först lyckas skapa den länken i Tools.
- Den synkvägen kör nu också även när standalone-runnern inte kunde bygga någon stabil lokal message-state-nyckel, så hanterade eller ignorerade mail fortfarande ska dyka upp i Tools i stället för bara i den lokala runtime-miljön.
- Admin kan nu radera en enskild synkad tråd från ärendelistan eller ärendedetaljen, och ärendelistan innehåller också ett bulkstädformulär för äldre synkade trådar som inte längre behövs.
- Adminoperatörer kan nu också lägga återkommande avsändare i en mailboxnivålista för ignored senders direkt från den trådade ärendesidan, recent-case-korten eller mailboxsektionen på
/admin/mail-support-assistant.
- När en avsändare ignoreras på det sättet kan operatören samtidigt välja att radera redan lagrade synkade trådar för samma mailbox/avsändare.
- Standalone-runnern får nu samma ignore-lista via Tools-configen och skippar framtida mail från de avsändaradresserna direkt i stället för att skapa nya follow-up-ärenden för dem.
Synlighet i standalone-inkorgen
- Standalone-dashboarden är fortfarande inte tänkt att ersätta full mailboxadministration, men den kan nu också blanda in en live-preview av olästa IMAP-mail i aktivitetspanelen.
- Det betyder att olästa mail nu kan dyka upp i assistentens webbgränssnitt även innan en ny sparad latest-run-sammanfattning har skrivits.
- Tools admin visar den synkade/trådade ärendevyn; standalone-dashboarden visar den lokala live-previewen av olästa mail plus latest-run/manualhantering.
- Standalone-dashboarden renderar nu också först ett lättviktigt skal och laddar därefter tyngre Tools-config + live-preview av olästa IMAP-mail direkt efter första page paint, så inloggningen inte längre måste vänta på att hela dashboardbygget blir klart innan sidan syns.
Valfri rapport över obesvarade mail
- Standalone kan nu skicka ett sammanfattningsmail efter en körning med vilka meddelanden som inte besvarades.
- Aktivera det med:
MAIL_ASSISTANT_UNANSWERED_REPORT_ENABLED=true
MAIL_ASSISTANT_UNANSWERED_REPORT_TO=user@example.com[,second@example.com]
- Rapporten är avsedd för operatörsuppföljning och stoppar inte körningen även om själva rapportmailet misslyckas.
Nya API-endpoints som standalone-klienten använder
GET /api/mail-support-assistant/cases
- Auth: samma personliga AI-kapabla tokenmodell som
GET /api/mail-support-assistant/config
- Syfte: hämta nyligen lagrade Tools-ärenden som är synliga för tokenägaren
POST /api/mail-support-assistant/cases/sync
- Auth: samma personliga AI-kapabla tokenmodell som
GET /api/mail-support-assistant/config
- Syfte: låta standalone-klienten uppdatera ett inkommande/utgående supporttrådssnapshot tillbaka till Tools
- Vanliga payloadfält:
mailbox_id, message_id, message_key, reply_issue_id, thread_key, subject, from, to, status, reason, additiva headers_raw, additiva headers_map, additiva body_text_raw, additiva body_text, additiva body_text_reply_aware, additiva body_html, body_excerpt, valfritt reply_message_id, additiva reply_body_text, additiva reply_body_html och valfritt reply_excerpt
Eftersom den fristående klienten hämtar mailbox- och regelkonfiguration direkt från Tools med bearer-token räcker det i många installationer med CLI-runner eller cronjobb. Den lilla PHP-dashboarden är valfri och behöver normalt inte exponeras publikt.
Samma CLI-/dashboard-runner är nu också overlapsäker: varje körning tar en lokal icke-blockerande låsfil under storage/state/run.lock, så om cron eller dashboarden försöker starta en ny körning medan en annan redan arbetar hoppar det andra försöket över direkt med runner_already_active i stället för att samma olästa mailbox pollas dubbelt.
Shell-wrappern cron-run.sh håller nu dessutom en egen PID-medveten låskatalog (standard storage/state/cron-run.lock.d) med städning av stale-lås, så överlappande cronkörningar kan stoppas redan innan PHP-runnern startar. Den shell-låsvägen kan överskrivas via MAIL_ASSISTANT_CRON_LOCK_DIR när flera installationer delar samma filsystem.
Den fristående dashboarden är nu också mer operatörsvänlig än tidigare:
- senaste körningen visas som mailbox-/meddelandekort i stället för bara råa JSON-block
- konfigurerade mailboxkort visas nu där även innan någon dry-run eller riktig körning hunnit spara meddelandeaktivitet, med en tydlig not om att detta är en operatörsvy för senaste körningen och inte någon full live-IMAP-klient
- varje meddelande kan expandera tråddiagnostik, vald regel/no-match-resonemang och valfri lokal header-/body-preview när en cachad message copy finns
- runnern uppdaterar nu också en stabil lokal message copy för varje skannat mail, så dashboarden/manualhanteringen behåller läsbar body-text mer tillförlitligt i stället för att vara beroende av kortare latest-run-utdrag
- den första dashboardrenderingen är nu också avsiktligt lättare: sidans skal visas först och de tyngre Tools-config-/live-IMAP-panelerna hämtas direkt därefter, vilket gör inloggning och manuell refresh snabbare på trögare IMAP-/Tools-hostar
- operatören kan nu också agera direkt på senaste körningens meddelanden i dashboarden: välja lokal regelkontext, skicka manuellt svar eller markera meddelandet som manuellt hanterat/läst utan att vänta på nästa cronpass
- manuella svar använder samma multipart plain-text + stylade HTML-svarspipeline som automatiska svar, så operatörens manuella svar får samma synliga format och samma request-summary-beteende
- Tools-konfigurationen sammanfattas nu i en mer läsbar mailbox-/regelöversikt, och dashboarden visar nu även läsbara matchade regelrader, omatchade AI/IF-rader (inklusive footer/modell/reasoning) samt mailboxnivåns ignored senders samtidigt som rå JSON fortfarande finns kvar i kollapsbara advanced-sektioner
- tydliga alertkort visar nu både Tools-sidans dagliga AI-budgettryck (när den metadata finns i config) och standalone-upptäckta quota-/billingfel från senaste körningen
Dashboarden ska fortfarande ses som en lightweight operatörsyta, inte som en full ersättning för det riktiga admin-UI:t i Tools.
Token för standalone-klienten
Den fristående PHP-klienten ska använda en personlig bearer-token, till exempel:
provider_mail_support_assistant
Viktiga regler:
- mottagar-/klienttoken som pratar till Tools för OpenAI:s räkning ska sparas med
is_ai=1
- den uppströms
provider_openai-secret som Tools använder mot OpenAI är inte en mottagartoken och utesluts automatiskt från is_ai
- om en regel har AI aktiverat måste tokenägaren fortfarande ha godkänd
provider_openai-access, om användaren inte är admin
API-endpoint för standalone-klienten
GET /api/mail-support-assistant/config
Auth:
Authorization: Bearer <personlig AI-kapabel token>
X-Api-Key: <personlig AI-kapabel token>
apikey=<personlig AI-kapabel token>
Förväntad tokenmodell:
- personlig icke-global nyckel
- aktiv
- AI-kapabel (
is_ai=1) eller äldre tools_ai_bearer
Lyckat svar:
{
"ok": true,
"message": "Mail Support Assistant config loaded.",
"user": {
"id": 1,
"name": "Admin User",
"email": "admin@example.com",
"has_openai_access": true,
"ai_daily_budget": {
"feature": "social_media_extension",
"default_model": "gpt-4o-mini",
"max_output_tokens_default": 800,
"cap": 60000,
"used": 4200,
"remaining": 55800,
"is_unlimited": false,
"source": "user_override"
}
},
"token": {
"provider": "provider_mail_support_assistant",
"user_id": 1,
"is_personal": true,
"is_ai": true
},
"mailboxes": [
{
"defaults": {
"spam_score_reply_threshold": 6.5,
"generic_no_match_ai_enabled": true,
"generic_no_match_ai_model": "gpt-4o-mini",
"generic_no_match_ai_reasoning_effort": "medium",
"generic_no_match_if": "Om det omatchade mailet är en normal supportfråga och tydligt inte är spam, bedrägeri, phishing eller vag säljkontakt får sista fallbacken svara.",
"generic_no_match_instruction": "Svara kort, be om den saknade kontodetaljen och håll dig till avsändarens ursprungliga språk.",
"generic_no_match_footer": "Med vänliga hälsningar",
"ignored_senders": [
{
"id": 77,
"email": "ignoreme@example.com",
"label": "Ignore Me <ignoreme@example.com>",
"notes": "Återkommande avsändare som operatören valt att ignorera"
}
],
"generic_no_match_rules": [
{
"id": 41,
"sort_order": 0,
"is_active": true,
"if": "Om det omatchade mailet är ett oombett säljerbjudande ska vi tacka nej.",
"instruction": "Avböj vänligt och bjud inte in till fortsatt kontakt.",
"footer": "Med vänliga hälsningar",
"ai_model": "gpt-4o-mini",
"ai_reasoning_effort": "medium"
}
]
}
}
]
}
Fel:
401 om bearer-token saknas eller nekas
POST /api/mail-support-assistant/send-reply
Syfte:
- relay:a ett utgående svar via Tools mailtransport när standalone-klienten inte kan eller ska använda lokal
mail()/MTA.
Auth:
- dedikerad personlig token med provider
provider_mail_support_assistant_mailer
- tokenägaren måste ha permission
mail-support-assistant.relay (admin bypass gäller)
Body (exempel):
{
"mailbox_id": 5,
"rule_id": 11,
"mode": "fallback_after_php_mail",
"to": "customer@example.com",
"cc": [],
"bcc": ["audit@example.com"],
"from": "Support Team <support@example.com>",
"subject": "Re: Order status",
"body": "Tack för ditt meddelande.",
"body_html": "<html><body><p>Tack för ditt meddelande.</p></body></html>",
"message_meta": {
"message_id": "<abc@example.com>",
"uid": 12345
}
}
Lyckat svar:
{
"ok": true,
"message": "Reply relayed via Tools mail transport.",
"relay": {
"provider": "provider_mail_support_assistant_mailer",
"user_id": 1,
"mailbox_id": 5,
"rule_id": 11,
"mode": "fallback_after_php_mail"
}
}
Fel:
401 om relay-token saknas/är ogiltig/inaktiv
403 om tokenägaren saknar mail-support-assistant.relay
422 vid ogiltiga payloadfält
Additivt relay-fält:
body_html är valfritt.
- När det skickas med relay:ar Tools svaret som
multipart/alternative med både den ursprungliga plain-text-delen i body och HTML-delen i body_html.
- Om fältet utelämnas behålls det tidigare plain-text-beteendet i relayläget.
- Relay stämplar nu också utgående svar med
X-Tornevall-Mail-Assistant: sent för anti-loop-detektering i standalone-pollning.
Driftnoteringar
- Mailboxar/regler konfigureras i Tools, men själva IMAP-pollningen och reply-körningen är tänkt att köras från den fristående klienten/cronjobbet.
- Mailboxuppgifter ligger i Tools admin; den fristående klienten är fortfarande databaslös lokalt och sparar bara env/session/logg/sammanfattningsdata plus valfria lokala meddelandekopior under
storage/.
- Standalone-svarstransporten är nu SMTP-först som standard (
MAIL_ASSISTANT_MAIL_TRANSPORT=smtp) och kan styras med MAIL_ASSISTANT_SMTP_*-nycklar, så lokal Postfix/sendmail inte längre krävs i normalfallet.
- För WSL-/self-signed-/lokal-CA-miljöer kan standalone nu också slå av eller styra om TLS-verifiering separat för Tools API-anrop (
MAIL_ASSISTANT_TOOLS_SSL_VERIFY, MAIL_ASSISTANT_TOOLS_CA_BUNDLE) och SMTP (MAIL_ASSISTANT_SMTP_SSL_VERIFY, MAIL_ASSISTANT_SMTP_CA_FILE).
- Om varken den matchade regeln eller mailboxens defaults anger någon BCC-mottagare kan standalone nu också falla tillbaka till
MAIL_ASSISTANT_DEFAULT_BCC i sin lokala .env.
- Standalone-svarstransporten stöder nu också en explicit ordnad fallbackkedja via
MAIL_ASSISTANT_MAIL_FALLBACK_TRANSPORTS.
- Om primär transport är
tools_api men den dedikerade relay-token saknas hoppar runnern nu över relayläget och fortsätter med SMTP/lokala fallbacktransporter i stället för att avbryta hela svaret.
- Om SMTP/lokal transport fallerar och fallback är aktiverad kan runnern försöka igen via
POST /api/mail-support-assistant/send-reply.
- Utgående svar från standalone-runtime genereras nu som
multipart/alternative: en plain-text-del finns alltid kvar för kompatibilitet, och en stylad HTML-version läggs till för mailklienter som föredrar rikare formatering.
- Den stylade HTML-delen renderar nu också vanlig markdown från AI-/operatörstext till riktig HTML i stället för att visa markdown-syntax direkt i det synliga mailet.
- I statiskt footerläge rensar standalone nu bort trailing AI-genererade signoff-block innan den konfigurerade footern läggs till, vilket förhindrar dubbla avslut som både
Best regards och Regards i samma svar.
- Standalone behandlar nu inkommande olästa mail med
X-Tornevall-Mail-Assistant: sent som assistant-originerade loopkandidater: de hoppas över före regelmatchning/svar och markeras lästa för att undvika återkommande självsvarsloopar.
- Om ingen regel matchar ett mail ska klienten lämna det helt orört.
- När mailboxnivåns AI-fallback för omatchade mail är aktiverad i Tools admin kan standalone-klienten i stället köra en strikt AI-triage via de additiva
defaults.generic_no_match_*-fälten från /api/mail-support-assistant/config.
- Mailboxens
generic_no_match_if / generic_no_match_instruction beskriver nu mailboxens egen sista fallback och är inte längre alias för den första avancerade omatchade raden.
- Avancerade omatchade rader ligger fortsatt i
defaults.generic_no_match_rules[] och kontrolleras fortfarande före den sista mailboxfallbacken.
- Mailboxnivåns ignoreringar visas nu också additivt i
defaults.ignored_senders[]; standalone-klienter kan använda den listan för att hoppa över återkommande avsändaradresser innan mailet synkas tillbaka till Tools som ett nytt follow-up-ärende.
- Dessa additiva mailboxdefaults kan nu också innehålla
defaults.generic_no_match_ai_reasoning_effort.
- Dessa additiva mailboxdefaults kan nu också innehålla
defaults.generic_no_match_if.
- AI instrueras nu att bortse från yttre SpamAssassin-wrappertext när den bara kapslar in originalmailet, samtidigt som SpamAssassin-score/tester fortfarande används som risksignaler.
- Svar på omatchade mail skickas nu bara när AI returnerar giltig JSON,
can_reply=true, certainty="high" och en icke-tom reply-payload. Allt annat lämnar mailet orört.
- Standalone-parsern för omatchade mail tolererar nu också några vanliga mindre JSON-formatfel från provider/modell (till exempel smart quotes eller trailing commas) innan svaret slutligen klassas som ogiltig JSON.
- Om denna strikta omatchade fallback verkligen skickar ett svar finaliserar runnern mailet genom att markera det som läst direkt (förutom vid dry-run).
- Standalone-diagnostiken för den no-match-vägen innehåller nu också
generic_ai_decision.evaluated_no_match_rules[], så operatören kan se vilka fallback-rader som faktiskt provades, i ordning, innan ett svar skickades eller mailet lämnades oläst.
- Per-message-diagnostik i körresultatet visar nu också
thread_key, in_reply_to och references[], vilket gör det lättare att se om ett skippat mail faktiskt bar med sig användbar reply-chain-metadata.
- Matchade AI-aktiverade regler använder nu
reply.responder_name, reply.persona_profile, reply.custom_instruction, reply.ai_model och additiva reply.ai_reasoning_effort som auktoritativa AI-override-värden för just det svaret i stället för att se ut som ett vanligt statiskt autosvar.
- Standalone-klienten försöker nu också igen när tillfälliga AI-rate-limitfel inträffar innan den överger AI-spåret.
- Standalone-AI-svar försöker nu också uttryckligen svara på samma språk som det inkommande mailet (
response_language=auto) om inte avsändaren tydligt ber om ett annat språk.
- Standalone-fallbackmodellen är nu
o4 som standard; den fallbackkörningen skickar medvetet inte reasoning_effort, så o4 används här som en vanlig icke-reasoning fallback.
GET /api/mail-support-assistant/config kan nu också exponera additiv metadata i user.ai_daily_budget så standalone-klienten/operatören kan se effektiv daglig AI-tokenlimit, återstående budget, defaultmodell och standardgräns för output-tokens som Mail Support Assistants SocialGPT-baserade svar använder.
- Om en AI-aktiverad matchad regel fortfarande fallerar efter retries och ingen explicit
reply.template_text-fallback finns konfigurerad lämnas svaret nu oskickat och felet loggas, i stället för att en missvisande generisk standardsvarstext skickas.
- Mailbox-/runnerfel från dessa misslyckade AI-svar innehåller nu också vilken modellkedja som faktiskt provades, vilket gör tomma svar/fallbackproblem lättare att felsöka.
- Om ett mail hoppas över därför att ingen regel matchar, eller därför att den generiska fallbacken för omatchade mail är avstängd, ofullständigt konfigurerad, underkänd som osäker, ogiltig, tom eller i övrigt fallerar, lämnas mailet nu oläst även om
mark_seen_on_skip är aktiverat.
- Undantag: när den strikta AI-/slutfallbacken för omatchade mail faktiskt har utvärderats men landar i ett terminalt reject-/error-utfall markerar standalone-runnern nu mailet som läst för manuell uppföljning, så samma olästa mail inte fortsätter att bränna AI-försök i all evighet.
- Quota-/billingfel från AI-mailflöden lyfts nu också upp som tydliga runtime-alerts och kan valfritt skicka cooldown-begränsad operatörsnotis via
MAIL_ASSISTANT_QUOTA_ALERT_EMAIL i standalone-miljön.
mark_seen_on_skip ska därför främst ses som en bekvämlighetsinställning för medvetna heuristiska skippar, till exempel högscorat SpamAssassin-skräp, och inte som ett sätt att tysta konfigurationsdrivna no-match-mail.
- Den fristående runnern pollar bara olästa mail. Mail som redan är markerade lästa vid inläsning hoppas över direkt.
- Den lokala filen
storage/state/message-state.json är nu bara diagnostikhistorik. Ett oläst mail kan alltså fortfarande omprövas i en senare körning även om samma Message-Id redan finns i filen, vilket gör att nya regler kan börja gälla utan att lokal state först rensas.
- Samma lokala state kan ändå användas som kontinuitetshjälp för reply-kedjor: den kan återhämta tidigare vald regel eller tidigare matchad no-match-rad för ett länkat uppföljningsmail, men den får aldrig i sig själv blockera omprövning av oläst mail.
- Den kontinuitetsuppslagningen förstår nu också sparade utgående
reply_message_id-värden och kan falla tillbaka till normaliserat subject + samma deltagare när explicita reply-headers gått förlorade i ett äldre mailformat eller vid någon mellanliggande omskrivning.
- AI ska bara aktiveras per regel när du uttryckligen vill att Tools/OpenAI ska blandas in.
- Den fristående klienten tittar nu också på SpamAssassin-headers så att mycket högscorat skräppost kan hoppas över försiktigare, medan wrapper-liknande SpamAssassin-omskrivningar fortfarande kan kopieras lokalt och rensas bort innan regelmatchning eller AI-svar.
- Mailbox-defaults kan nu också innehålla
spam_score_reply_threshold; när ett mail har score över den nivån undertrycker standalone svarshantering för mailet och lämnar det oläst.
- Score-tolkningen läser nu också
X-Spam-Score direkt när X-Spam-Status saknar en parsebar score=-token.
- Utgående svar lägger nu också till ett kompakt utdrag av den ursprungliga förfrågan, och wrapper-liknande felmail rensas nu hårdare först så vidarebefordrade
.eml-headerdumpningar eller SpamAssassin-wrappers inte blir den synliga citerade sammanfattningen.