import { NextResponse } from 'next/server'; import { getServerSession } from 'next-auth'; import { authOptions } from '@/app/api/auth/[...nextauth]/route'; import { getMailboxes } from '@/lib/services/email-service'; import { getRedisClient } from '@/lib/redis'; import { getImapConnection } from '@/lib/services/email-service'; import { prisma } from '@/lib/prisma'; // Define extended MailCredentials type interface MailCredentials { id: string; userId: string; email: string; password: string; host: string; port: number; secure?: boolean; smtp_host?: string | null; smtp_port?: number | null; smtp_secure?: boolean | null; display_name?: string | null; color?: string | null; createdAt: Date; updatedAt: Date; } // Keep track of last prefetch time for each user const lastPrefetchMap = new Map(); const PREFETCH_COOLDOWN_MS = 30000; // 30 seconds cooldown between prefetches // Cache TTL for folders in Redis (5 minutes) const FOLDERS_CACHE_TTL = 3600; // 1 hour // Redis key for folders cache const FOLDERS_CACHE_KEY = (userId: string, accountId: string) => `email:folders:${userId}:${accountId}`; /** * This endpoint is called when the app initializes to check if the user has email credentials * and to start prefetching email data in the background if they do */ export async function GET() { try { // Get Redis connection first to ensure it's available const redis = getRedisClient(); if (!redis) { console.error('Redis connection failed'); return NextResponse.json({ error: 'Redis connection failed' }, { status: 500 }); } // Get session with detailed logging console.log('Attempting to get server session...'); const session = await getServerSession(authOptions); if (!session) { console.error('No session found'); return NextResponse.json({ authenticated: false, error: 'No session found' }, { status: 401 }); } if (!session.user) { console.error('No user in session'); return NextResponse.json({ authenticated: false, error: 'No user in session' }, { status: 401 }); } if (!session.user.id) { console.error('No user ID in session'); return NextResponse.json({ authenticated: false, error: 'No user ID in session' }, { status: 401 }); } console.log('Session validated successfully:', { userId: session.user.id, email: session.user.email, name: session.user.name }); // Get user with their accounts console.log('Fetching user with ID:', session.user.id); const user = await prisma.user.findUnique({ where: { id: session.user.id }, include: { mailCredentials: true } }); if (!user) { console.error('User not found in database'); return NextResponse.json({ authenticated: true, hasEmailCredentials: false, error: 'User not found in database' }); } // Get all accounts for the user const accounts = (user.mailCredentials || []) as MailCredentials[]; if (accounts.length === 0) { console.log('No email accounts found for user:', session.user.id); return NextResponse.json({ authenticated: true, hasEmailCredentials: false, accounts: [], message: 'No email accounts found' }); } console.log(`Found ${accounts.length} accounts for user:`, accounts.map(a => a.email)); // Fetch folders for each account const accountsWithFolders = await Promise.all( accounts.map(async (account: MailCredentials) => { const cacheKey = FOLDERS_CACHE_KEY(user.id, account.id); try { // Try to get folders from Redis cache first const cachedFolders = await redis.get(cacheKey); if (cachedFolders) { console.log(`Using cached folders for account ${account.email}`); return { id: account.id, email: account.email, display_name: account.display_name, color: account.color, folders: JSON.parse(cachedFolders) }; } // If not in cache, fetch from IMAP console.log(`Fetching folders from IMAP for account ${account.email}`); const client = await getImapConnection(user.id, account.id); if (!client) { console.warn(`Failed to get IMAP connection for account ${account.email}`); return { id: account.id, email: account.email, display_name: account.display_name, color: account.color, folders: ['INBOX', 'Sent', 'Drafts', 'Trash', 'Junk'] }; } const folders = await getMailboxes(client); console.log(`Fetched ${folders.length} folders for account ${account.email}`); // Cache the folders in Redis await redis.set( cacheKey, JSON.stringify(folders), 'EX', FOLDERS_CACHE_TTL ); return { id: account.id, email: account.email, display_name: account.display_name, color: account.color, folders }; } catch (error) { console.error(`Error fetching folders for account ${account.id}:`, error); return { id: account.id, email: account.email, display_name: account.display_name, color: account.color, folders: ['INBOX', 'Sent', 'Drafts', 'Trash', 'Junk'] }; } }) ); return NextResponse.json({ authenticated: true, hasEmailCredentials: true, allAccounts: accountsWithFolders }); } catch (error) { console.error('Error in session route:', error); return NextResponse.json( { authenticated: false, error: 'Internal server error', details: error instanceof Error ? error.message : 'Unknown error' }, { status: 500 } ); } }