'use client'; import { useEffect, useRef, useState } from 'react'; import { useTranslations } from 'next-intl'; import { fetchSmtp, saveSmtp, testSmtp, type SaveSmtpPayload, } from '@/lib/settings-api'; // Encryption options — technical terms, not translated const ENCRYPTION_OPTIONS = [ { value: 'none', label: 'Keine' }, { value: 'starttls', label: 'STARTTLS' }, { value: 'ssl-tls', label: 'SSL-TLS' }, ] as const; interface FormState { host: string; port: number; encryption: 'none' | 'starttls' | 'ssl-tls'; username: string; password: string; // T-07-17: always starts blank; never pre-filled from server fromAddress: string; } const DEFAULT_FORM: FormState = { host: '', port: 587, encryption: 'starttls', username: '', password: '', fromAddress: '', }; type TestFeedback = | { type: 'loading'; message: string } | { type: 'success'; message: string } | { type: 'error'; message: string } | null; /** * SMTP configuration form for /settings/general/smtp (Surface C, DKV-05). * * Loads existing config via GET /settings/smtp on mount. * Password is NEVER pre-filled (T-07-17) — only sent when the user types one. * Connection test feedback auto-clears after 6 seconds. */ export function SmtpSettingsForm() { const t = useTranslations('settings'); const [form, setForm] = useState(DEFAULT_FORM); const [isSaving, setIsSaving] = useState(false); const [isTesting, setIsTesting] = useState(false); const [showPassword, setShowPassword] = useState(false); const [testFeedback, setTestFeedback] = useState(null); const clearTimerRef = useRef | null>(null); // Load existing config on mount useEffect(() => { fetchSmtp() .then((config) => { if (config) { setForm({ host: config.host, port: config.port, encryption: config.encryption, username: config.username ?? '', password: '', // T-07-17: never pre-filled fromAddress: config.fromAddress, }); } }) .catch(() => { // Silent fail — user can still enter config manually }); }, []); // Clear any pending auto-dismiss timer on unmount useEffect(() => { return () => { if (clearTimerRef.current) clearTimeout(clearTimerRef.current); }; }, []); const buildPayload = (): SaveSmtpPayload => { const payload: SaveSmtpPayload = { host: form.host, port: form.port, encryption: form.encryption, fromAddress: form.fromAddress, }; if (form.username.trim()) payload.username = form.username.trim(); // T-07-17: only include password when user has typed a new one if (form.password) payload.password = form.password; return payload; }; const handleSave = async (e: React.FormEvent) => { e.preventDefault(); setIsSaving(true); try { await saveSmtp(buildPayload()); } catch { // Silent fail for now — future: inline error state } finally { setIsSaving(false); } }; const handleTest = async () => { if (clearTimerRef.current) clearTimeout(clearTimerRef.current); setIsTesting(true); setTestFeedback({ type: 'loading', message: t('smtp.testTesting') }); try { const result = await testSmtp(buildPayload()); if (result.success && result.warning === 'no_auth') { setTestFeedback({ type: 'error', message: t('smtp.testNoAuth') }); } else if (result.success) { setTestFeedback({ type: 'success', message: t('smtp.testSuccess') }); } else { setTestFeedback({ type: 'error', message: t('smtp.testFailed') }); } } catch { setTestFeedback({ type: 'error', message: t('smtp.testFailed') }); } finally { setIsTesting(false); // Auto-clear after 6 seconds clearTimerRef.current = setTimeout(() => setTestFeedback(null), 6000); } }; const inputClass = 'h-9 w-full max-w-md rounded border border-border bg-background px-3 text-sm text-foreground'; const labelClass = 'mb-1 block text-sm text-foreground'; return (
{/* Host */}
setForm((prev) => ({ ...prev, host: e.target.value })) } />
{/* Port */}
setForm((prev) => ({ ...prev, port: Number(e.target.value) || 587, })) } />
{/* Verschlüsselung */}
{/* Benutzername */}
setForm((prev) => ({ ...prev, username: e.target.value })) } />
{/* Passwort + show/hide toggle */}
setForm((prev) => ({ ...prev, password: e.target.value })) } />
{/* Absenderadresse */}
setForm((prev) => ({ ...prev, fromAddress: e.target.value })) } />

{t('smtp.fromAddressHelp')}

{/* Action row */}
{/* Connection test feedback */} {testFeedback && (

{testFeedback.message}

)}
); }