courrier multi account restore compose

This commit is contained in:
alma 2025-04-30 12:57:32 +02:00
parent 9f0ca0e6f5
commit 21accd5224
3 changed files with 214 additions and 190 deletions

View File

@ -40,69 +40,63 @@ export async function GET(request: Request) {
const searchQuery = searchParams.get("search") || "";
const accountId = searchParams.get("accountId") || "";
// Extract account ID from folder name if present and none was explicitly provided
const folderAccountId = folder.includes(':') ? folder.split(':')[0] : "";
// CRITICAL FIX: Log exact parameters received by the API
console.log(`[API] Received request with: folder=${folder}, accountId=${accountId}, page=${page}`);
// Use the most specific account ID available
// First from the folder, then from the explicit parameter, then default
let effectiveAccountId = folderAccountId || accountId || 'default';
// CRITICAL FIX: More robust parameter normalization
// 1. If folder contains an account prefix, extract it but DO NOT use it
// 2. Always prioritize the explicit accountId parameter
let normalizedFolder = folder;
let effectiveAccountId = accountId || 'default';
// CRITICAL FIX: If effectiveAccountId is still 'default', try to find the first account for the user
if (effectiveAccountId === 'default') {
try {
const accounts = await prisma.mailCredentials.findMany({
where: { userId: session.user.id },
orderBy: { createdAt: 'asc' },
take: 1,
select: { id: true }
});
if (accounts && accounts.length > 0) {
effectiveAccountId = accounts[0].id;
console.log(`No specific account provided, using first available account: ${effectiveAccountId}`);
}
} catch (error) {
console.error("Error finding default account:", error);
// Continue with 'default' if there's an error
}
if (folder.includes(':')) {
const parts = folder.split(':');
const folderAccountId = parts[0];
normalizedFolder = parts[1];
console.log(`[API] Folder has prefix (${folderAccountId}), normalized to ${normalizedFolder}`);
// We intentionally DO NOT use folderAccountId here - the explicit accountId parameter takes precedence
}
// Normalize folder name by removing account prefix if present
const normalizedFolder = folder.includes(':') ? folder.split(':')[1] : folder;
// Log the request details for debugging
console.log(`Email request: user=${session.user.id}, folder=${normalizedFolder}, account=${effectiveAccountId}, page=${page}`);
// CRITICAL FIX: Enhanced logging for parameter resolution
console.log(`[API] Using normalized parameters: folder=${normalizedFolder}, accountId=${effectiveAccountId}`);
// Try to get from Redis cache first, but only if it's not a search query
if (!searchQuery) {
// CRITICAL FIX: Use consistent cache key format with the correct account ID
console.log(`[API] Checking Redis cache for ${session.user.id}:${effectiveAccountId}:${normalizedFolder}:${page}:${perPage}`);
const cachedEmails = await getCachedEmailList(
session.user.id,
effectiveAccountId,
normalizedFolder,
effectiveAccountId, // Use effective account ID for consistent cache key
normalizedFolder, // Use normalized folder name without prefix
page,
perPage
);
if (cachedEmails) {
console.log(`Using Redis cached emails for ${session.user.id}:${effectiveAccountId}:${normalizedFolder}:${page}:${perPage}`);
console.log(`[API] Using Redis cached emails for ${session.user.id}:${effectiveAccountId}:${normalizedFolder}:${page}:${perPage}`);
return NextResponse.json(cachedEmails);
}
}
console.log(`Redis cache miss for ${session.user.id}:${effectiveAccountId}:${normalizedFolder}:${page}:${perPage}, fetching emails from IMAP`);
console.log(`[API] Redis cache miss for ${session.user.id}:${effectiveAccountId}:${normalizedFolder}:${page}:${perPage}, fetching emails from IMAP`);
// Use the email service to fetch emails with the normalized folder and effective account ID
// CRITICAL FIX: Pass parameters in the correct order and with proper values
const emailsResult = await getEmails(
session.user.id,
normalizedFolder,
page,
perPage,
effectiveAccountId
session.user.id, // userId
normalizedFolder, // folder (without prefix)
page, // page
perPage, // perPage
effectiveAccountId // accountId
);
// CRITICAL FIX: Log when emails are returned from IMAP
console.log(`[API] Successfully fetched ${emailsResult.emails.length} emails from IMAP for account ${effectiveAccountId}`);
// The result is already cached in the getEmails function
return NextResponse.json(emailsResult);
} catch (error: any) {
console.error("Error fetching emails:", error);
console.error("[API] Error fetching emails:", error);
return NextResponse.json(
{ error: "Failed to fetch emails", message: error.message },
{ status: 500 }

View File

@ -610,11 +610,16 @@ export default function CourrierPage() {
// Update handleMailboxChange to ensure consistent folder naming and prevent race conditions
const handleMailboxChange = (folder: string, accountId?: string) => {
// Enhanced logging to trace the flow
logEmailOp('MAILBOX-CHANGE-V4', `Starting mailbox change to folder=${folder}, accountId=${accountId || 'undefined'}`);
logEmailOp('MAILBOX-CHANGE', `Starting mailbox change to folder=${folder}, accountId=${accountId || 'undefined'}`);
// CRITICAL FIX: Account ID is REQUIRED for proper folder switching
if (!accountId || accountId === 'loading-account') {
logEmailOp('MAILBOX-CHANGE-V4', 'No valid accountId provided, using default flow', { folder });
changeFolder(folder);
logEmailOp('MAILBOX-CHANGE', 'ERROR: No valid accountId provided, cannot switch folders reliably', { folder });
toast({
title: "Cannot switch folders",
description: "A valid account ID is required to switch folders",
variant: "destructive",
});
return;
}
@ -624,9 +629,10 @@ export default function CourrierPage() {
// Clear emails during transition to avoid UI flicker/confusion
setEmails([]);
// Find the account to ensure it exists
const account = accounts.find(a => a.id.toString() === accountId.toString());
if (!account) {
logEmailOp('MAILBOX-CHANGE-V4', `ERROR: Account not found: ${accountId}`);
logEmailOp('MAILBOX-CHANGE', `ERROR: Account not found: ${accountId}`);
toast({
title: "Account not found",
description: `The account ${accountId} could not be found.`,
@ -636,75 +642,60 @@ export default function CourrierPage() {
return;
}
logEmailOp('MAILBOX-CHANGE-V4', `Found account: ${account.email}`, {
folderCount: account.folders?.length || 0,
folder: folder
logEmailOp('MAILBOX-CHANGE', `Account found: ${account.email}`, {
accountId: account.id
});
// Extract the base folder name if it already has an account prefix
let baseFolder = folder;
let folderAccountId = null;
// CRITICAL FIX: Simplify and clarify parameter handling
// Extract base folder name and ensure we have a clean normalized folder
let baseFolder: string;
if (folder.includes(':')) {
const parts = folder.split(':');
folderAccountId = parts[0];
const folderAccountId = parts[0];
baseFolder = parts[1];
logEmailOp('MAILBOX-CHANGE-V4', `Parsed folder: accountId=${folderAccountId}, baseFolder=${baseFolder}`);
logEmailOp('MAILBOX-CHANGE', `Parsed folder: accountId=${folderAccountId}, baseFolder=${baseFolder}`);
// CRITICAL FIX: If the folder has an account prefix that doesn't match the requested account,
// log a warning and ALWAYS use the requested accountId
if (folderAccountId !== accountId.toString()) {
logEmailOp('MAILBOX-CHANGE-V4', `WARNING: Folder prefix mismatch - FIXING`, {
folderAccount: folderAccountId,
requestedAccount: accountId,
originalFolder: folder,
baseFolder: baseFolder
});
// Force the correct account ID to be used
folderAccountId = accountId.toString();
// CRITICAL FIX: If folder has a different account prefix than requested, log warning
if (folderAccountId !== accountId) {
logEmailOp('MAILBOX-CHANGE', `WARNING: Folder prefix (${folderAccountId}) doesn't match requested account (${accountId})`);
}
} else {
baseFolder = folder;
logEmailOp('MAILBOX-CHANGE', `No folder prefix, using baseFolder=${baseFolder}`);
}
// ALWAYS create a consistent folder name with REQUESTED account prefix
// CRITICAL FIX: ALWAYS create consistent folder name with REQUESTED account prefix
const prefixedFolder = `${accountId}:${baseFolder}`;
logEmailOp('MAILBOX-CHANGE-V4', `Normalized folder name: ${prefixedFolder}`);
logEmailOp('MAILBOX-CHANGE', `Standardized folder: ${prefixedFolder}`);
// Check if we're already on this folder to avoid unnecessary refreshes
if (currentFolder === prefixedFolder) {
logEmailOp('MAILBOX-CHANGE-V4', `Already on folder ${prefixedFolder}, skipping change`);
setLoading(false);
return;
}
// CRITICAL FIX: Lock in the selected folder BEFORE changing it in the system
// This prevents any race conditions where the folder gets reset to INBOX
// CRITICAL FIX: Update the selected account BEFORE changing folders
// This prevents potential race conditions during account switching
setSelectedAccount(account);
// CRITICAL FIX: Update selected folder map with the new account's folder
// This ensures UI consistency with the selected folder
setSelectedFolders(prev => {
const updated = {
...prev,
[accountId]: prefixedFolder
};
logEmailOp('MAILBOX-CHANGE-V4', `Updated selected folders map`, updated);
logEmailOp('MAILBOX-CHANGE', `Updated selected folders map`, updated);
return updated;
});
// EXTRA SAFETY: Log exactly what we're passing to changeFolder
logEmailOp('MAILBOX-CHANGE-V4', `CALLING changeFolder with EXACT PARAMS:`, {
folder: prefixedFolder,
accountId: accountId,
folderType: typeof prefixedFolder,
accountIdType: typeof accountId
});
// CRITICAL FIX: Log the EXACT parameters being passed to changeFolder
logEmailOp('MAILBOX-CHANGE', `Calling changeFolder with: folder=${prefixedFolder}, accountId=${accountId}`);
// Now use the changeFolder function from the hook with our properly formatted folder name
// CRITICAL FIX: Call changeFolder with both parameters explicitly
// The accountId parameter is critical for successful account switching
changeFolder(prefixedFolder, accountId)
.then(() => {
logEmailOp('MAILBOX-CHANGE-V4', `Successfully changed to folder ${prefixedFolder}`);
logEmailOp('MAILBOX-CHANGE', `Successfully changed to folder ${prefixedFolder} for account ${accountId}`);
})
.catch(error => {
logEmailOp('MAILBOX-CHANGE-V4', `ERROR: Failed to change to folder ${prefixedFolder}`, { error });
logEmailOp('MAILBOX-CHANGE', `ERROR: Failed to change to folder ${prefixedFolder}`, { error });
toast({
title: "Error changing folders",
description: `Failed to change to folder ${baseFolder}. ${error instanceof Error ? error.message : String(error)}`,

View File

@ -91,32 +91,39 @@ export const useCourrier = () => {
setError(null);
try {
// CRITICAL FIX: Extract normalized folder name for API requests
// The currentFolder should already have the account prefix in format "accountId:folder"
// We need to extract the base folder name for the API request
// CRITICAL FIX: When an account ID is explicitly provided, ALWAYS prioritize it
// over any account ID that might be extracted from the currentFolder
let normalizedFolder = currentFolder;
// CRITICAL FIX: Handle account ID determination more robustly
// If specific account ID is provided, always use it
// Otherwise extract from currentFolder if possible
let effectiveAccountId: string;
if (accountId) {
// Use explicitly provided accountId
effectiveAccountId = accountId;
} else if (currentFolder.includes(':')) {
// Extract from folder format
// Start by logging exactly what parameters we received
console.log(`[loadEmails] Called with isLoadMore=${isLoadMore}, accountId=${accountId || 'undefined'}, currentFolder=${currentFolder}`);
if (currentFolder.includes(':')) {
const parts = currentFolder.split(':');
effectiveAccountId = parts[0];
normalizedFolder = parts[1];
const folderAccountId = parts[0];
const baseFolderName = parts[1];
// CRITICAL FIX: If an account ID is explicitly provided, use it with highest priority
// This ensures account switching always works correctly
if (accountId) {
console.log(`[loadEmails] Explicit accountId provided (${accountId}), overriding folder prefix (${folderAccountId})`);
effectiveAccountId = accountId;
normalizedFolder = baseFolderName;
} else {
// No explicit account ID, use the one from the folder
effectiveAccountId = folderAccountId;
normalizedFolder = baseFolderName;
}
} else {
// Default case
effectiveAccountId = 'default';
// Folder doesn't have a prefix
normalizedFolder = currentFolder;
effectiveAccountId = accountId || 'default';
}
console.log(`Load emails - using normalized folder: ${normalizedFolder}, effectiveAccountId: ${effectiveAccountId}`);
console.log(`[loadEmails] Using normalized folder: ${normalizedFolder}, effectiveAccountId: ${effectiveAccountId}`);
// Construct query parameters
// Construct query parameters with normalized values
const queryParams = new URLSearchParams({
folder: normalizedFolder, // Use normalized folder without account prefix for API
page: page.toString(),
@ -130,14 +137,16 @@ export const useCourrier = () => {
// Always add accountId to query params
queryParams.set('accountId', effectiveAccountId);
// Log the exact query parameters being used
console.log(`[loadEmails] Query parameters: ${queryParams.toString()}`);
// Try to get cached emails first
const currentRequestPage = page;
// CRITICAL FIX: Use the correct cache key format
// We pass the full prefixed folder to ensure proper cache key consistency
// CRITICAL FIX: Use consistent cache key format with explicit account ID
const folderForCache = `${effectiveAccountId}:${normalizedFolder}`;
console.log(`Getting cached emails for user ${session.user.id}, folder ${folderForCache}, page ${currentRequestPage}, accountId ${effectiveAccountId}`);
console.log(`[loadEmails] Checking cache with key: ${folderForCache}, accountId=${effectiveAccountId}`);
const cachedEmails = await getCachedEmailsWithTimeout(
session.user.id, // userId: string
folderForCache, // folder: string - use consistently prefixed folder for cache key
@ -307,7 +316,8 @@ export const useCourrier = () => {
// Change folder and load emails from that folder
const changeFolder = useCallback(async (folder: string, accountId?: string) => {
console.log(`Changing folder to ${folder} for account ${accountId || 'default'}`);
console.log(`[changeFolder] Called with folder=${folder}, accountId=${accountId || 'default'}`);
try {
// Reset selected email and selection state immediately to avoid race conditions
setSelectedEmail(null);
@ -315,22 +325,38 @@ export const useCourrier = () => {
setEmails([]); // Clear existing emails right away
setIsLoading(true); // Show loading state immediately
// CRITICAL FIX: Extract account ID from folder name if present and none was explicitly provided
const folderAccountId = folder.includes(':') ? folder.split(':')[0] : accountId;
// CRITICAL FIX: Clear and precise parameter handling with detailed logging
let normalizedFolder: string;
let effectiveAccountId: string;
let prefixedFolder: string;
// Use the most specific account ID available
const effectiveAccountId = folderAccountId || accountId || 'default';
// Parse input folder parameter
if (folder.includes(':')) {
// Folder has a prefix, extract components
const parts = folder.split(':');
const folderAccountId = parts[0];
normalizedFolder = parts[1];
// CRITICAL FIX: If an explicit accountId is provided, it ALWAYS takes precedence
// This is the key to fixing account switching issues
if (accountId) {
console.log(`[changeFolder] Explicit accountId (${accountId}) overrides folder prefix (${folderAccountId})`);
effectiveAccountId = accountId;
} else {
console.log(`[changeFolder] Using account ID from folder prefix: ${folderAccountId}`);
effectiveAccountId = folderAccountId;
}
} else {
// Folder has no prefix
normalizedFolder = folder;
effectiveAccountId = accountId || 'default';
console.log(`[changeFolder] No folder prefix, using accountId=${effectiveAccountId}, folder=${normalizedFolder}`);
}
// Normalize folder name by removing account prefix if present
const normalizedFolder = folder.includes(':') ? folder.split(':')[1] : folder;
// CRITICAL FIX: Always create a consistently formatted folder name with the EFFECTIVE account prefix
prefixedFolder = `${effectiveAccountId}:${normalizedFolder}`;
// Always create a consistently formatted folder name with account prefix
const prefixedFolder = `${effectiveAccountId}:${normalizedFolder}`;
console.log(`Folder change: original=${folder}, normalized=${normalizedFolder}, accountId=${effectiveAccountId}, prefixed=${prefixedFolder}`);
// CRITICAL FIX: Store the current account ID in state for all subsequent operations
// This ensures operations like markAsRead use the correct account context
console.log(`[changeFolder] Normalized parameters: folder=${normalizedFolder}, accountId=${effectiveAccountId}, prefixedFolder=${prefixedFolder}`);
// Reset search query when changing folders
setSearchQuery('');
@ -338,24 +364,29 @@ export const useCourrier = () => {
// Reset to page 1
setPage(1);
// CRITICAL FIX: We set the currentFolder state AFTER we have prepared all parameters
// This ensures any effects or functions triggered by currentFolder change have the correct context
// CRITICAL FIX: Set currentFolder state and verify it was set correctly
console.log(`[changeFolder] Setting currentFolder to: ${prefixedFolder}`);
setCurrentFolder(prefixedFolder);
// Use a small delay to ensure state updates have propagated
// This helps prevent race conditions when multiple folders are clicked quickly
await new Promise(resolve => setTimeout(resolve, 100));
// CRITICAL FIX: Use a small delay to ensure state updates have propagated
// This helps prevent race conditions during account switching
await new Promise(resolve => setTimeout(resolve, 200));
// CRITICAL FIX: Wait for the loadEmails operation to complete before considering the folder change done
// This prevents multiple concurrent folder changes from interfering with each other
// CRITICAL FIX: Double-check the folder after state update to ensure consistency
console.log(`[changeFolder] After state update, currentFolder=${currentFolder}, loading emails with explicit accountId=${effectiveAccountId}`);
// CRITICAL FIX: Always pass the effective account ID explicitly to loadEmails
// This ensures account context is maintained even if currentFolder hasn't updated yet
await loadEmails(false, effectiveAccountId);
console.log(`[changeFolder] Finished changing to folder=${prefixedFolder}`);
} catch (error) {
console.error(`Error changing to folder ${folder}:`, error);
console.error(`[changeFolder] Error changing to folder ${folder}:`, error);
setError(error instanceof Error ? error.message : 'Unknown error');
} finally {
setIsLoading(false);
}
}, [loadEmails]);
}, [loadEmails, currentFolder]);
// Load emails when page changes for pagination only
useEffect(() => {
@ -494,48 +525,58 @@ export const useCourrier = () => {
// Select an email to view
const handleEmailSelect = useCallback(async (emailId: string, accountId: string, folderOverride: string) => {
// Enhanced logging for better debugging
console.log(`Selecting email ${emailId} from account [${accountId}] in folder [${folderOverride}]`);
console.log(`[handleEmailSelect] Selecting email ${emailId} from account [${accountId}] in folder [${folderOverride}]`);
// Skip processing if emailId is empty (used when deselecting emails)
if (!emailId) {
console.log('No email ID provided, clearing selection');
console.log('[handleEmailSelect] No email ID provided, clearing selection');
setSelectedEmail(null);
return;
}
// CRITICAL FIX: Validate required parameters
if (!accountId) {
console.error('[handleEmailSelect] Account ID is required for email selection');
toast({
variant: "destructive",
title: "Error",
description: "Missing account information when selecting email"
});
return;
}
setIsLoading(true);
try {
// CRITICAL FIX: Always use the provided accountId, never use default
// This ensures we consistently use the correct account throughout the email selection process
if (!accountId) {
throw new Error('Account ID is required for email selection');
}
// Normalize folder name handling - ensure consistent format
// CRITICAL FIX: Normalize folder name with detailed logging
let normalizedFolder: string;
let prefixedFolder: string;
if (folderOverride.includes(':')) {
// Extract parts if folder already has a prefix
const parts = folderOverride.split(':');
const folderAccountId = parts[0];
normalizedFolder = parts[1];
// CRITICAL FIX: Always use the explicitly provided accountId
// This ensures we're looking in the right account when an email is clicked
console.log(`[handleEmailSelect] Folder has prefix '${folderAccountId}', normalized to ${normalizedFolder}`);
// CRITICAL FIX: ALWAYS use the provided accountId, never use the one from the folder
if (folderAccountId !== accountId) {
console.log(`[handleEmailSelect] WARNING: Folder account ID (${folderAccountId}) doesn't match provided account ID (${accountId})`);
}
// Create folder name with consistent account ID
prefixedFolder = `${accountId}:${normalizedFolder}`;
} else {
// No prefix, add one using the provided account ID
// No prefix, add one with the provided account ID
normalizedFolder = folderOverride;
prefixedFolder = `${accountId}:${normalizedFolder}`;
console.log(`[handleEmailSelect] Folder has no prefix, created prefixed version: ${prefixedFolder}`);
}
console.log(`Email selection with normalized values: folder=${normalizedFolder}, prefixed=${prefixedFolder}, accountId=${accountId}`);
console.log(`[handleEmailSelect] Looking for email with ID=${emailId}, account=${accountId}, folder=${prefixedFolder}`);
// CRITICAL FIX: First search for email in current list using the EXACT account provided
// This ensures we don't mix emails from different accounts
console.log(`Looking for email with ID=${emailId}, account=${accountId}, normalized folder=${normalizedFolder}, prefixed=${prefixedFolder}`);
// First, try to find by exact match with the provided account and folder
// CRITICAL FIX: Find email by exact match with the provided account ID
// This prevents mixing emails across accounts
let email = emails.find(e =>
e.id === emailId &&
e.accountId === accountId &&
@ -546,17 +587,18 @@ export const useCourrier = () => {
)
);
// CRITICAL FIX: If not found, we do NOT try finding by ID only
// This prevents mixing emails across accounts
if (!email) {
console.log(`Email ${emailId} not found in current list for account ${accountId} (searched ${emails.length} emails). Fetching from API.`);
if (email) {
console.log(`[handleEmailSelect] Found matching email in current list`);
} else {
console.log(`[handleEmailSelect] Email ${emailId} not found in current list for account ${accountId}, fetching from API`);
try {
// Use the provided account ID and normalized folder for the API request
console.log(`Fetching email ${emailId} directly from API with normalizedFolder=${normalizedFolder}, accountId=${accountId}`);
// CRITICAL FIX: Always use explicit parameters for API request
console.log(`[handleEmailSelect] Fetching email ${emailId} from API with folder=${normalizedFolder}, accountId=${accountId}`);
const fullEmail = await fetchEmailContent(emailId, accountId, normalizedFolder);
// CRITICAL FIX: Always set the accountId correctly
if (fullEmail) {
// CRITICAL FIX: Ensure the email has proper account and folder context
fullEmail.accountId = accountId;
// Make sure folder has the proper prefix for consistent lookup
@ -564,17 +606,14 @@ export const useCourrier = () => {
fullEmail.folder = `${accountId}:${fullEmail.folder}`;
}
console.log(`Successfully fetched email from API:`, {
id: fullEmail.id,
account: fullEmail.accountId,
folder: fullEmail.folder
});
console.log(`[handleEmailSelect] Successfully fetched email from API`);
setSelectedEmail(fullEmail);
} else {
throw new Error('Email content not found');
}
} catch (error) {
// Type the error properly
const fetchError = error instanceof Error ? error : new Error(String(error));
console.error(`Error fetching email from API: ${fetchError.message}`);
console.error(`[handleEmailSelect] Error fetching email from API: ${fetchError.message}`);
throw fetchError;
}
return;
@ -582,53 +621,53 @@ export const useCourrier = () => {
// If content is not fetched, get the full content
if (!email.contentFetched) {
console.log(`Email found but content not fetched. Getting full content for ${emailId}`);
console.log(`[handleEmailSelect] Email found but content not fetched. Getting full content for ${emailId}`);
try {
// CRITICAL FIX: Use the provided accountId for fetching content, not the one from the email
// This ensures consistent account context
console.log(`[handleEmailSelect] Fetching content with explicit parameters: emailId=${emailId}, accountId=${accountId}, folder=${normalizedFolder}`);
console.log(`Fetching content for email ${emailId} with accountId=${accountId}, folder=${normalizedFolder}`);
// Use the provided accountId and normalized folder for fetching
// CRITICAL FIX: Use explicit parameters for API request
const fullEmail = await fetchEmailContent(
emailId,
accountId,
normalizedFolder
);
// CRITICAL FIX: Ensure the returned email has the correct account ID
if (fullEmail) {
// CRITICAL FIX: Force correct account ID
fullEmail.accountId = accountId;
// CRITICAL FIX: Create an updated email with explicit account context
const updatedEmail = {
...email,
accountId: accountId, // Use provided accountId
folder: prefixedFolder, // Use consistent prefixed folder
content: fullEmail.content,
attachments: fullEmail.attachments,
contentFetched: true
};
// Update the email in the list - only match emails with the same ID AND account
setEmails(emails.map(e =>
(e.id === emailId && e.accountId === accountId) ? updatedEmail : e
));
setSelectedEmail(updatedEmail);
console.log(`[handleEmailSelect] Email content loaded successfully`);
}
// Merge the full content with the email
const updatedEmail = {
...email,
accountId, // CRITICAL FIX: Use the provided accountId
folder: prefixedFolder, // CRITICAL FIX: Use the consistently prefixed folder
content: fullEmail.content,
attachments: fullEmail.attachments,
contentFetched: true
};
// Update the email in the list
setEmails(emails.map(e => e.id === emailId && e.accountId === accountId ? updatedEmail : e));
setSelectedEmail(updatedEmail);
console.log(`Successfully updated email with content`);
} catch (error) {
// Type the error properly
const contentError = error instanceof Error ? error : new Error(String(error));
console.error(`Error fetching email content: ${contentError.message}`);
console.error(`[handleEmailSelect] Error fetching email content: ${contentError.message}`);
throw contentError;
}
} else {
console.log(`Email found with content already fetched, selecting directly`);
console.log(`[handleEmailSelect] Email found with content already fetched, selecting directly`);
// CRITICAL FIX: Ensure the email has the correct account ID before selecting
// CRITICAL FIX: Even if already fetched, ensure consistent account context
email = {
...email,
accountId, // Always use the provided accountId
folder: prefixedFolder // Always use the consistently prefixed folder
accountId: accountId, // Force the correct account ID
folder: prefixedFolder // Force the consistent folder prefix
};
setSelectedEmail(email);
@ -636,13 +675,13 @@ export const useCourrier = () => {
// Mark the email as read if it's not already
if (!email.flags.seen) {
console.log(`Marking email ${emailId} as read for account ${accountId}`);
console.log(`[handleEmailSelect] Marking email ${emailId} as read for account ${accountId}`);
markEmailAsRead(emailId, true, accountId).catch(err => {
console.error(`Failed to mark email as read: ${err.message}`);
console.error(`[handleEmailSelect] Failed to mark email as read: ${err.message}`);
});
}
} catch (err) {
console.error(`Error selecting email: ${err instanceof Error ? err.message : String(err)}`);
console.error(`[handleEmailSelect] Error: ${err instanceof Error ? err.message : String(err)}`);
toast({
variant: "destructive",
title: "Error",