diff --git a/app/[locale]/page.tsx b/app/[locale]/page.tsx index 99f84e9b..a9b844b2 100644 --- a/app/[locale]/page.tsx +++ b/app/[locale]/page.tsx @@ -500,7 +500,10 @@ export default function Home() { // Load mailboxes and emails when authenticated (only if not already loaded) useEffect(() => { if (isAuthenticated && client && mailboxes.length === 0) { - const loadData = async () => { + let retryTimer: ReturnType | null = null; + let cancelled = false; + + const loadData = async (attempt = 1) => { try { // First fetch mailboxes and quota (inbox will be auto-selected in fetchMailboxes) await Promise.all([ @@ -512,6 +515,15 @@ export default function Home() { const state = useEmailStore.getState(); const selectedMailboxId = state.selectedMailbox; + // On first login the server may still be provisioning mailboxes. + // Retry a few times with back-off before giving up. + if (state.mailboxes.length === 0 && attempt <= 5 && !cancelled) { + const delay = Math.min(1000 * attempt, 5000); + debug.log('jmap', `[Mailbox] No mailboxes returned (attempt ${attempt}), retrying in ${delay}ms`); + retryTimer = setTimeout(() => loadData(attempt + 1), delay); + return; + } + // Fetch emails for the selected mailbox if (selectedMailboxId) { await fetchEmails(client, selectedMailboxId); @@ -545,6 +557,12 @@ export default function Home() { } }; loadData(); + + return () => { + cancelled = true; + if (retryTimer) clearTimeout(retryTimer); + client.closePushNotifications(); + }; } // Cleanup push notifications on unmount