"use strict"; // ==================== PLESK EMAIL PROVIDER ==================== Object.defineProperty(exports, "__esModule", { value: true }); exports.PleskEmailProvider = void 0; const undici_1 = require("undici"); // Undici-Agent der selbstsignierte Zertifikate akzeptiert // Mit Timeouts und Connection-Limits um Probleme zu vermeiden const httpsAgent = new undici_1.Agent({ connect: { rejectUnauthorized: false, timeout: 10000, // 10 Sekunden Connect-Timeout }, bodyTimeout: 30000, // 30 Sekunden für Response-Body headersTimeout: 30000, // 30 Sekunden für Headers keepAliveTimeout: 1000, // Connections nach 1 Sekunde schließen keepAliveMaxTimeout: 5000, // Maximal 5 Sekunden Keep-Alive connections: 1, // Nur eine Connection gleichzeitig pro Host pipelining: 1, // Kein Pipelining }); class PleskEmailProvider { type = 'PLESK'; config; constructor(config) { this.config = config; } // Basis-URL für API-Requests get baseUrl() { // Entferne trailing slash falls vorhanden return this.config.apiUrl.replace(/\/$/, ''); } // HTTP-Request an Plesk API senden async request(method, endpoint, data) { const url = `${this.baseUrl}${endpoint}`; const headers = { 'Content-Type': 'application/json', Accept: 'application/json', }; // Authentifizierung: API-Key hat Priorität, sonst Basic Auth if (this.config.apiKey) { // Nur API-Key verwenden (ohne Basic Auth) headers['X-API-Key'] = this.config.apiKey; } else if (this.config.username && this.config.password) { // Basic Auth nur wenn kein API-Key const authHeader = Buffer.from(`${this.config.username}:${this.config.password}`).toString('base64'); headers['Authorization'] = `Basic ${authHeader}`; } else { // Keine Authentifizierung vorhanden throw new Error('Keine Zugangsdaten angegeben - bitte API-Key oder Benutzername/Passwort eingeben'); } const options = { method, headers, dispatcher: httpsAgent, }; if (data && (method === 'POST' || method === 'PUT')) { options.body = JSON.stringify(data); } try { const response = await (0, undici_1.fetch)(url, options); if (!response.ok) { const errorText = await response.text(); throw new Error(`Plesk API Fehler: ${response.status} - ${errorText}`); } // Leere Response bei DELETE if (response.status === 204) { return {}; } return await response.json(); } catch (error) { // Verbesserte Fehlermeldungen für häufige Probleme if (error instanceof Error) { const msg = error.message.toLowerCase(); // Netzwerkfehler if (msg.includes('econnrefused')) { throw new Error(`Server nicht erreichbar unter ${this.baseUrl} - Ist der Server gestartet?`); } if (msg.includes('enotfound') || msg.includes('getaddrinfo')) { throw new Error(`Server-Adresse nicht gefunden: ${this.baseUrl} - Bitte URL prüfen`); } if (msg.includes('etimedout') || msg.includes('timeout')) { throw new Error(`Zeitüberschreitung bei Verbindung zu ${this.baseUrl}`); } if (msg.includes('econnreset')) { throw new Error(`Verbindung wurde vom Server abgebrochen`); } // SSL/TLS Fehler if (msg.includes('cert') || msg.includes('ssl') || msg.includes('tls') || msg.includes('unable_to_verify')) { throw new Error(`SSL-Zertifikatsfehler - Selbstsigniertes Zertifikat wird nicht akzeptiert`); } // fetch failed ist meist ein Netzwerk/SSL Problem if (msg.includes('fetch failed')) { throw new Error(`Verbindung fehlgeschlagen zu ${this.baseUrl} - Bitte prüfen: Server erreichbar? HTTPS-Port korrekt?`); } } console.error('Plesk API Request failed:', error); throw error; } } async testConnection() { // Versuche Server-Info abzurufen - wirft Fehler bei Auth-Problemen try { await this.request('GET', '/api/v2/server'); } catch (error) { if (error instanceof Error) { // Verbesserte Fehlermeldung if (error.message.includes('401')) { throw new Error('Authentifizierung fehlgeschlagen - Benutzername/Passwort oder API-Key prüfen'); } if (error.message.includes('403')) { throw new Error('Zugriff verweigert - Berechtigungen prüfen'); } // Andere Fehler wurden schon in request() übersetzt } throw error; } } async emailExists(localPart) { const email = `${localPart}@${this.config.domain}`; try { // Plesk CLI API: Mail-Info abfragen const result = await this.request('POST', '/api/v2/cli/mail/call', { params: ['--info', email] }); // Debug: Response-Struktur loggen console.log('Plesk emailExists response:', JSON.stringify(result, null, 2)); // Plesk gibt code=0 bei Erfolg, code!=0 bei Fehler // stderr enthält Fehlermeldung wenn Mail nicht existiert const hasError = result.code !== 0 || result.stderr?.toLowerCase().includes('not found') || result.stderr?.toLowerCase().includes('does not exist') || result.stderr?.toLowerCase().includes('unable to find') || result.stderr?.toLowerCase().includes('no such'); if (hasError) { return { exists: false }; } // stdout sollte die Mail-Infos enthalten const exists = result.stdout?.toLowerCase().includes(localPart.toLowerCase()); // Mailbox-Status aus stdout parsen (Format: "Mailbox: true" oder "Mailbox: false") let hasMailbox; if (exists && result.stdout) { const mailboxMatch = result.stdout.match(/Mailbox:\s*(true|false)/i); if (mailboxMatch) { hasMailbox = mailboxMatch[1].toLowerCase() === 'true'; } } return { exists, email: exists ? email : undefined, hasMailbox, }; } catch (error) { // HTTP-Fehler oder Netzwerkfehler if (error instanceof Error) { const msg = error.message.toLowerCase(); // "not found" = Mail gibt es nicht if (msg.includes('not found') || msg.includes('does not exist') || msg.includes('unable to find')) { return { exists: false }; } } console.error('Plesk emailExists error:', error); return { exists: false }; } } async createEmail(params) { const { localPart, forwardTargets } = params; const email = `${localPart}@${this.config.domain}`; try { // Prüfen ob schon existiert const exists = await this.emailExists(localPart); if (exists.exists) { return { success: false, error: `E-Mail ${email} existiert bereits`, }; } // Plesk CLI API: Mail-Account mit Weiterleitung erstellen // Verwendet den CLI-Wrapper unter /api/v2/cli/mail/call // Format für -forwarding-addresses: "add:email1,email2" oder "set:email1,email2" await this.request('POST', '/api/v2/cli/mail/call', { params: [ '--create', email, '-forwarding', 'true', '-forwarding-addresses', `add:${forwardTargets.join(',')}`, '-mailbox', 'false', ], }); return { success: true, message: `E-Mail ${email} erfolgreich erstellt mit Weiterleitung an: ${forwardTargets.join(', ')}`, }; } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unbekannter Fehler'; console.error('Plesk createEmail error:', error); return { success: false, error: `Fehler beim Erstellen der E-Mail: ${errorMessage}`, }; } } async createEmailWithMailbox(params) { const { localPart, forwardTargets, password } = params; const email = `${localPart}@${this.config.domain}`; try { // Prüfen ob schon existiert const exists = await this.emailExists(localPart); if (exists.exists) { return { success: false, error: `E-Mail ${email} existiert bereits`, }; } // Plesk CLI API: Mail-Account mit echter Mailbox erstellen // -mailbox true: Echte Mailbox (IMAP/SMTP-Zugang) // -passwd: Passwort für die Mailbox // -forwarding true: Zusätzlich Weiterleitung aktivieren await this.request('POST', '/api/v2/cli/mail/call', { params: [ '--create', email, '-mailbox', 'true', '-passwd', password, '-forwarding', 'true', '-forwarding-addresses', `add:${forwardTargets.join(',')}`, ], }); return { success: true, message: `E-Mail ${email} mit Mailbox erfolgreich erstellt`, email, }; } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unbekannter Fehler'; console.error('Plesk createEmailWithMailbox error:', error); return { success: false, error: `Fehler beim Erstellen der E-Mail mit Mailbox: ${errorMessage}`, }; } } async enableMailboxForExisting(params) { const { localPart, password } = params; const email = `${localPart}@${this.config.domain}`; try { // Prüfen ob E-Mail existiert const exists = await this.emailExists(localPart); if (!exists.exists) { return { success: false, error: `E-Mail ${email} nicht gefunden`, }; } // Plesk CLI API: Mailbox für existierende E-Mail aktivieren // --update: Existierende E-Mail aktualisieren // -mailbox true: Mailbox aktivieren // -passwd: Passwort für die Mailbox setzen await this.request('POST', '/api/v2/cli/mail/call', { params: [ '--update', email, '-mailbox', 'true', '-passwd', password, ], }); return { success: true, message: `Mailbox für ${email} erfolgreich aktiviert`, }; } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unbekannter Fehler'; console.error('Plesk enableMailboxForExisting error:', error); return { success: false, error: `Fehler beim Aktivieren der Mailbox: ${errorMessage}`, }; } } async updateMailboxPassword(params) { const { localPart, password } = params; const email = `${localPart}@${this.config.domain}`; try { // Prüfen ob E-Mail existiert const exists = await this.emailExists(localPart); if (!exists.exists) { return { success: false, error: `E-Mail ${email} nicht gefunden`, }; } // Plesk CLI API: Passwort für existierende E-Mail aktualisieren // --update: Existierende E-Mail aktualisieren // -passwd: Neues Passwort setzen await this.request('POST', '/api/v2/cli/mail/call', { params: [ '--update', email, '-passwd', password, ], }); return { success: true, message: `Passwort für ${email} erfolgreich aktualisiert`, }; } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unbekannter Fehler'; console.error('Plesk updateMailboxPassword error:', error); return { success: false, error: `Fehler beim Aktualisieren des Passworts: ${errorMessage}`, }; } } async deleteEmail(localPart) { const email = `${localPart}@${this.config.domain}`; try { // Prüfen ob Mail existiert const exists = await this.emailExists(localPart); if (!exists.exists) { return { success: false, error: `E-Mail ${email} nicht gefunden`, }; } // Plesk CLI API: Mail-Account löschen await this.request('POST', '/api/v2/cli/mail/call', { params: ['--remove', email], }); return { success: true, message: `E-Mail ${email} erfolgreich gelöscht`, }; } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unbekannter Fehler'; console.error('Plesk deleteEmail error:', error); return { success: false, error: `Fehler beim Löschen der E-Mail: ${errorMessage}`, }; } } async renameEmail(params) { const { oldLocalPart, newLocalPart } = params; const oldEmail = `${oldLocalPart}@${this.config.domain}`; const newEmail = `${newLocalPart}@${this.config.domain}`; try { // Prüfen ob alte Mail existiert const oldExists = await this.emailExists(oldLocalPart); if (!oldExists.exists) { return { success: false, error: `E-Mail ${oldEmail} nicht gefunden`, }; } // Prüfen ob neue Adresse schon existiert const newExists = await this.emailExists(newLocalPart); if (newExists.exists) { return { success: false, error: `E-Mail ${newEmail} existiert bereits`, }; } // Plesk CLI API: Mail-Account umbenennen await this.request('POST', '/api/v2/cli/mail/call', { params: ['--rename', oldEmail, '-new-name', newLocalPart], }); return { success: true, message: `E-Mail erfolgreich umbenannt von ${oldEmail} zu ${newEmail}`, }; } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unbekannter Fehler'; console.error('Plesk renameEmail error:', error); return { success: false, error: `Fehler beim Umbenennen der E-Mail: ${errorMessage}`, }; } } async updateForwardTargets(localPart, targets) { const email = `${localPart}@${this.config.domain}`; try { // Prüfen ob Mail existiert const exists = await this.emailExists(localPart); if (!exists.exists) { return { success: false, error: `E-Mail ${email} nicht gefunden`, }; } // Plesk CLI API: Weiterleitungsziele aktualisieren // Format für -forwarding-addresses: "set:email1,email2" ersetzt alle Adressen await this.request('POST', '/api/v2/cli/mail/call', { params: [ '--update', email, '-forwarding', 'true', '-forwarding-addresses', `set:${targets.join(',')}`, ], }); return { success: true, message: `Weiterleitungen für ${email} aktualisiert: ${targets.join(', ')}`, }; } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unbekannter Fehler'; console.error('Plesk updateForwardTargets error:', error); return { success: false, error: `Fehler beim Aktualisieren der Weiterleitungen: ${errorMessage}`, }; } } } exports.PleskEmailProvider = PleskEmailProvider; //# sourceMappingURL=pleskProvider.js.map