NeahNew/app/api/courrier/session/route.ts
2025-05-05 13:04:01 +02:00

194 lines
6.0 KiB
TypeScript

import { NextResponse } from 'next/server';
import { getServerSession } from 'next-auth';
import { authOptions } from "@/app/api/auth/options";
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<string, number>();
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 }
);
}
}