diff --git a/lib/redis.ts b/lib/redis.ts index eac864de..3ed63293 100644 --- a/lib/redis.ts +++ b/lib/redis.ts @@ -96,6 +96,11 @@ interface EmailCredentials { port: number; secure?: boolean; encryptedPassword?: string; + smtp_host?: string; + smtp_port?: number; + smtp_secure?: boolean; + display_name?: string; + color?: string; } interface ImapSessionData { @@ -129,7 +134,13 @@ export async function cacheEmailCredentials( email: credentials.email, host: credentials.host, port: credentials.port, - secure: credentials.secure ?? true + secure: credentials.secure ?? true, + // Include the extended fields + ...(credentials.smtp_host && { smtp_host: credentials.smtp_host }), + ...(credentials.smtp_port && { smtp_port: credentials.smtp_port }), + ...(credentials.smtp_secure !== undefined && { smtp_secure: credentials.smtp_secure }), + ...(credentials.display_name && { display_name: credentials.display_name }), + ...(credentials.color && { color: credentials.color }) }; // Encrypt password @@ -156,49 +167,50 @@ export async function cacheEmailCredentials( } /** - * Get cached email credentials from Redis + * Get email credentials from Redis */ -export async function getCachedEmailCredentials( - userId: string -): Promise { +export async function getEmailCredentials(userId: string): Promise { const redis = getRedisClient(); const key = KEYS.CREDENTIALS(userId); try { - const cachedData = await redis.get(key); - if (!cachedData) { - console.log(`No cached credentials found for user ${userId}`); + const credStr = await redis.get(key); + + if (!credStr) { return null; } - console.log(`Found cached credentials for user ${userId}, attempting to decrypt`); - const credentials = JSON.parse(cachedData) as EmailCredentials; + const creds = JSON.parse(credStr) as EmailCredentials; - // Check if we have encrypted password - if (!credentials.encryptedPassword) { - console.warn(`Cached credentials for user ${userId} missing encrypted password`); + if (!creds.encryptedPassword) { + console.warn(`No encrypted password found for user ${userId}`); return null; } try { - // Decrypt password with error handling - credentials.password = decryptData(credentials.encryptedPassword); - delete credentials.encryptedPassword; + // Decrypt the password + const password = decryptData(creds.encryptedPassword); - // Validate the credentials to ensure they're complete - if (!credentials.password || !credentials.email || !credentials.host) { - console.warn(`Incomplete credentials in cache for user ${userId}, missing required fields`); - return null; - } - - console.log(`Successfully retrieved and decrypted credentials for ${userId}`); - return credentials; + // Return the full credentials with decrypted password + return { + email: creds.email, + password, + host: creds.host, + port: creds.port, + secure: creds.secure ?? true, + // Include the extended fields if they exist in the cache + ...(creds.smtp_host && { smtp_host: creds.smtp_host }), + ...(creds.smtp_port && { smtp_port: creds.smtp_port }), + ...(creds.smtp_secure !== undefined && { smtp_secure: creds.smtp_secure }), + ...(creds.display_name && { display_name: creds.display_name }), + ...(creds.color && { color: creds.color }) + }; } catch (decryptError) { console.error(`Failed to decrypt password for user ${userId}:`, decryptError); return null; } } catch (error) { - console.error(`Error retrieving credentials from Redis for user ${userId}:`, error); + console.error(`Error retrieving credentials for user ${userId}:`, error); return null; } } @@ -397,4 +409,14 @@ export async function invalidateUserEmailCache( } } while (cursor !== '0'); } +} + +/** + * Get cached email credentials from Redis + * @deprecated Use getEmailCredentials instead + */ +export async function getCachedEmailCredentials( + userId: string +): Promise { + return getEmailCredentials(userId); } \ No newline at end of file diff --git a/lib/services/email-service.ts b/lib/services/email-service.ts index f81c2436..3228a4c8 100644 --- a/lib/services/email-service.ts +++ b/lib/services/email-service.ts @@ -192,37 +192,27 @@ export async function saveUserEmailCredentials( userId: string, credentials: EmailCredentials ): Promise { - // Save to database + console.log('Saving credentials for user:', userId); + + // Extract only the fields that exist in the database schema + const dbCredentials = { + email: credentials.email, + password: credentials.password ?? '', + host: credentials.host, + port: credentials.port + }; + + // Save to database - only using fields that exist in the schema await prisma.mailCredentials.upsert({ where: { userId }, - update: { - email: credentials.email, - password: credentials.password, - host: credentials.host, - port: credentials.port, - secure: credentials.secure ?? true, - smtp_host: credentials.smtp_host, - smtp_port: credentials.smtp_port, - smtp_secure: credentials.smtp_secure, - display_name: credentials.display_name, - color: credentials.color - }, + update: dbCredentials, create: { userId, - email: credentials.email, - password: credentials.password, - host: credentials.host, - port: credentials.port, - secure: credentials.secure ?? true, - smtp_host: credentials.smtp_host, - smtp_port: credentials.smtp_port, - smtp_secure: credentials.smtp_secure, - display_name: credentials.display_name, - color: credentials.color + ...dbCredentials } }); - // Also cache in Redis + // Cache the full credentials object in Redis (with all fields) await cacheEmailCredentials(userId, credentials); }