import fs from 'fs/promises' import path from 'path' import { getUserFromToken, hasAnyRole } from '../../../utils/auth.js' import { getRecipientsByGroup, getNewsletterSubscribers, generateUnsubscribeToken } from '../../../utils/newsletter.js' import nodemailer from 'nodemailer' const getDataPath = (filename) => { const cwd = process.cwd() if (cwd.endsWith('.output')) { return path.join(cwd, '../server/data', filename) } return path.join(cwd, 'server/data', filename) } const NEWSLETTERS_FILE = getDataPath('newsletters.json') async function readNewsletters() { try { const data = await fs.readFile(NEWSLETTERS_FILE, 'utf-8') return JSON.parse(data) } catch (error) { if (error.code === 'ENOENT') { return [] } throw error } } async function writeNewsletters(newsletters) { await fs.writeFile(NEWSLETTERS_FILE, JSON.stringify(newsletters, null, 2), 'utf-8') } // Lädt Config für Logo und Clubname async function loadConfig() { try { const configPath = getDataPath('config.json') const data = await fs.readFile(configPath, 'utf-8') return JSON.parse(data) } catch { return { verein: { name: 'Harheimer Tischtennis-Club 1954 e.V.' } } } } // Erstellt Newsletter-HTML mit Header und Footer async function createNewsletterHTML(newsletter, unsubscribeToken = null) { const config = await loadConfig() const clubName = config.verein?.name || 'Harheimer Tischtennis-Club 1954 e.V.' const baseUrl = process.env.NUXT_PUBLIC_BASE_URL || 'http://localhost:3100' let unsubscribeLink = '' if (unsubscribeToken) { const unsubscribeUrl = `${baseUrl}/newsletter/unsubscribe?token=${unsubscribeToken}` unsubscribeLink = `

Sie erhalten diese E-Mail, weil Sie sich für unseren Newsletter angemeldet haben.

Newsletter abmelden

` } return `

${clubName}

${newsletter.title}

${newsletter.content}
${unsubscribeLink}

${clubName}
${baseUrl}

` } export default defineEventHandler(async (event) => { try { // Authentifizierung prüfen const token = getCookie(event, 'auth_token') || getHeader(event, 'authorization')?.replace('Bearer ', '') if (!token) { throw createError({ statusCode: 401, statusMessage: 'Nicht authentifiziert' }) } const user = await getUserFromToken(token) if (!user || !hasAnyRole(user, 'admin', 'vorstand', 'newsletter')) { throw createError({ statusCode: 403, statusMessage: 'Keine Berechtigung' }) } const newsletterId = getRouterParam(event, 'id') const newsletters = await readNewsletters() const newsletterIndex = newsletters.findIndex(n => n.id === newsletterId) if (newsletterIndex === -1) { throw createError({ statusCode: 404, statusMessage: 'Newsletter nicht gefunden' }) } const newsletter = newsletters[newsletterIndex] if (newsletter.status === 'sent') { throw createError({ statusCode: 400, statusMessage: 'Newsletter wurde bereits versendet' }) } // Prüfe ob Newsletter Inhalt hat if (!newsletter.content || newsletter.content.trim() === '' || newsletter.content === '


') { throw createError({ statusCode: 400, statusMessage: 'Newsletter hat keinen Inhalt. Bitte fügen Sie Inhalte hinzu, bevor Sie den Newsletter versenden.' }) } // SMTP-Credentials prüfen const smtpUser = process.env.SMTP_USER const smtpPass = process.env.SMTP_PASS if (!smtpUser || !smtpPass) { throw createError({ statusCode: 500, statusMessage: 'SMTP-Credentials fehlen! Bitte setzen Sie SMTP_USER und SMTP_PASS in der .env Datei.' }) } const transporter = nodemailer.createTransport({ host: process.env.SMTP_HOST || 'smtp.gmail.com', port: process.env.SMTP_PORT || 587, secure: false, auth: { user: smtpUser, pass: smtpPass } }) // Empfänger bestimmen let recipients = [] if (newsletter.type === 'subscription') { // Abonnenten-Newsletter recipients = await getNewsletterSubscribers(!newsletter.sendToExternal) } else if (newsletter.type === 'group') { // Gruppen-Newsletter recipients = await getRecipientsByGroup(newsletter.targetGroup) } if (recipients.length === 0) { throw createError({ statusCode: 400, statusMessage: 'Keine Empfänger gefunden' }) } // Newsletter versenden let sentCount = 0 let failedCount = 0 const failedEmails = [] for (const recipient of recipients) { try { // Abmelde-Token generieren (nur für Abonnenten-Newsletter) let unsubscribeToken = null if (newsletter.type === 'subscription') { unsubscribeToken = await generateUnsubscribeToken(recipient.email) } const htmlContent = await createNewsletterHTML(newsletter, unsubscribeToken) await transporter.sendMail({ from: process.env.SMTP_FROM || 'noreply@harheimertc.de', to: recipient.email, subject: newsletter.title, html: htmlContent }) sentCount++ } catch (error) { console.error(`Fehler beim Senden an ${recipient.email}:`, error) failedCount++ failedEmails.push(recipient.email) } } // Newsletter als versendet markieren newsletters[newsletterIndex].status = 'sent' newsletters[newsletterIndex].sentAt = new Date().toISOString() newsletters[newsletterIndex].sentTo = { total: recipients.length, sent: sentCount, failed: failedCount, failedEmails: failedEmails.length > 0 ? failedEmails : undefined } await writeNewsletters(newsletters) return { success: true, message: `Newsletter erfolgreich versendet`, stats: { total: recipients.length, sent: sentCount, failed: failedCount, failedEmails: failedEmails.length > 0 ? failedEmails : undefined } } } catch (error) { console.error('Fehler beim Versenden des Newsletters:', error) if (error.statusCode) { throw error } throw createError({ statusCode: 500, statusMessage: error.message || 'Fehler beim Versenden des Newsletters' }) } })