mail page imap connection mime 5 bis rest 16 login page 5

This commit is contained in:
alma 2025-04-15 23:42:43 +02:00
parent 76ea7ffe66
commit a9221f2d65
2 changed files with 159 additions and 32 deletions

View File

@ -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<ImapMessage[]> {
});
}
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 }
);
}
}

View File

@ -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