import { randomUUID } from "crypto"; import { getImapProxyAccounts, getMailConnections } from "../../db/mail"; import { getProfile } from "../../db/profile"; import { getPlanLimits } from "../../utils/plan-features"; import { detectSmtpProvider } from "../../utils/imap-providers"; import { decrypt } from "../../utils/crypto"; function escapeXml(s: string): string { return s .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """) .replace(/'/g, "'"); } export default defineEventHandler(async (event) => { const user = await requireUser(event); const profile = await getProfile(user.id); const limits = getPlanLimits(profile?.plan ?? "free"); if (limits.mailAgents !== Infinity) { throw createError({ statusCode: 403, message: "Nur für Legend-User verfügbar" }); } const [accounts, connections] = await Promise.all([ getImapProxyAccounts(user.id), getMailConnections(user.id), ]); if (accounts.length === 0) { throw createError({ statusCode: 404, message: "Noch keine Proxy-Konten eingerichtet" }); } const connMap = new Map(connections.map((c) => [c.id, c])); const payloads: string[] = []; for (const account of accounts) { const conn = connMap.get(account.connectionId); if (!conn) continue; let proxyPassword: string; try { proxyPassword = decrypt(account.proxyPassword); } catch { continue; // Legacy scrypt hash – skip, user needs to re-generate via proxy-account.post } let realPassword = ""; try { realPassword = decrypt(conn.passwordEncrypted); } catch { /* SMTP password omitted */ } const smtp = detectSmtpProvider(conn.imapHost); payloads.push(` EmailAccountDescription ReBreak Filter – ${escapeXml(conn.email)} EmailAccountName ${escapeXml(conn.email)} EmailAccountType EmailTypeIMAP EmailAddress ${escapeXml(conn.email)} IncomingMailServerHostName imap.rebreak.org IncomingMailServerPortNumber 993 IncomingMailServerUseSSL IncomingMailServerUsername ${escapeXml(account.proxyUsername)} IncomingMailServerPassword ${escapeXml(proxyPassword)} OutgoingMailServerHostName ${escapeXml(smtp.host)} OutgoingMailServerPortNumber ${smtp.port} OutgoingMailServerUseSSL OutgoingMailServerUsername ${escapeXml(conn.email)}${realPassword ? ` OutgoingMailServerPassword ${escapeXml(realPassword)}` : ""} SMIMEEnabled PayloadDescription Mail-Filter für ${escapeXml(conn.email)} PayloadDisplayName ReBreak – ${escapeXml(conn.email)} PayloadIdentifier org.rebreak.mail.${conn.id} PayloadType com.apple.mail.managed PayloadUUID ${randomUUID()} PayloadVersion 1 `); } if (payloads.length === 0) { throw createError({ statusCode: 400, message: "Proxy-Konten müssen zuerst neu erstellt werden" }); } const plist = ` PayloadContent ${payloads.join("\n ")} PayloadDescription Blockiert Casino-Mails automatisch bevor sie in deinen Posteingang gelangen PayloadDisplayName ReBreak Mail Filter PayloadIdentifier org.rebreak.mail.profile.${user.id} PayloadOrganization ReBreak PayloadRemovalDisallowed PayloadType Configuration PayloadUUID ${randomUUID()} PayloadVersion 1 `; setHeader(event, "Content-Type", "application/x-apple-aspen-config"); setHeader(event, "Content-Disposition", 'attachment; filename="rebreak-mail-filter.mobileconfig"'); return plist; });