diff --git a/app/api/mail/mark-read/route.ts b/app/api/mail/mark-read/route.ts index d306b896..8185d39b 100644 --- a/app/api/mail/mark-read/route.ts +++ b/app/api/mail/mark-read/route.ts @@ -1,7 +1,7 @@ import { NextResponse } from 'next/server'; import { getServerSession } from 'next-auth'; import { authOptions } from '@/app/api/auth/[...nextauth]/route'; -import { getImapClient } from '@/lib/imap'; +import { prisma } from '@/lib/prisma'; import { ImapFlow } from 'imapflow'; export async function POST(request: Request) { @@ -9,7 +9,7 @@ export async function POST(request: Request) { try { // Get the session and validate it const session = await getServerSession(authOptions); - console.log('Session:', session); // Debug log + console.log('Session:', session); if (!session?.user?.id) { console.error('No session or user ID found'); @@ -21,7 +21,7 @@ export async function POST(request: Request) { // Get the request body const { emailId, isRead } = await request.json(); - console.log('Request body:', { emailId, isRead }); // Debug log + console.log('Request body:', { emailId, isRead }); if (!emailId || typeof isRead !== 'boolean') { console.error('Invalid request parameters:', { emailId, isRead }); @@ -34,43 +34,99 @@ export async function POST(request: Request) { // Get the current folder from the request URL const url = new URL(request.url); const folder = url.searchParams.get('folder') || 'INBOX'; - console.log('Folder:', folder); // Debug log + console.log('Folder:', folder); + + // Get credentials directly from database + const credentials = await prisma.mailCredentials.findUnique({ + where: { + userId: session.user.id + } + }); + + if (!credentials) { + return NextResponse.json( + { error: 'No mail credentials found. Please configure your email account.' }, + { status: 401 } + ); + } + + // Create IMAP client + client = new ImapFlow({ + host: credentials.host, + port: credentials.port, + secure: true, + auth: { + user: credentials.email, + pass: credentials.password, + }, + logger: false, + emitLogs: false, + tls: { + rejectUnauthorized: false + }, + disableAutoIdle: true + }); try { - // Initialize IMAP client with user credentials - client = await getImapClient(); - if (!client) { - console.error('Failed to initialize IMAP client'); - return NextResponse.json( - { error: 'Failed to initialize email client' }, - { status: 500 } - ); + await client.connect(); + + // Open the mailbox + const mailbox = await client.mailboxOpen(folder); + console.log(`Mailbox opened: ${folder}, total messages: ${mailbox.exists}`); + + // Scan through messages in chunks to find the one with the right UID + let foundMessage = false; + const chunkSize = 10; + + for (let i = 1; i <= mailbox.exists; i += chunkSize) { + const endIdx = Math.min(i + chunkSize - 1, mailbox.exists); + const range = `${i}:${endIdx}`; + + console.log(`Scanning messages ${range} to find UID ${emailId}`); + + // Fetch messages in chunks with UID + const messages = client.fetch(range, { + uid: true, + flags: true + }); + + for await (const message of messages) { + if (message.uid.toString() === emailId) { + console.log(`Found matching message with UID ${emailId}`); + + // Get the sequence number (i is the start of the range) + const seqNum = i + message.seq - 1; + console.log(`Message sequence number: ${seqNum}`); + + // Update the flags based on the isRead parameter + if (isRead && !message.flags.has('\\Seen')) { + console.log(`Marking message ${emailId} as read`); + await client.messageFlagsAdd(seqNum.toString(), ['\\Seen']); + } else if (!isRead && message.flags.has('\\Seen')) { + console.log(`Marking message ${emailId} as unread`); + await client.messageFlagsRemove(seqNum.toString(), ['\\Seen']); + } else { + console.log(`Message ${emailId} already has the correct read status`); + } + + foundMessage = true; + break; + } + } + + if (foundMessage) { + break; + } } - await client.connect(); - await client.mailboxOpen(folder); - - // Fetch the email to get its UID - const message = await client.fetchOne(emailId.toString(), { - uid: true, - flags: true - }); - - if (!message) { - console.error('Email not found:', emailId); + if (!foundMessage) { + console.error(`Email with UID ${emailId} not found`); return NextResponse.json( { error: 'Email not found' }, { status: 404 } ); } - // Update the flags - if (isRead) { - await client.messageFlagsAdd(message.uid.toString(), ['\\Seen'], { uid: true }); - } else { - await client.messageFlagsRemove(message.uid.toString(), ['\\Seen'], { uid: true }); - } - return NextResponse.json({ success: true }); } finally { if (client) { diff --git a/app/courrier/page.tsx b/app/courrier/page.tsx index 42e06a8f..7ac93298 100644 --- a/app/courrier/page.tsx +++ b/app/courrier/page.tsx @@ -623,7 +623,13 @@ export default function CourrierPage() { // Update handleEmailSelect to set selectedEmail correctly const handleEmailSelect = async (emailId: string) => { try { - // Make sure it's using this: + // First, set partial selectedEmail to show something immediately + const emailToSelect = emails.find(email => email.id === emailId); + if (emailToSelect) { + setSelectedEmail(emailToSelect); + } + + // Then fetch the full content const response = await fetch(`/api/courrier/${emailId}`); if (!response.ok) { @@ -632,17 +638,15 @@ export default function CourrierPage() { const fullEmail = await response.json(); - // Update the email in the list and selected email with full content + // Set the complete selectedEmail with all content + setSelectedEmail(fullEmail); + + // Also update the email in the list setEmails(prevEmails => prevEmails.map(email => email.id === emailId - ? { ...email, content: fullEmail.content || fullEmail.body || email.content } + ? { ...email, read: true } : email )); - - setSelectedEmail(prev => prev ? { - ...prev, - content: fullEmail.content || fullEmail.body || prev.content - } : prev); // Try to mark as read in the background try { @@ -657,16 +661,7 @@ export default function CourrierPage() { }), }); - if (markReadResponse.ok) { - // Only update the emails list if the API call was successful - setEmails((prevEmails: Email[]) => - prevEmails.map((email: Email): Email => - email.id === emailId - ? { ...email, read: true } - : email - ) - ); - } else { + if (!markReadResponse.ok) { console.error('Failed to mark email as read:', await markReadResponse.text()); } } catch (error) {