MBO-Tech-IT-Webseite/lib/mailer.ts

108 lines
3.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import nodemailer from "nodemailer";
import { queueEmail } from "./email-queue";
// Port 587 = STARTTLS, Port 465 = SSL/TLS
const transporter = nodemailer.createTransport({
host: process.env.SMTP_HOST,
port: Number(process.env.SMTP_PORT ?? 587),
secure: false,
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASS,
},
connectionTimeout: 15000,
greetingTimeout: 10000,
socketTimeout: 20000,
tls: {
rejectUnauthorized: false,
ciphers: "SSLv3",
},
});
export interface KontaktEmailData {
name: string;
anrede?: string;
telefon: string;
email: string;
betreff: string;
nachricht?: string;
}
interface MailOptions {
from: string;
to: string | undefined;
replyTo?: string;
subject: string;
text: string;
html: string;
}
async function sendWithFallback(options: MailOptions, label: string) {
if (!options.to) {
console.error(`[Mailer] Kein Empfänger für "${label}" Mail übersprungen`);
return;
}
try {
await transporter.sendMail(options);
console.log(`[Mailer] ✓ Mail "${label}" an "${options.to}" gesendet`);
} catch (err) {
const msg = err instanceof Error ? err.message : String(err);
console.error(`[Mailer] ✗ Mail "${label}" fehlgeschlagen (${msg}) in Queue gespeichert`);
await queueEmail({
mail_from: options.from,
mail_to: options.to,
reply_to: options.replyTo,
subject: options.subject,
html: options.html,
body_text: options.text,
});
}
}
export async function sendeKontaktEmail(data: KontaktEmailData) {
const anrede = data.anrede
? `${data.anrede.charAt(0).toUpperCase() + data.anrede.slice(1)} `
: "";
const html = `
<!DOCTYPE html>
<html lang="de">
<head><meta charset="UTF-8"></head>
<body style="font-family:system-ui,sans-serif;color:#e2e8f0;max-width:600px;margin:0 auto;padding:0">
<div style="background:#18212f;padding:20px 24px;border-bottom:2px solid #f97316">
<h1 style="color:#f97316;margin:0;font-size:20px;font-weight:700">MBO Tech IT</h1>
<p style="color:rgba(255,255,255,0.6);margin:4px 0 0;font-size:13px">Neue Kontaktanfrage</p>
</div>
<div style="padding:24px;background:#1e2a3b">
<h2 style="margin:0 0 16px;font-size:18px;color:#f8fafc">Kontaktanfrage von ${anrede}${data.name}</h2>
<table style="width:100%;border-collapse:collapse;margin-bottom:24px">
<tr><td style="padding:6px 0;color:#94a3b8;width:120px">Name</td><td style="padding:6px 0;font-weight:600;color:#f8fafc">${anrede}${data.name}</td></tr>
<tr><td style="padding:6px 0;color:#94a3b8">Telefon</td><td style="padding:6px 0"><a href="tel:${data.telefon}" style="color:#f97316">${data.telefon}</a></td></tr>
<tr><td style="padding:6px 0;color:#94a3b8">E-Mail</td><td style="padding:6px 0"><a href="mailto:${data.email}" style="color:#60a5fa">${data.email}</a></td></tr>
<tr><td style="padding:6px 0;color:#94a3b8">Betreff</td><td style="padding:6px 0;color:#f8fafc">${data.betreff}</td></tr>
</table>
${
data.nachricht
? `<div style="padding:12px 16px;background:#111925;border-left:3px solid #f97316"><p style="margin:0;font-size:14px;white-space:pre-wrap;color:#cbd5e1">${data.nachricht}</p></div>`
: ""
}
</div>
<div style="padding:12px 24px;background:#111925;border-top:1px solid rgba(255,255,255,0.1)">
<p style="margin:0;font-size:11px;color:#64748b">MBO Tech IT · ${process.env.APP_URL ?? "https://mbo-tech-it.de"}</p>
</div>
</body>
</html>`;
await sendWithFallback(
{
from: `"MBO Tech IT" <${process.env.SMTP_FROM}>`,
to: process.env.SMTP_TO,
replyTo: data.email,
subject: `Kontaktanfrage: ${anrede}${data.name} ${data.betreff}`,
text: `Neue Kontaktanfrage\n\nName: ${anrede}${data.name}\nTelefon: ${data.telefon}\nE-Mail: ${data.email}\nBetreff: ${data.betreff}${data.nachricht ? `\n\nNachricht:\n${data.nachricht}` : ""}`,
html,
},
`Kontaktanfrage ${data.name}`
);
}