mail page connected with folders 6

This commit is contained in:
alma 2025-04-16 17:00:07 +02:00
parent 7cf49d8cf3
commit fd2a4f1483
2 changed files with 91 additions and 112 deletions

View File

@ -91,7 +91,7 @@ function getStoredCredentials(): StoredCredentials | null {
}
}
export async function GET() {
export async function GET(request: Request) {
try {
const credentials = getStoredCredentials();
if (!credentials) {
@ -101,8 +101,10 @@ export async function GET() {
);
}
const availableMailboxes: string[] = [];
const emailsByFolder: { [key: string]: any[] } = {};
// Get the current folder from the URL
const url = new URL(request.url);
const folder = url.searchParams.get('folder') || 'INBOX';
const limit = 50; // Limit number of emails per folder
return new Promise((resolve) => {
const imap = new Imap({
@ -116,7 +118,6 @@ export async function GET() {
connTimeout: 30000
});
// Add a timeout to prevent hanging
const timeout = setTimeout(() => {
console.error('IMAP connection timeout');
imap.end();
@ -124,7 +125,7 @@ export async function GET() {
emails: [],
error: 'Connection timeout'
}));
}, 60000);
}, 30000);
imap.once('error', (err: Error) => {
console.error('IMAP error:', err);
@ -145,133 +146,111 @@ export async function GET() {
return;
}
// Process mailboxes
Object.keys(boxes).forEach((box) => {
availableMailboxes.push(box);
});
const availableMailboxes = Object.keys(boxes);
console.log('Available mailboxes:', availableMailboxes);
// Process each mailbox
const foldersToProcess = availableMailboxes;
let processedFolders = 0;
let activeFetches = 0;
function checkCompletion() {
processedFolders++;
if (processedFolders === foldersToProcess.length && activeFetches === 0) {
// Only process the requested folder
imap.openBox(folder, false, (err, box) => {
if (err) {
console.error(`Error opening box ${folder}:`, err);
clearTimeout(timeout);
finishProcessing();
imap.end();
resolve(NextResponse.json({ emails: [], error: `Failed to open folder ${folder}` }));
return;
}
}
function finishProcessing() {
// Combine all emails from all folders
const allEmails = Object.entries(emailsByFolder).flatMap(([folder, emails]) => emails);
console.log('Emails by folder:', Object.fromEntries(
Object.entries(emailsByFolder).map(([folder, emails]) => [folder, emails.length])
));
console.log('All folders processed, total emails:', allEmails.length);
const response = {
emails: allEmails,
folders: availableMailboxes,
mailUrl: process.env.NEXTCLOUD_URL ? `${process.env.NEXTCLOUD_URL}/apps/mail/` : null
};
imap.end();
resolve(NextResponse.json(response));
}
foldersToProcess.forEach((folderName) => {
// Initialize array for this folder
emailsByFolder[folderName] = [];
imap.openBox(folderName, false, (err, box) => {
// Search for emails in this folder, limited to the most recent ones
imap.search(['ALL'], (err, results) => {
if (err) {
console.error(`Error opening box ${folderName}:`, err);
checkCompletion();
console.error(`Error searching in ${folder}:`, err);
clearTimeout(timeout);
imap.end();
resolve(NextResponse.json({ emails: [], error: `Failed to search in ${folder}` }));
return;
}
// Search for all emails in this folder
imap.search(['ALL'], (err, results) => {
if (err) {
console.error(`Error searching in ${folderName}:`, err);
checkCompletion();
return;
}
if (!results || results.length === 0) {
clearTimeout(timeout);
imap.end();
resolve(NextResponse.json({
emails: [],
folders: availableMailboxes,
mailUrl: process.env.NEXTCLOUD_URL ? `${process.env.NEXTCLOUD_URL}/apps/mail/` : null
}));
return;
}
if (!results || results.length === 0) {
checkCompletion();
return;
}
// Take only the most recent emails up to the limit
const recentResults = results.slice(-limit);
const emails: any[] = [];
activeFetches++;
// Fetch emails
const fetch = imap.fetch(results, {
bodies: ['HEADER', 'TEXT'],
struct: true
const fetch = imap.fetch(recentResults, {
bodies: ['HEADER', 'TEXT'],
struct: true
});
fetch.on('message', (msg) => {
let header = '';
let text = '';
let messageId: number | null = null;
let messageFlags: string[] = [];
msg.once('attributes', (attrs) => {
messageId = attrs.uid;
messageFlags = attrs.flags || [];
});
fetch.on('message', (msg) => {
let header = '';
let text = '';
let messageId: number | null = null;
let messageFlags: string[] = [];
// Handle attributes first
msg.once('attributes', (attrs) => {
messageId = attrs.uid;
messageFlags = attrs.flags || [];
msg.on('body', (stream, info) => {
let buffer = '';
stream.on('data', (chunk) => {
buffer += chunk.toString('utf8');
});
msg.on('body', (stream, info) => {
let buffer = '';
stream.on('data', (chunk) => {
buffer += chunk.toString('utf8');
});
stream.on('end', () => {
if (info.which === 'HEADER') {
header = buffer;
} else if (info.which === 'TEXT') {
text = buffer;
}
});
});
msg.on('end', () => {
if (!messageId) {
console.error('No message ID found for email');
return;
stream.on('end', () => {
if (info.which === 'HEADER') {
header = buffer;
} else if (info.which === 'TEXT') {
text = buffer;
}
const parsedHeader = Imap.parseHeader(header);
const email = {
id: messageId,
from: parsedHeader.from?.[0] || '',
to: parsedHeader.to?.[0] || '',
subject: parsedHeader.subject?.[0] || '(No subject)',
date: parsedHeader.date?.[0] || new Date().toISOString(),
body: text,
folder: folderName,
flags: messageFlags
};
emailsByFolder[folderName].push(email);
});
});
fetch.on('error', (err) => {
console.error(`Error fetching emails from ${folderName}:`, err);
activeFetches--;
checkCompletion();
});
msg.on('end', () => {
if (!messageId) {
console.error('No message ID found for email');
return;
}
fetch.on('end', () => {
activeFetches--;
checkCompletion();
const parsedHeader = Imap.parseHeader(header);
const email = {
id: messageId,
from: parsedHeader.from?.[0] || '',
to: parsedHeader.to?.[0] || '',
subject: parsedHeader.subject?.[0] || '(No subject)',
date: parsedHeader.date?.[0] || new Date().toISOString(),
body: text,
folder: folder,
flags: messageFlags
};
emails.push(email);
});
});
fetch.on('error', (err) => {
console.error(`Error fetching emails from ${folder}:`, err);
clearTimeout(timeout);
imap.end();
resolve(NextResponse.json({ emails: [], error: `Failed to fetch emails from ${folder}` }));
});
fetch.on('end', () => {
clearTimeout(timeout);
imap.end();
resolve(NextResponse.json({
emails: emails,
folders: availableMailboxes,
mailUrl: process.env.NEXTCLOUD_URL ? `${process.env.NEXTCLOUD_URL}/apps/mail/` : null
}));
});
});
});
});

View File

@ -540,7 +540,7 @@ export default function MailPage() {
setLoading(true);
setError(null);
const response = await fetch('/api/mail');
const response = await fetch(`/api/mail?folder=${currentView}`);
if (!response.ok) {
throw new Error('Failed to load emails');
}