import { ImapFlow } from "imapflow"; import { getProfile } from "../../db/profile"; import { getPlanLimits } from "../../utils/plan-features"; import { countMailConnections, upsertMailConnection } from "../../db/mail"; /** * POST /api/mail/connect * Body: { email, password } * Testet IMAP-Verbindung und speichert Credentials verschlüsselt. */ export default defineEventHandler(async (event) => { const user = await requireUser(event); const { email, password, // Custom-IMAP-Felder (optional, nur wenn User eigenen Server konfiguriert) imapHost: customImapHost, imapPort: customImapPort, useTls, rejectUnauthorized, } = await readBody(event); if (!email || !password) { throw createError({ statusCode: 400, message: "Email und Passwort erforderlich", }); } // Plan-Limit prüfen const profile = await getProfile(user.id); const limits = getPlanLimits(profile?.plan ?? "free"); if (limits.mailAgents !== Infinity) { const count = await countMailConnections(user.id); if (count >= limits.mailAgents) { throw createError({ statusCode: 403, message: `Dein Plan erlaubt maximal ${limits.mailAgents} Mail-Agent${limits.mailAgents !== 1 ? "en" : ""}`, }); } } // Custom-IMAP: wenn imapHost explizit gesetzt → Provider-Detection überspringen. // Sonst: automatisch via Email-Domain erkennen. const provider = detectImapProvider(email); const resolvedHost = customImapHost?.trim() || provider.host; const resolvedPort = customImapPort ?? provider.port; // TLS-Konfiguration ableiten // useTls=false → STARTTLS (secure=false, requireTLS=true bei ImapFlow) // useTls=true oder nicht gesetzt → implicit TLS (secure=true) const useImplicitTls = useTls !== false; // default: true const tlsRejectUnauthorized = rejectUnauthorized !== false; // default: true // STARTTLS nur wenn explizit angefordert (useTls === false) const useStarttls = useTls === false; // IMAP-Verbindung testen const client = new ImapFlow({ host: resolvedHost, port: resolvedPort, secure: useImplicitTls, ...(useStarttls ? { requireTLS: true } : {}), auth: { user: email, pass: password }, logger: false, tls: { rejectUnauthorized: tlsRejectUnauthorized }, }); try { await client.connect(); await client.logout(); } catch (err: any) { throw createError({ statusCode: 401, message: `Verbindung fehlgeschlagen: ${err.message ?? "Ungültige Zugangsdaten"}`, }); } // Credentials verschlüsselt speichern await upsertMailConnection({ userId: user.id, email, provider: "imap", // Bei Custom-Host: Host als providerName, sonst auto-erkannter Name providerName: customImapHost ? resolvedHost : provider.name, imapHost: resolvedHost, imapPort: resolvedPort, passwordEncrypted: encrypt(password), rejectUnauthorized: tlsRejectUnauthorized, useStarttls, }); return { connected: true, email, provider: customImapHost ? resolvedHost : provider.name, custom: !!customImapHost, }; });