From 375db2e7d8bd2ad2d9b73d17b5e413d4cd84445f Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Tue, 28 Oct 2025 20:29:14 +0000 Subject: [PATCH] Fix thread ID matching for email replies --- .../functions/receive-inbound-email/index.ts | 65 +++++++++++++++++-- .../functions/send-contact-message/index.ts | 13 ++-- 2 files changed, 65 insertions(+), 13 deletions(-) diff --git a/supabase/functions/receive-inbound-email/index.ts b/supabase/functions/receive-inbound-email/index.ts index 4d6f4544..cd4f95c8 100644 --- a/supabase/functions/receive-inbound-email/index.ts +++ b/supabase/functions/receive-inbound-email/index.ts @@ -44,8 +44,8 @@ const handler = async (req: Request): Promise => { }); // Extract thread ID from headers or inReplyTo - const threadId = headers['X-Thread-ID'] || - (inReplyTo ? inReplyTo.replace(/<|>/g, '').split('@')[0] : null); + let threadId = headers['X-Thread-ID'] || + (inReplyTo ? inReplyTo.replace(/<|>/g, '').split('@')[0] : null); if (!threadId) { edgeLogger.warn('Email missing thread ID', { @@ -58,17 +58,68 @@ const handler = async (req: Request): Promise => { }); } - // Find submission by thread_id - const { data: submission, error: submissionError } = await supabase + // Extract ticket number from thread_id (handles multiple formats) + // Formats: "TW-100000.uuid", "ticket-TW-100000", "TW-100000" + const ticketMatch = threadId.match(/(?:ticket-)?(TW-\d+)/i); + const ticketNumber = ticketMatch ? ticketMatch[1] : null; + + edgeLogger.info('Thread ID extracted', { + requestId: tracking.requestId, + rawThreadId: threadId, + ticketNumber + }); + + // Find submission by thread_id or ticket_number + let submission = null; + let submissionError = null; + + // Strategy 1: Try exact thread_id match + const { data: submissionByThreadId, error: error1 } = await supabase .from('contact_submissions') - .select('id, email, status') + .select('id, email, status, ticket_number') .eq('thread_id', threadId) - .single(); + .maybeSingle(); + + if (submissionByThreadId) { + submission = submissionByThreadId; + } else if (ticketNumber) { + // Strategy 2: Try ticket_number match + const { data: submissionByTicket, error: error2 } = await supabase + .from('contact_submissions') + .select('id, email, status, ticket_number, thread_id') + .eq('ticket_number', ticketNumber) + .maybeSingle(); + + if (submissionByTicket) { + submission = submissionByTicket; + + // Update thread_id if it's null or in old format + if (!submissionByTicket.thread_id || submissionByTicket.thread_id !== threadId) { + await supabase + .from('contact_submissions') + .update({ thread_id: threadId }) + .eq('id', submissionByTicket.id); + + edgeLogger.info('Updated submission thread_id', { + requestId: tracking.requestId, + submissionId: submissionByTicket.id, + oldThreadId: submissionByTicket.thread_id, + newThreadId: threadId + }); + } + } else { + submissionError = error2; + } + } else { + submissionError = error1; + } if (submissionError || !submission) { edgeLogger.warn('Submission not found for thread ID', { requestId: tracking.requestId, - threadId + threadId, + ticketNumber, + error: submissionError }); return new Response(JSON.stringify({ success: false, reason: 'submission_not_found' }), { status: 200, diff --git a/supabase/functions/send-contact-message/index.ts b/supabase/functions/send-contact-message/index.ts index b01e727a..bab3d3a2 100644 --- a/supabase/functions/send-contact-message/index.ts +++ b/supabase/functions/send-contact-message/index.ts @@ -232,6 +232,13 @@ const handler = async (req: Request): Promise => { } }); + // Update thread_id with Message-ID format (always, not just when email is sent) + const threadId = `${ticketNumber}.${submission.id}`; + await supabase + .from('contact_submissions') + .update({ thread_id: threadId }) + .eq('id', submission.id); + if (forwardEmailKey) { // Send admin notification fetch('https://api.forwardemail.net/v1/emails', { @@ -302,12 +309,6 @@ The ThrillWiki Team`, }).catch(err => { edgeLogger.error('Failed to send confirmation email', { requestId, error: err.message }); }); - - // Update thread_id with ticket number - await supabase - .from('contact_submissions') - .update({ thread_id: `ticket-${ticketNumber}` }) - .eq('id', submission.id); } const duration = Date.now() - startTime;