From a9221f2d655f8c2d8db64ed5c0257d08877a8e97 Mon Sep 17 00:00:00 2001 From: alma Date: Tue, 15 Apr 2025 23:42:43 +0200 Subject: [PATCH] mail page imap connection mime 5 bis rest 16 login page 5 --- app/api/mail/route.ts | 182 +++++++++++++++++++++++++++++++++++------- app/mail/page.tsx | 9 ++- 2 files changed, 159 insertions(+), 32 deletions(-) diff --git a/app/api/mail/route.ts b/app/api/mail/route.ts index be42cf7..d16a1c5 100644 --- a/app/api/mail/route.ts +++ b/app/api/mail/route.ts @@ -83,6 +83,43 @@ interface ImapError extends Error { source?: string; } +interface Email { + id: string; + from: string; + subject: string; + date: string; + body: string; + read: boolean; + starred: boolean; +} + +interface EmailHeaders { + from: string; + subject: string; + date: string; +} + +function parseEmailHeaders(buffer: string): EmailHeaders { + const headers: EmailHeaders = { + from: '', + subject: '', + date: '' + }; + + const lines = buffer.split('\r\n'); + for (const line of lines) { + if (line.toLowerCase().startsWith('from:')) { + headers.from = line.substring(5).trim(); + } else if (line.toLowerCase().startsWith('subject:')) { + headers.subject = line.substring(8).trim(); + } else if (line.toLowerCase().startsWith('date:')) { + headers.date = line.substring(5).trim(); + } + } + + return headers; +} + // Helper function to create a promise-based IMAP connection function createImapConnection(imapConfig: Imap.Config) { return new Promise((resolve, reject) => { @@ -191,11 +228,27 @@ function fetchMessages(imap: Imap, box: string): Promise { }); } -export async function GET(request: Request) { +export async function GET() { + console.log('Starting email fetch process...'); + try { - console.log('Starting email fetch process...'); - - const imapConfig = getImapConfig(); + const credentials = getStoredCredentials(); + if (!credentials) { + return NextResponse.json( + { error: 'No credentials found', details: 'Please login first' }, + { status: 401 } + ); + } + + const imapConfig = { + user: credentials.email, + password: credentials.password, + host: credentials.host, + port: credentials.port, + tls: true, + debug: console.log + }; + console.log('IMAP Configuration:', { user: imapConfig.user, host: imapConfig.host, @@ -204,38 +257,105 @@ export async function GET(request: Request) { hasPassword: !!imapConfig.password }); - console.log('Creating IMAP connection...'); - const imap = await createImapConnection(imapConfig) as Imap; + const imap = new Imap(imapConfig); - console.log('Fetching messages...'); - const messages = await fetchMessages(imap, 'INBOX'); - - console.log(`Successfully fetched ${messages.length} messages`); - - // Process messages into the format expected by the frontend - const processedMessages = messages.map((msg: ImapMessage, index: number) => ({ - id: index + 1, - accountId: 1, - from: msg.header.from?.[0] || '', - fromName: (msg.header.from?.[0] || '').split('<')[0].trim(), - to: msg.header.to?.[0] || '', - subject: msg.header.subject?.[0] || '', - body: msg.body || '', - date: msg.header.date?.[0] || new Date().toISOString(), - read: !(msg.attributes.flags.indexOf('\\Seen') < 0), - starred: !(msg.attributes.flags.indexOf('\\Flagged') < 0), - category: 'inbox' - })); + return new Promise((resolve, reject) => { + imap.once('ready', () => { + console.log('IMAP connection ready'); + imap.openBox('INBOX', false, (err, box) => { + if (err) { + console.error('Error opening inbox:', err); + imap.end(); + reject(new Error('Failed to open inbox')); + return; + } - imap.end(); - return NextResponse.json({ messages: processedMessages }); + const fetch = imap.seq.fetch('1:10', { + bodies: ['HEADER', 'TEXT'], + struct: true + }); + const messages: Email[] = []; + + fetch.on('message', (msg) => { + const email: Email = { + id: '', + from: '', + subject: '', + date: '', + body: '', + read: false, + starred: false + }; + + msg.on('body', (stream) => { + let buffer = ''; + stream.on('data', (chunk) => { + buffer += chunk.toString('utf8'); + }); + stream.on('end', () => { + const headers = parseEmailHeaders(buffer); + email.from = headers.from; + email.subject = headers.subject; + email.date = headers.date; + }); + }); + + msg.once('attributes', (attrs) => { + email.id = attrs.uid.toString(); + email.read = !attrs.flags.includes('\\Unseen'); + email.starred = attrs.flags.includes('\\Flagged'); + }); + + msg.once('end', () => { + messages.push(email); + }); + }); + + fetch.once('error', (err) => { + console.error('Fetch error:', err); + imap.end(); + reject(new Error('Failed to fetch messages')); + }); + + fetch.once('end', () => { + imap.end(); + resolve(NextResponse.json(messages)); + }); + }); + }); + + imap.once('error', (err: ImapError) => { + console.error('IMAP connection error:', err); + console.error('Error details:', { + type: err.type, + textCode: err.textCode, + source: err.source + }); + imap.end(); + reject(new Error(err.message)); + }); + + imap.connect(); + }); } catch (error) { console.error('Error in GET handler:', error); - return NextResponse.json({ - error: 'Failed to fetch emails', - details: error instanceof Error ? error.message : 'Unknown error' - }, { status: 500 }); + if (error instanceof Error) { + if (error.message.includes('Invalid login or password')) { + return NextResponse.json( + { error: 'Invalid login or password', details: error.message }, + { status: 401 } + ); + } + return NextResponse.json( + { error: 'Failed to fetch emails', details: error.message }, + { status: 500 } + ); + } + return NextResponse.json( + { error: 'Unknown error occurred' }, + { status: 500 } + ); } } diff --git a/app/mail/page.tsx b/app/mail/page.tsx index d100e38..d562486 100644 --- a/app/mail/page.tsx +++ b/app/mail/page.tsx @@ -435,7 +435,14 @@ export default function MailPage() { try { const response = await fetch('/api/mail'); if (!response.ok) { - throw new Error('Failed to fetch emails'); + const errorData = await response.json(); + if (errorData.error === 'Invalid login or password') { + // Clear invalid credentials and redirect to login + localStorage.removeItem('imapCredentials'); + router.push('/mail/login'); + return; + } + throw new Error(errorData.details || 'Failed to fetch emails'); } const data = await response.json(); console.log('API Response:', data); // Debug log