108 lines
3.3 KiB
TypeScript
108 lines
3.3 KiB
TypeScript
import { ImapFlow } from 'imapflow';
|
|
import { getServerSession } from 'next-auth';
|
|
import { authOptions } from "@/app/api/auth/options";
|
|
import { prisma } from '@/lib/prisma';
|
|
import { getCachedEmailCredentials } from '@/lib/redis';
|
|
import { EmailCredentials } from '@/lib/types';
|
|
|
|
export async function getImapClient() {
|
|
const session = await getServerSession(authOptions);
|
|
if (!session?.user?.id) {
|
|
throw new Error('No authenticated user');
|
|
}
|
|
|
|
// First try to get credentials from Redis cache
|
|
let credentials = await getCachedEmailCredentials(session.user.id, 'default');
|
|
|
|
// If not in cache, get from database
|
|
if (!credentials) {
|
|
console.log(`Credentials not found in cache for ${session.user.id}, checking database`);
|
|
const dbCredentials = await prisma.mailCredentials.findFirst({
|
|
where: {
|
|
userId: session.user.id
|
|
}
|
|
});
|
|
|
|
// Convert database model to EmailCredentials
|
|
if (dbCredentials) {
|
|
const dbCreds = dbCredentials as any;
|
|
|
|
credentials = {
|
|
email: dbCreds.email,
|
|
password: dbCreds.password || undefined, // Convert null to undefined
|
|
host: dbCreds.host,
|
|
port: dbCreds.port,
|
|
secure: dbCreds.secure,
|
|
useOAuth: dbCreds.use_oauth,
|
|
accessToken: dbCreds.access_token || undefined,
|
|
refreshToken: dbCreds.refresh_token || undefined,
|
|
smtp_host: dbCreds.smtp_host || undefined,
|
|
smtp_port: dbCreds.smtp_port || undefined, // Handle null
|
|
smtp_secure: dbCreds.smtp_secure || undefined, // Handle null
|
|
display_name: dbCreds.display_name || undefined,
|
|
color: dbCreds.color || undefined,
|
|
};
|
|
}
|
|
}
|
|
|
|
if (!credentials) {
|
|
throw new Error('No mail credentials found. Please configure your email account.');
|
|
}
|
|
|
|
// Validate credentials
|
|
if (!credentials.password) {
|
|
throw new Error('No password configured for email account');
|
|
}
|
|
|
|
return new ImapFlow({
|
|
host: credentials.host,
|
|
port: credentials.port,
|
|
secure: true,
|
|
auth: {
|
|
user: credentials.email,
|
|
pass: credentials.password,
|
|
},
|
|
logger: false,
|
|
tls: {
|
|
rejectUnauthorized: false
|
|
}
|
|
});
|
|
}
|
|
|
|
export async function moveEmails(emailIds: number[], targetFolder: string) {
|
|
const imap = await getImapClient();
|
|
const lock = await imap.getMailboxLock('INBOX');
|
|
try {
|
|
for (const id of emailIds) {
|
|
const message = await imap.fetchOne(id.toString(), { uid: true });
|
|
if (message) {
|
|
const uid = typeof message.uid === 'number' ? message.uid.toString() : message.uid;
|
|
await imap.messageMove(uid, targetFolder);
|
|
}
|
|
}
|
|
} finally {
|
|
lock.release();
|
|
}
|
|
}
|
|
|
|
export async function markAsRead(emailIds: (string | number)[], isRead: boolean) {
|
|
const imap = await getImapClient();
|
|
try {
|
|
await imap.connect();
|
|
const lock = await imap.getMailboxLock('INBOX');
|
|
try {
|
|
for (const id of emailIds) {
|
|
const stringId = typeof id === 'number' ? id.toString() : id;
|
|
const message = await imap.fetchOne(stringId, { uid: true });
|
|
if (message) {
|
|
const uid = typeof message.uid === 'number' ? message.uid.toString() : message.uid;
|
|
await imap.messageFlagsAdd(uid, isRead ? ['\\Seen'] : [], { uid: true });
|
|
}
|
|
}
|
|
} finally {
|
|
lock.release();
|
|
}
|
|
} finally {
|
|
await imap.logout();
|
|
}
|
|
}
|