feat(mail): add smtp email delivery
This commit is contained in:
parent
faddaa91d0
commit
3456b04ed4
25 changed files with 529 additions and 60 deletions
94
components/admin/SmtpSettingsForm.tsx
Normal file
94
components/admin/SmtpSettingsForm.tsx
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
"use client";
|
||||
|
||||
import { useRef, useState, type FormEvent } from "react";
|
||||
import type { PublicSmtpSettings } from "@/lib/mail/types";
|
||||
|
||||
type ApiResponse = {
|
||||
message?: string;
|
||||
ok?: boolean;
|
||||
settings?: PublicSmtpSettings;
|
||||
};
|
||||
|
||||
export default function SmtpSettingsForm({ initialSettings, configured }: { initialSettings: PublicSmtpSettings; configured: boolean }) {
|
||||
const formRef = useRef<HTMLFormElement>(null);
|
||||
const [settings, setSettings] = useState(initialSettings);
|
||||
const [isConfigured, setIsConfigured] = useState(configured);
|
||||
const [message, setMessage] = useState("");
|
||||
const [error, setError] = useState("");
|
||||
const [pending, setPending] = useState(false);
|
||||
|
||||
async function submitForm(form: HTMLFormElement, action: "save" | "test") {
|
||||
setMessage("");
|
||||
setError("");
|
||||
setPending(true);
|
||||
|
||||
const formData = new FormData(form);
|
||||
formData.set("action", action);
|
||||
|
||||
try {
|
||||
const response = await fetch("/api/admin/smtp", { method: "POST", body: formData });
|
||||
const result = await response.json() as ApiResponse;
|
||||
if (result.settings) {
|
||||
setSettings(result.settings);
|
||||
setIsConfigured(Boolean(result.settings.host && result.settings.username && result.settings.hasPassword && result.settings.fromAddress && result.settings.recipientAddress));
|
||||
}
|
||||
if (!response.ok) throw new Error(result.message ?? "SMTP-Aktion fehlgeschlagen.");
|
||||
setMessage(result.message ?? "Aktion erfolgreich.");
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : "SMTP-Aktion fehlgeschlagen.");
|
||||
} finally {
|
||||
setPending(false);
|
||||
}
|
||||
}
|
||||
|
||||
function submit(event: FormEvent<HTMLFormElement>) {
|
||||
event.preventDefault();
|
||||
void submitForm(event.currentTarget, "save");
|
||||
}
|
||||
|
||||
function test() {
|
||||
if (formRef.current) void submitForm(formRef.current, "test");
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<section className="admin-card">
|
||||
<h2>Status</h2>
|
||||
<p className="admin-muted">SMTP ist {isConfigured ? "konfiguriert" : "nicht konfiguriert"}.</p>
|
||||
{settings.lastTestAt && <p>Letzte Testmail: {new Date(settings.lastTestAt).toLocaleString("de-DE")} ({settings.lastTestStatus})</p>}
|
||||
{settings.lastDeliveryAt && <p>Letzter Formularversand: {new Date(settings.lastDeliveryAt).toLocaleString("de-DE")} ({settings.lastDeliveryStatus})</p>}
|
||||
{settings.lastError && <p className="error">Letzter Fehler: {settings.lastError}</p>}
|
||||
<p className="notice">Für Apple Mail/iCloud bitte smtp.mail.me.com, Port 587, STARTTLS und ein app-spezifisches Passwort verwenden.</p>
|
||||
</section>
|
||||
|
||||
{message && <p className="success admin-message">{message}</p>}
|
||||
{error && <p className="error admin-message">{error}</p>}
|
||||
|
||||
<form ref={formRef} className="admin-card admin-form" onSubmit={submit}>
|
||||
<label>SMTP Host<input name="host" defaultValue={settings.host} placeholder="smtp.mail.me.com" /></label>
|
||||
<label>SMTP Port<input name="port" defaultValue={settings.port} inputMode="numeric" placeholder="587" /></label>
|
||||
<label>SMTP Benutzername<input name="username" defaultValue={settings.username} placeholder="name@example.com" /></label>
|
||||
<label>
|
||||
SMTP Passwort
|
||||
<input name="password" type="password" placeholder={settings.hasPassword ? "Passwort ist gesetzt" : "App-spezifisches Passwort"} autoComplete="new-password" />
|
||||
</label>
|
||||
<label>
|
||||
Verschlüsselung
|
||||
<select name="security" defaultValue={settings.security}>
|
||||
<option value="starttls">STARTTLS</option>
|
||||
<option value="tls">TLS</option>
|
||||
<option value="none">Keine</option>
|
||||
</select>
|
||||
</label>
|
||||
<label>Absenderadresse<input name="fromAddress" type="email" defaultValue={settings.fromAddress} /></label>
|
||||
<label>Antwortadresse<input name="replyToAddress" type="email" defaultValue={settings.replyToAddress} /></label>
|
||||
<label>Empfängeradresse<input name="recipientAddress" type="email" defaultValue={settings.recipientAddress} /></label>
|
||||
<label>BCC optional<input name="bccAddress" type="email" defaultValue={settings.bccAddress} /></label>
|
||||
<div className="actions">
|
||||
<button className="button" type="submit" disabled={pending}>Speichern</button>
|
||||
<button className="button light" type="button" disabled={pending} onClick={test}>Test-E-Mail senden</button>
|
||||
</div>
|
||||
</form>
|
||||
</>
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue