import nodemailer from 'nodemailer' const SMTP_HOST = process.env.SMTP_HOST const SMTP_PORT = parseInt(process.env.SMTP_PORT || '587', 10) const SMTP_USER = process.env.SMTP_USER const SMTP_PASS = process.env.SMTP_PASS const STAKEHOLDER_EMAIL = process.env.STAKEHOLDER_EMAIL || 'knie@d-hive.de' const BASE_URL = process.env.BASE_URL || 'https://andreknie.de' let transporter = null function getTransporter() { if (!transporter && SMTP_HOST && SMTP_USER && SMTP_PASS) { transporter = nodemailer.createTransport({ host: SMTP_HOST, port: SMTP_PORT, secure: SMTP_PORT === 465, auth: { user: SMTP_USER, pass: SMTP_PASS }, }) } return transporter } export async function sendConfirmationEmail(to, type, token) { const t = getTransporter() if (!t) { console.log(`[Mailer] SMTP not configured. Would send ${type} confirmation to ${to}`) return } const confirmUrl = `${BASE_URL}/api/${type}/confirm/${token}` const subjects = { contact: 'Bitte bestätige deine Kontaktanfrage', 'talk-request': 'Bitte bestätige deine Vortragsanfrage', newsletter: 'Bitte bestätige dein Newsletter-Abo', } await t.sendMail({ from: SMTP_USER, to, subject: subjects[type] || 'Bestätigung erforderlich', text: `Bitte bestätige deine Anfrage:\n\n${confirmUrl}\n\nDieser Link ist 48 Stunden gültig.`, }) } export async function sendStakeholderNotification(type, data) { const t = getTransporter() if (!t) { console.log(`[Mailer] SMTP not configured. Would notify stakeholder about ${type}`) return } const subjects = { contact: `Neue Kontaktanfrage von ${data.name}`, 'talk-request': `Neue Vortragsanfrage von ${data.name}`, } const body = Object.entries(data) .map(([key, val]) => `${key}: ${val}`) .join('\n') await t.sendMail({ from: SMTP_USER, to: STAKEHOLDER_EMAIL, subject: subjects[type] || `Neue Anfrage (${type})`, text: body, }) } export { STAKEHOLDER_EMAIL, BASE_URL } /** * Send the speaker CV PDF as an attachment to the requester, and notify the * stakeholder about the lead. If the PDF is missing, the stakeholder is still * notified so the CV can be sent manually. * @returns {{ sent: boolean, pdfMissing: boolean }} */ export async function sendSpeakerCv(to, lead, pdfPath) { const { existsSync } = await import('fs') const t = getTransporter() const pdfMissing = !pdfPath || !existsSync(pdfPath) if (!t) { console.log(`[Mailer] SMTP not configured. Would send speaker CV to ${to} (pdfMissing=${pdfMissing})`) await notifyStakeholderSpeakerCv(lead, pdfMissing) return { sent: false, pdfMissing } } if (!pdfMissing) { await t.sendMail({ from: SMTP_USER, to, subject: 'Dein Speaker CV von Dr. Andre Knie', text: `Hallo ${lead.name},\n\nvielen Dank für dein Interesse. Im Anhang findest du meinen Speaker CV.\n\nBeste Grüße\nAndre Knie`, attachments: [{ filename: 'Speaker-CV-Andre-Knie.pdf', path: pdfPath }], }) } await notifyStakeholderSpeakerCv(lead, pdfMissing) return { sent: !pdfMissing, pdfMissing } } async function notifyStakeholderSpeakerCv(lead, pdfMissing) { const t = getTransporter() const body = [ `Name: ${lead.name}`, `E-Mail: ${lead.email}`, `Nachricht: ${lead.message}`, `Zeitpunkt: ${lead.timestamp}`, pdfMissing ? 'ACHTUNG: PDF fehlte — CV wurde NICHT automatisch versandt, bitte manuell senden.' : 'CV wurde automatisch an den Anfragenden gesendet.', ].join('\n') if (!t) { console.log(`[Mailer] SMTP not configured. Would notify stakeholder about speaker-cv lead:\n${body}`) return } await t.sendMail({ from: SMTP_USER, to: STAKEHOLDER_EMAIL, subject: `Speaker-CV-Anfrage von ${lead.name}`, text: body, }) }