courrier multi account restore compose

This commit is contained in:
alma 2025-04-28 20:47:09 +02:00
parent 9fa4f807eb
commit 6a7d69ecf8

View File

@ -416,39 +416,56 @@ export async function getEmailContent(
throw new Error('Email ID must be a number'); throw new Error('Email ID must be a number');
} }
// Try to get from cache first // Try to get from cache first, using account-specific cache key
const cachedEmail = await getCachedEmailContent(userId, accountId || folder, emailId); const cacheKey = accountId ? `${accountId}:${folder}` : folder;
const cachedEmail = await getCachedEmailContent(userId, cacheKey, emailId);
if (cachedEmail) { if (cachedEmail) {
console.log(`Using cached email content for ${userId}:${emailId}`); console.log(`Using cached email content for ${userId}:${accountId}:${emailId}`);
return cachedEmail; return cachedEmail;
} }
console.log(`Cache miss for email content ${userId}:${emailId}, fetching from IMAP`); console.log(`Cache miss for email content ${userId}:${accountId}:${emailId}, fetching from IMAP`);
const client = await getImapConnection(userId, accountId); const client = await getImapConnection(userId, accountId);
try { try {
// Remove accountId prefix if present // Remove accountId prefix if present in folder name
const actualFolder = folder.includes(':') ? folder.split(':')[1] : folder; const actualFolder = folder.includes(':') ? folder.split(':')[1] : folder;
// Log connection details // Log connection details with account context
console.log(`[DEBUG] Fetching email ${emailId} from folder ${actualFolder} for account ${accountId}`); console.log(`[DEBUG] Fetching email ${emailId} from folder ${actualFolder} for account ${accountId || 'default'}`);
// Open mailbox with error handling // Open mailbox with error handling
const mailbox = await client.mailboxOpen(actualFolder); const mailbox = await client.mailboxOpen(actualFolder);
if (!mailbox || typeof mailbox === 'boolean') { if (!mailbox || typeof mailbox === 'boolean') {
throw new Error(`Failed to open mailbox: ${actualFolder}`); throw new Error(`Failed to open mailbox: ${actualFolder} for account ${accountId || 'default'}`);
} }
// Log mailbox status // Log mailbox status with account context
console.log(`[DEBUG] Mailbox ${actualFolder} opened, total messages: ${mailbox.exists}`); console.log(`[DEBUG] Mailbox ${actualFolder} opened for account ${accountId || 'default'}, total messages: ${mailbox.exists}`);
// Get the UIDVALIDITY and UIDNEXT values
const uidValidity = mailbox.uidValidity;
const uidNext = mailbox.uidNext;
console.log(`[DEBUG] Mailbox UIDVALIDITY: ${uidValidity}, UIDNEXT: ${uidNext} for account ${accountId || 'default'}`);
// Validate UID exists in mailbox // Validate UID exists in mailbox
if (numericId > mailbox.uidNext) { if (numericId >= uidNext) {
throw new Error(`Email ID ${numericId} is greater than the highest UID in mailbox (${mailbox.uidNext})`); throw new Error(`Email ID ${numericId} is greater than or equal to the highest UID in mailbox (${uidNext}) for account ${accountId || 'default'}`);
} }
const message = await client.fetchOne(numericId.toString(), { // First, try to get the sequence number for this UID
const searchResult = await client.search({ uid: numericId.toString() });
if (!searchResult || searchResult.length === 0) {
throw new Error(`Email with UID ${numericId} not found in folder ${actualFolder} for account ${accountId || 'default'}`);
}
const sequenceNumber = searchResult[0];
console.log(`[DEBUG] Found sequence number ${sequenceNumber} for UID ${numericId} in account ${accountId || 'default'}`);
// Now fetch using the sequence number
const message = await client.fetchOne(sequenceNumber.toString(), {
source: true, source: true,
envelope: true, envelope: true,
flags: true, flags: true,
@ -456,15 +473,15 @@ export async function getEmailContent(
}); });
if (!message) { if (!message) {
throw new Error(`Email not found with ID ${numericId} in folder ${actualFolder}`); throw new Error(`Email not found with sequence number ${sequenceNumber} in folder ${actualFolder} for account ${accountId || 'default'}`);
} }
const { source, envelope, flags, size } = message; const { source, envelope, flags, size } = message;
// Parse the email content, ensuring all styles and structure are preserved // Parse the email content, ensuring all styles and structure are preserved
const parsedEmail = await simpleParser(source.toString(), { const parsedEmail = await simpleParser(source.toString(), {
skipHtmlToText: true, // Don't convert HTML to plain text skipHtmlToText: true,
keepCidLinks: true // Keep Content-ID references for inline images keepCidLinks: true
}); });
// Convert flags from Set to boolean checks // Convert flags from Set to boolean checks
@ -513,11 +530,12 @@ export async function getEmailContent(
}, },
folder: actualFolder, folder: actualFolder,
contentFetched: true, contentFetched: true,
size: size || 0 size: size || 0,
accountId: accountId || 'default' // Add accountId to the email object
}; };
// Cache the email content // Cache the email content with account-specific key
await cacheEmailContent(userId, accountId || folder, emailId, email); await cacheEmailContent(userId, cacheKey, emailId, email);
return email; return email;
} catch (error) { } catch (error) {
@ -526,7 +544,8 @@ export async function getEmailContent(
emailId, emailId,
folder, folder,
accountId, accountId,
error: error instanceof Error ? error.message : 'Unknown error' error: error instanceof Error ? error.message : 'Unknown error',
details: error instanceof Error ? error.stack : undefined
}); });
throw error; throw error;
} finally { } finally {