"use strict"; // ==================== EMAIL PROVIDER SERVICE ==================== Object.defineProperty(exports, "__esModule", { value: true }); exports.getAllProviderConfigs = getAllProviderConfigs; exports.getProviderConfigById = getProviderConfigById; exports.getDefaultProviderConfig = getDefaultProviderConfig; exports.getActiveProviderConfig = getActiveProviderConfig; exports.createProviderConfig = createProviderConfig; exports.updateProviderConfig = updateProviderConfig; exports.deleteProviderConfig = deleteProviderConfig; exports.checkEmailExists = checkEmailExists; exports.provisionEmail = provisionEmail; exports.provisionEmailWithMailbox = provisionEmailWithMailbox; exports.enableMailboxForExistingEmail = enableMailboxForExistingEmail; exports.updateMailboxPassword = updateMailboxPassword; exports.getImapSmtpSettings = getImapSmtpSettings; exports.deprovisionEmail = deprovisionEmail; exports.renameProvisionedEmail = renameProvisionedEmail; exports.getProviderDomain = getProviderDomain; exports.testProviderConnection = testProviderConnection; const client_1 = require("@prisma/client"); const encryption_js_1 = require("../../utils/encryption.js"); const pleskProvider_js_1 = require("./pleskProvider.js"); const prisma = new client_1.PrismaClient(); // Factory-Funktion um den richtigen Provider zu erstellen function createProvider(config) { switch (config.type) { case 'PLESK': return new pleskProvider_js_1.PleskEmailProvider(config); case 'CPANEL': // TODO: cPanel Provider implementieren throw new Error('cPanel Provider noch nicht implementiert'); case 'DIRECTADMIN': // TODO: DirectAdmin Provider implementieren throw new Error('DirectAdmin Provider noch nicht implementiert'); default: throw new Error(`Unbekannter Provider-Typ: ${config.type}`); } } // ==================== CONFIG CRUD ==================== async function getAllProviderConfigs() { return prisma.emailProviderConfig.findMany({ orderBy: [{ isDefault: 'desc' }, { name: 'asc' }], }); } async function getProviderConfigById(id) { return prisma.emailProviderConfig.findUnique({ where: { id }, }); } async function getDefaultProviderConfig() { return prisma.emailProviderConfig.findFirst({ where: { isActive: true, isDefault: true }, }); } async function getActiveProviderConfig() { // Erst Default-Provider versuchen, dann irgendeinen aktiven const defaultProvider = await getDefaultProviderConfig(); if (defaultProvider) return defaultProvider; return prisma.emailProviderConfig.findFirst({ where: { isActive: true }, }); } async function createProviderConfig(data) { // Falls isDefault=true, alle anderen auf false setzen if (data.isDefault) { await prisma.emailProviderConfig.updateMany({ where: { isDefault: true }, data: { isDefault: false }, }); } // Passwort verschlüsseln falls vorhanden const { encrypt } = await import('../../utils/encryption.js'); const passwordEncrypted = data.password ? encrypt(data.password) : null; return prisma.emailProviderConfig.create({ data: { name: data.name, type: data.type, apiUrl: data.apiUrl, apiKey: data.apiKey || null, username: data.username || null, passwordEncrypted, domain: data.domain, defaultForwardEmail: data.defaultForwardEmail || null, imapEncryption: data.imapEncryption ?? 'SSL', smtpEncryption: data.smtpEncryption ?? 'SSL', allowSelfSignedCerts: data.allowSelfSignedCerts ?? false, isActive: data.isActive ?? true, isDefault: data.isDefault ?? false, }, }); } async function updateProviderConfig(id, data) { // Falls isDefault=true, alle anderen auf false setzen if (data.isDefault) { await prisma.emailProviderConfig.updateMany({ where: { isDefault: true, id: { not: id } }, data: { isDefault: false }, }); } const updateData = {}; if (data.name !== undefined) updateData.name = data.name; if (data.type !== undefined) updateData.type = data.type; if (data.apiUrl !== undefined) updateData.apiUrl = data.apiUrl; if (data.apiKey !== undefined) updateData.apiKey = data.apiKey || null; if (data.username !== undefined) updateData.username = data.username || null; if (data.domain !== undefined) updateData.domain = data.domain; if (data.defaultForwardEmail !== undefined) updateData.defaultForwardEmail = data.defaultForwardEmail || null; if (data.imapEncryption !== undefined) updateData.imapEncryption = data.imapEncryption; if (data.smtpEncryption !== undefined) updateData.smtpEncryption = data.smtpEncryption; if (data.allowSelfSignedCerts !== undefined) updateData.allowSelfSignedCerts = data.allowSelfSignedCerts; if (data.isActive !== undefined) updateData.isActive = data.isActive; if (data.isDefault !== undefined) updateData.isDefault = data.isDefault; // Passwort-Logik: // - Wenn neues Passwort übergeben → verschlüsseln und speichern // - Wenn Benutzername gelöscht wird → Passwort auch löschen (gehören zusammen) if (data.password) { const { encrypt } = await import('../../utils/encryption.js'); updateData.passwordEncrypted = encrypt(data.password); } else if (data.username !== undefined && !data.username) { // Benutzername wird gelöscht → Passwort auch löschen updateData.passwordEncrypted = null; } return prisma.emailProviderConfig.update({ where: { id }, data: updateData, }); } async function deleteProviderConfig(id) { return prisma.emailProviderConfig.delete({ where: { id }, }); } // ==================== EMAIL OPERATIONS ==================== // Provider-Instanz aus DB-Config erstellen async function getProviderInstance() { const dbConfig = await getActiveProviderConfig(); if (!dbConfig) { throw new Error('Kein aktiver Email-Provider konfiguriert'); } // Passwort entschlüsseln let password; if (dbConfig.passwordEncrypted) { try { password = (0, encryption_js_1.decrypt)(dbConfig.passwordEncrypted); } catch { console.error('Konnte Passwort nicht entschlüsseln'); } } const config = { id: dbConfig.id, name: dbConfig.name, type: dbConfig.type, apiUrl: dbConfig.apiUrl, apiKey: dbConfig.apiKey || undefined, username: dbConfig.username || undefined, password, domain: dbConfig.domain, defaultForwardEmail: dbConfig.defaultForwardEmail || undefined, imapServer: dbConfig.imapServer || undefined, imapPort: dbConfig.imapPort || undefined, smtpServer: dbConfig.smtpServer || undefined, smtpPort: dbConfig.smtpPort || undefined, imapEncryption: dbConfig.imapEncryption, smtpEncryption: dbConfig.smtpEncryption, allowSelfSignedCerts: dbConfig.allowSelfSignedCerts, isActive: dbConfig.isActive, isDefault: dbConfig.isDefault, }; return createProvider(config); } // Prüfen ob eine E-Mail existiert async function checkEmailExists(localPart) { try { const provider = await getProviderInstance(); return provider.emailExists(localPart); } catch (error) { console.error('checkEmailExists error:', error); return { exists: false }; } } // E-Mail erstellen mit Weiterleitungen async function provisionEmail(localPart, customerEmail) { try { const provider = await getProviderInstance(); const config = await getActiveProviderConfig(); // Weiterleitungsziele zusammenstellen const forwardTargets = [customerEmail]; // Unsere eigene Weiterleitungsadresse hinzufügen falls konfiguriert if (config?.defaultForwardEmail) { forwardTargets.push(config.defaultForwardEmail); } // Prüfen ob existiert const exists = await provider.emailExists(localPart); if (exists.exists) { return { success: true, message: `E-Mail ${exists.email} existiert bereits`, }; } // Erstellen const result = await provider.createEmail({ localPart, forwardTargets, }); return result; } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unbekannter Fehler'; return { success: false, error: errorMessage, }; } } // E-Mail mit echter Mailbox erstellen (IMAP/SMTP-Zugang) async function provisionEmailWithMailbox(localPart, customerEmail, password) { try { const provider = await getProviderInstance(); const config = await getActiveProviderConfig(); // Weiterleitungsziele zusammenstellen const forwardTargets = [customerEmail]; // Unsere eigene Weiterleitungsadresse hinzufügen falls konfiguriert if (config?.defaultForwardEmail) { forwardTargets.push(config.defaultForwardEmail); } // Prüfen ob existiert const exists = await provider.emailExists(localPart); if (exists.exists) { return { success: true, message: `E-Mail ${exists.email} existiert bereits`, email: exists.email, }; } // Mit Mailbox erstellen const result = await provider.createEmailWithMailbox({ localPart, forwardTargets, password, }); return result; } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unbekannter Fehler'; return { success: false, error: errorMessage, }; } } // Mailbox für existierende E-Mail-Weiterleitung aktivieren async function enableMailboxForExistingEmail(localPart, password) { try { const provider = await getProviderInstance(); const result = await provider.enableMailboxForExisting({ localPart, password, }); return result; } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unbekannter Fehler'; return { success: false, error: errorMessage, }; } } // Mailbox-Passwort beim Provider aktualisieren async function updateMailboxPassword(localPart, password) { try { const provider = await getProviderInstance(); const result = await provider.updateMailboxPassword({ localPart, password, }); return result; } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unbekannter Fehler'; return { success: false, error: errorMessage, }; } } async function getImapSmtpSettings() { const config = await getActiveProviderConfig(); if (!config) return null; // Default-Server: Hostname aus der apiUrl extrahieren (z.B. rs001871.fastrootserver.de aus https://rs001871.fastrootserver.de:8443) // Der Plesk-Server ist gleichzeitig der Mail-Server let defaultServer; try { const url = new URL(config.apiUrl); defaultServer = url.hostname; } catch { // Fallback falls apiUrl ungültig defaultServer = `mail.${config.domain}`; } // Verschlüsselungs-Einstellungen const imapEncryption = (config.imapEncryption ?? 'SSL'); const smtpEncryption = (config.smtpEncryption ?? 'SSL'); // Ports basierend auf Verschlüsselung berechnen: // SSL: IMAP 993, SMTP 465 // STARTTLS: IMAP 143, SMTP 587 // NONE: IMAP 143, SMTP 25 // // Standard-Ports werden IMMER basierend auf Verschlüsselung berechnet. // Nur benutzerdefinierte Ports (nicht 993/143/465/587/25) werden aus der DB übernommen. const getImapPort = (enc, storedPort) => { const standardPorts = [993, 143]; // Wenn ein nicht-standard Port gespeichert ist, diesen verwenden if (storedPort && !standardPorts.includes(storedPort)) { return storedPort; } // Sonst basierend auf Verschlüsselung return enc === 'SSL' ? 993 : 143; }; const getSmtpPort = (enc, storedPort) => { const standardPorts = [465, 587, 25]; // Wenn ein nicht-standard Port gespeichert ist, diesen verwenden if (storedPort && !standardPorts.includes(storedPort)) { return storedPort; } // Sonst basierend auf Verschlüsselung if (enc === 'SSL') return 465; if (enc === 'STARTTLS') return 587; return 25; // NONE }; return { imapServer: config.imapServer || defaultServer, imapPort: getImapPort(imapEncryption, config.imapPort), imapEncryption, smtpServer: config.smtpServer || defaultServer, smtpPort: getSmtpPort(smtpEncryption, config.smtpPort), smtpEncryption, allowSelfSignedCerts: config.allowSelfSignedCerts ?? false, domain: config.domain, }; } // E-Mail löschen async function deprovisionEmail(localPart) { try { const provider = await getProviderInstance(); return provider.deleteEmail(localPart); } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unbekannter Fehler'; return { success: false, error: errorMessage, }; } } // E-Mail umbenennen async function renameProvisionedEmail(oldLocalPart, newLocalPart) { try { const provider = await getProviderInstance(); return provider.renameEmail({ oldLocalPart, newLocalPart }); } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unbekannter Fehler'; return { success: false, error: errorMessage, }; } } // Domain aus aktivem Provider holen async function getProviderDomain() { const config = await getActiveProviderConfig(); return config?.domain || null; } // Provider-Instanz aus übergebener Config erstellen (für Tests mit ungespeicherten Daten) function createProviderFromFormData(data) { const config = { id: 0, name: 'Test', type: data.type, apiUrl: data.apiUrl, apiKey: data.apiKey, username: data.username, password: data.password, domain: data.domain, isActive: true, isDefault: false, }; return createProvider(config); } // Provider-Instanz aus DB-Config per ID erstellen async function getProviderInstanceById(id) { const dbConfig = await getProviderConfigById(id); if (!dbConfig) { throw new Error('Email-Provider nicht gefunden'); } // Passwort entschlüsseln let password; if (dbConfig.passwordEncrypted) { try { password = (0, encryption_js_1.decrypt)(dbConfig.passwordEncrypted); } catch { console.error('Konnte Passwort nicht entschlüsseln'); } } const config = { id: dbConfig.id, name: dbConfig.name, type: dbConfig.type, apiUrl: dbConfig.apiUrl, apiKey: dbConfig.apiKey || undefined, username: dbConfig.username || undefined, password, domain: dbConfig.domain, defaultForwardEmail: dbConfig.defaultForwardEmail || undefined, imapServer: dbConfig.imapServer || undefined, imapPort: dbConfig.imapPort || undefined, smtpServer: dbConfig.smtpServer || undefined, smtpPort: dbConfig.smtpPort || undefined, imapEncryption: dbConfig.imapEncryption, smtpEncryption: dbConfig.smtpEncryption, allowSelfSignedCerts: dbConfig.allowSelfSignedCerts, isActive: dbConfig.isActive, isDefault: dbConfig.isDefault, }; return createProvider(config); } // Provider-Verbindung testen (mit ID, Formulardaten oder Default-Provider) async function testProviderConnection(options) { try { let provider; if (options?.testData) { // Mit übergebenen Daten testen (z.B. aus Modal beim Neuanlegen) provider = createProviderFromFormData(options.testData); } else if (options?.id) { // Gespeicherten Provider per ID testen provider = await getProviderInstanceById(options.id); } else { // Default-Provider testen provider = await getProviderInstance(); } // Expliziter Verbindungstest (wirft Fehler bei Auth-Problemen) await provider.testConnection(); return { success: true, message: 'Verbindung zum Email-Provider erfolgreich', }; } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unbekannter Fehler'; return { success: false, error: errorMessage, }; } } //# sourceMappingURL=emailProviderService.js.map