137 lines
4.9 KiB
TypeScript
137 lines
4.9 KiB
TypeScript
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, """)
|
||
.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(`<dict>
|
||
<key>EmailAccountDescription</key>
|
||
<string>ReBreak Filter – ${escapeXml(conn.email)}</string>
|
||
<key>EmailAccountName</key>
|
||
<string>${escapeXml(conn.email)}</string>
|
||
<key>EmailAccountType</key>
|
||
<string>EmailTypeIMAP</string>
|
||
<key>EmailAddress</key>
|
||
<string>${escapeXml(conn.email)}</string>
|
||
<key>IncomingMailServerHostName</key>
|
||
<string>imap.rebreak.org</string>
|
||
<key>IncomingMailServerPortNumber</key>
|
||
<integer>993</integer>
|
||
<key>IncomingMailServerUseSSL</key>
|
||
<true/>
|
||
<key>IncomingMailServerUsername</key>
|
||
<string>${escapeXml(account.proxyUsername)}</string>
|
||
<key>IncomingMailServerPassword</key>
|
||
<string>${escapeXml(proxyPassword)}</string>
|
||
<key>OutgoingMailServerHostName</key>
|
||
<string>${escapeXml(smtp.host)}</string>
|
||
<key>OutgoingMailServerPortNumber</key>
|
||
<integer>${smtp.port}</integer>
|
||
<key>OutgoingMailServerUseSSL</key>
|
||
<true/>
|
||
<key>OutgoingMailServerUsername</key>
|
||
<string>${escapeXml(conn.email)}</string>${realPassword ? `
|
||
<key>OutgoingMailServerPassword</key>
|
||
<string>${escapeXml(realPassword)}</string>` : ""}
|
||
<key>SMIMEEnabled</key>
|
||
<false/>
|
||
<key>PayloadDescription</key>
|
||
<string>Mail-Filter für ${escapeXml(conn.email)}</string>
|
||
<key>PayloadDisplayName</key>
|
||
<string>ReBreak – ${escapeXml(conn.email)}</string>
|
||
<key>PayloadIdentifier</key>
|
||
<string>org.rebreak.mail.${conn.id}</string>
|
||
<key>PayloadType</key>
|
||
<string>com.apple.mail.managed</string>
|
||
<key>PayloadUUID</key>
|
||
<string>${randomUUID()}</string>
|
||
<key>PayloadVersion</key>
|
||
<integer>1</integer>
|
||
</dict>`);
|
||
}
|
||
|
||
if (payloads.length === 0) {
|
||
throw createError({ statusCode: 400, message: "Proxy-Konten müssen zuerst neu erstellt werden" });
|
||
}
|
||
|
||
const plist = `<?xml version="1.0" encoding="UTF-8"?>
|
||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||
<plist version="1.0">
|
||
<dict>
|
||
<key>PayloadContent</key>
|
||
<array>
|
||
${payloads.join("\n ")}
|
||
</array>
|
||
<key>PayloadDescription</key>
|
||
<string>Blockiert Casino-Mails automatisch bevor sie in deinen Posteingang gelangen</string>
|
||
<key>PayloadDisplayName</key>
|
||
<string>ReBreak Mail Filter</string>
|
||
<key>PayloadIdentifier</key>
|
||
<string>org.rebreak.mail.profile.${user.id}</string>
|
||
<key>PayloadOrganization</key>
|
||
<string>ReBreak</string>
|
||
<key>PayloadRemovalDisallowed</key>
|
||
<false/>
|
||
<key>PayloadType</key>
|
||
<string>Configuration</string>
|
||
<key>PayloadUUID</key>
|
||
<string>${randomUUID()}</string>
|
||
<key>PayloadVersion</key>
|
||
<integer>1</integer>
|
||
</dict>
|
||
</plist>`;
|
||
|
||
setHeader(event, "Content-Type", "application/x-apple-aspen-config");
|
||
setHeader(event, "Content-Disposition", 'attachment; filename="rebreak-mail-filter.mobileconfig"');
|
||
return plist;
|
||
});
|