From 99927aea0bdf95dd1303507d2cd431f31a1bf2d3 Mon Sep 17 00:00:00 2001 From: ogrechko Date: Mon, 7 Sep 2026 05:22:29 +0000 Subject: [PATCH] Stop merging unrelated emails into a customer's other open ticket Inbound email with no In-Reply-To/References match against a tracked message now always opens a new ticket, instead of falling back to the customer's most recent open ticket. That fallback made sense for Telegram/website chat (no subject, single running stream) but was wrong for email, where an unrelated new request from a repeat customer got silently appended to whatever ticket happened to still be open. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01Gh2UXUQUVBWroWEnn1FLFG --- src/lib/tickets/service.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/lib/tickets/service.ts b/src/lib/tickets/service.ts index 2e60e5c..778a29c 100644 --- a/src/lib/tickets/service.ts +++ b/src/lib/tickets/service.ts @@ -310,10 +310,12 @@ export async function recordChatInboundMessage(params: { } /** - * Records an inbound email. Prefers exact thread matching via - * In-Reply-To/References (so a reply to a specific closed ticket lands on - * that ticket, not a random other open one); falls back to the same - * find-or-create-open-ticket heuristic used for Telegram. + * Records an inbound email. Threads it onto an existing ticket only via + * exact In-Reply-To/References matching. Unlike Telegram/the website widget + * (a continuous chat stream with no subject), email always carries a + * distinct subject per conversation — so a message with no header match is + * always a new, unrelated request and must become its own ticket, even if + * the customer already has another ticket open. */ export async function recordEmailInboundMessage(params: { fromEmail: string; @@ -330,7 +332,7 @@ export async function recordEmailInboundMessage(params: { const matchedTicketId = await findTicketIdByEmailReferences(params.referencedMessageIds); let ticket = matchedTicketId ? await db.query.tickets.findFirst({ where: eq(tickets.id, matchedTicketId) }) - : await findOpenTicketForCustomer(customer.id); + : null; let ticketIsNew = false; if (!ticket) {