funktechnik-schubert-website/lib/mail/smtp.ts
2026-07-04 00:06:20 +02:00

100 lines
3.3 KiB
TypeScript

import nodemailer from "nodemailer";
import type SMTPTransport from "nodemailer/lib/smtp-transport";
import type { SmtpSettings } from "@/lib/admin/types";
import { getSmtpSettings, isSmtpConfigured, updateSmtpDeliveryStatus, updateSmtpTestStatus } from "./config";
import { contactTemplate, repairTemplate, testTemplate } from "./templates";
import type { ContactMailInput, MailSendResult, RepairMailInput } from "./types";
function sanitizeMailError(error: unknown) {
const message = error instanceof Error ? error.message : "Unbekannter SMTP-Fehler";
return message
.replace(/AUTH PLAIN\s+\S+/gi, "AUTH PLAIN [redacted]")
.replace(/AUTH LOGIN\s+\S+/gi, "AUTH LOGIN [redacted]")
.replace(/password[=:]\S+/gi, "password=[redacted]")
.slice(0, 500);
}
function createTransport(settings: SmtpSettings) {
const secure = settings.security === "tls";
const requireTLS = settings.security === "starttls";
const options: SMTPTransport.Options = {
host: settings.host,
port: Number(settings.port),
secure,
requireTLS,
auth: {
user: settings.username,
pass: settings.password,
},
};
if (settings.security === "none") {
options.auth = settings.username && settings.password ? options.auth : undefined;
options.ignoreTLS = true;
}
return nodemailer.createTransport(options);
}
async function sendConfiguredMail(input: {
subject: string;
text: string;
html: string;
replyTo?: string;
}): Promise<MailSendResult> {
const settings = await getSmtpSettings();
if (!isSmtpConfigured(settings)) return { ok: false, error: "SMTP nicht konfiguriert." };
try {
const transport = createTransport(settings);
await transport.sendMail({
from: settings.fromAddress,
to: settings.recipientAddress,
bcc: settings.bccAddress || undefined,
replyTo: input.replyTo || settings.replyToAddress || undefined,
subject: input.subject,
text: input.text,
html: input.html,
});
return { ok: true };
} catch (error) {
return { ok: false, error: sanitizeMailError(error) };
}
}
export async function sendTestMail() {
const template = testTemplate();
const result = await sendConfiguredMail(template);
await updateSmtpTestStatus({
lastTestAt: new Date().toISOString(),
lastTestStatus: result.ok ? "success" : "error",
lastError: result.ok ? "" : result.error,
});
return result;
}
export async function sendContactInquiryMail(input: ContactMailInput) {
const template = contactTemplate(input);
const result = await sendConfiguredMail({ ...template, replyTo: input.email });
if (result.error !== "SMTP nicht konfiguriert.") {
await updateSmtpDeliveryStatus({
lastDeliveryAt: new Date().toISOString(),
lastDeliveryStatus: result.ok ? "success" : "error",
lastError: result.ok ? "" : result.error,
});
}
return result;
}
export async function sendRepairInquiryMail(input: RepairMailInput) {
const template = repairTemplate(input);
const result = await sendConfiguredMail({ ...template, replyTo: input.email });
if (result.error !== "SMTP nicht konfiguriert.") {
await updateSmtpDeliveryStatus({
lastDeliveryAt: new Date().toISOString(),
lastDeliveryStatus: result.ok ? "success" : "error",
lastError: result.ok ? "" : result.error,
});
}
return result;
}