import { getUserFromToken, hasAnyRole } from '../../../../../utils/auth.js' import { readSubscribers, writeSubscribers } from '../../../../../utils/newsletter.js' import { randomUUID } from 'crypto' import nodemailer from 'nodemailer' import crypto from 'crypto' import fs from 'fs/promises' import path from 'path' 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 NEWSLETTER_GROUPS_FILE = getDataPath('newsletter-groups.json') async function readGroups() { try { const data = await fs.readFile(NEWSLETTER_GROUPS_FILE, 'utf-8') return JSON.parse(data) } catch (error) { if (error.code === 'ENOENT') { return [] } throw error } } 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 groupId = getRouterParam(event, 'id') const body = await readBody(event) const { email, name, customMessage } = body if (!email || !email.match(/^[^\s@]+@[^\s@]+\.[^\s@]+$/)) { throw createError({ statusCode: 400, statusMessage: 'Ungültige E-Mail-Adresse' }) } // Prüfe ob Gruppe existiert und vom Typ 'subscription' ist const groups = await readGroups() const group = groups.find(g => g.id === groupId) if (!group) { throw createError({ statusCode: 404, statusMessage: 'Newsletter-Gruppe nicht gefunden' }) } if (group.type !== 'subscription') { throw createError({ statusCode: 400, statusMessage: 'Diese Funktion ist nur für Abonnenten-Newsletter verfügbar' }) } const subscribers = await readSubscribers() const emailLower = email.toLowerCase() // Prüfe ob bereits für diese Gruppe angemeldet const existing = subscribers.find(s => { const sEmail = (s.email || '').toLowerCase() return sEmail === emailLower && s.groupIds && s.groupIds.includes(groupId) }) if (existing) { if (existing.confirmed) { throw createError({ statusCode: 409, statusMessage: 'Diese E-Mail-Adresse ist bereits für diesen Newsletter angemeldet' }) } else { // Bestätigungsmail erneut senden mit individueller Nachricht await sendConfirmationEmail(existing.email, existing.name || name, existing.confirmationToken, group.name, customMessage, user.name) return { success: true, message: 'Eine Bestätigungsmail wurde an die E-Mail-Adresse gesendet' } } } // Prüfe ob E-Mail bereits existiert (für andere Gruppe oder ohne Gruppe) const existingEmail = subscribers.find(s => (s.email || '').toLowerCase() === emailLower) if (existingEmail) { // Bestehender Subscriber - Gruppe hinzufügen if (!existingEmail.groupIds) { existingEmail.groupIds = [] } if (existingEmail.groupIds.includes(groupId)) { // Bereits für diese Gruppe angemeldet if (existingEmail.confirmed) { throw createError({ statusCode: 409, statusMessage: 'Diese E-Mail-Adresse ist bereits für diesen Newsletter angemeldet' }) } else { // Bestätigungsmail erneut senden mit individueller Nachricht await sendConfirmationEmail(existingEmail.email, existingEmail.name || name, existingEmail.confirmationToken, group.name, customMessage, user.name) return { success: true, message: 'Eine Bestätigungsmail wurde an die E-Mail-Adresse gesendet' } } } // Gruppe hinzufügen existingEmail.groupIds.push(groupId) if (!existingEmail.confirmed) { // Neuer Bestätigungstoken für alle Gruppen existingEmail.confirmationToken = crypto.randomBytes(32).toString('hex') } existingEmail.name = name || existingEmail.name || '' await writeSubscribers(subscribers) if (existingEmail.confirmed) { // Bereits bestätigt - sofort aktiviert return { success: true, message: `Empfänger wurde erfolgreich für den Newsletter "${group.name}" hinzugefügt` } } else { // Bestätigungsmail senden mit individueller Nachricht await sendConfirmationEmail(existingEmail.email, existingEmail.name, existingEmail.confirmationToken, group.name, customMessage, user.name) return { success: true, message: 'Eine Bestätigungsmail wurde an die E-Mail-Adresse gesendet' } } } // Neuer Abonnent const confirmationToken = crypto.randomBytes(32).toString('hex') const unsubscribeToken = crypto.randomBytes(32).toString('hex') const newSubscriber = { id: randomUUID(), email: emailLower, name: name || '', groupIds: [groupId], confirmed: false, confirmationToken, unsubscribeToken, subscribedAt: new Date().toISOString(), confirmedAt: null, unsubscribedAt: null } subscribers.push(newSubscriber) await writeSubscribers(subscribers) // Bestätigungsmail senden mit individueller Nachricht await sendConfirmationEmail(email, name, confirmationToken, group.name, customMessage, user.name) return { success: true, message: 'Eine Bestätigungsmail wurde an die E-Mail-Adresse gesendet' } } catch (error) { console.error('Fehler beim Hinzufügen des Empfängers:', error) if (error.statusCode) { throw error } throw createError({ statusCode: 500, statusMessage: 'Fehler beim Hinzufügen des Empfängers' }) } }) async function sendConfirmationEmail(email, name, token, groupName, customMessage = null, inviterName = null) { const smtpUser = process.env.SMTP_USER const smtpPass = process.env.SMTP_PASS if (!smtpUser || !smtpPass) { console.warn('SMTP-Credentials fehlen! Bestätigungsmail kann nicht gesendet werden.') return } const baseUrl = process.env.NUXT_PUBLIC_BASE_URL || 'http://localhost:3100' const confirmationUrl = `${baseUrl}/newsletter/confirm?token=${token}` 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 } }) // Individuelle Nachricht einbauen, falls vorhanden const customMessageHtml = customMessage ? `
${customMessage.replace(/\n/g, '
')}
Sie wurden von ${inviterName} zum Newsletter eingeladen.
` : '' await transporter.sendMail({ from: process.env.SMTP_FROM || 'noreply@harheimertc.de', to: email, subject: `Newsletter-Anmeldung bestätigen - ${groupName} - Harheimer TC`, html: `Hallo ${name || 'Liebe/r Abonnent/in'},
${inviterText}vielen Dank für Ihre Anmeldung zum Newsletter "${groupName}" des Harheimer TC!
${customMessageHtml}Bitte bestätigen Sie Ihre Anmeldung, indem Sie auf den folgenden Link klicken:
Newsletter-Anmeldung bestätigen
Falls Sie sich nicht angemeldet haben, können Sie diese E-Mail ignorieren.
Mit sportlichen Grüßen,
Ihr Harheimer Tischtennis-Club 1954 e.V.