diff --git a/server/api/auth/register.post.js b/server/api/auth/register.post.js
index 6a90b58..d15239c 100644
--- a/server/api/auth/register.post.js
+++ b/server/api/auth/register.post.js
@@ -1,5 +1,5 @@
import { readUsers, writeUsers, hashPassword } from '../../utils/auth.js'
-import nodemailer from 'nodemailer'
+import { sendRegistrationNotification } from '../../utils/email-service.js'
import { assertPasswordNotPwned } from '../../utils/hibp.js'
export default defineEventHandler(async (event) => {
@@ -55,61 +55,11 @@ export default defineEventHandler(async (event) => {
users.push(newUser)
await writeUsers(users)
- // Send notification email to admin
+ // Send notification to Vorstand/admin via central email service
try {
- const smtpUser = process.env.SMTP_USER
- const smtpPass = process.env.SMTP_PASS
-
- if (!smtpUser || !smtpPass) {
- console.warn('SMTP-Credentials fehlen! E-Mail-Versand wird übersprungen.')
- console.warn(`SMTP_USER=${smtpUser ? 'gesetzt' : 'FEHLT'}, SMTP_PASS=${smtpPass ? 'gesetzt' : 'FEHLT'}`)
- // Continue without sending email
- } else {
- 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
- }
- })
-
- // Email to admin
- await transporter.sendMail({
- from: process.env.SMTP_FROM || 'noreply@harheimertc.de',
- to: process.env.SMTP_ADMIN || 'j.dichmann@gmx.de',
- subject: 'Neue Registrierung - Harheimer TC',
- html: `
-
Neue Registrierung
- Ein neuer Benutzer hat sich registriert und wartet auf Freigabe:
-
- - Name: ${name}
- - E-Mail: ${email}
- - Telefon: ${phone || 'Nicht angegeben'}
-
- Bitte prüfen Sie die Registrierung im CMS.
- `
- })
-
- // Email to user
- await transporter.sendMail({
- from: process.env.SMTP_FROM || 'noreply@harheimertc.de',
- to: email,
- subject: 'Registrierung erhalten - Harheimer TC',
- html: `
- Registrierung erhalten
- Hallo ${name},
- vielen Dank für Ihre Registrierung beim Harheimer TC!
- Ihre Anfrage wird vom Vorstand geprüft. Sie erhalten eine E-Mail, sobald Ihr Zugang freigeschaltet wurde.
-
- Mit sportlichen Grüßen,
Ihr Harheimer TC
- `
- })
- }
+ await sendRegistrationNotification({ name, email, phone })
} catch (emailError) {
- console.error('E-Mail-Versand fehlgeschlagen:', emailError)
- // Continue anyway - user is registered
+ console.error('Registrierungs-Benachrichtigung fehlgeschlagen:', emailError)
}
return {
diff --git a/server/api/membership/generate-pdf.post.js b/server/api/membership/generate-pdf.post.js
index 9bae67d..dbd1282 100644
--- a/server/api/membership/generate-pdf.post.js
+++ b/server/api/membership/generate-pdf.post.js
@@ -5,6 +5,7 @@ import fs from 'fs/promises'
import path from 'path'
import { StandardFonts } from 'pdf-lib'
import { getDownloadCookieOptionsWithMaxAge } from '../../utils/cookies.js'
+import { sendMembershipEmail as sendMembershipEmailUtil } from '../../utils/email-service.js'
// const require = createRequire(import.meta.url) // Nicht verwendet
const execAsync = promisify(exec)
@@ -317,59 +318,7 @@ function getDataPath(filename) {
return path.join(projectRoot, 'server', 'data', filename)
}
-async function sendMembershipEmail(data, _filename, _event) {
- try {
- const configPath = getDataPath('config.json')
- const configData = await fs.readFile(configPath, 'utf8')
- const config = JSON.parse(configData)
-
- let recipients = []
- let subject = `Neuer Mitgliedschaftsantrag - ${data.vorname} ${data.nachname}`
-
- // Sammle alle verfügbaren E-Mail-Adressen
- const availableEmails = []
-
- // Vorsitzender E-Mail hinzufügen (falls vorhanden)
- if (config.vorstand.vorsitzender.email && config.vorstand.vorsitzender.email.trim() !== '') {
- availableEmails.push(config.vorstand.vorsitzender.email)
- }
-
- // Schriftführer E-Mail hinzufügen (falls vorhanden)
- if (config.vorstand.schriftfuehrer.email && config.vorstand.schriftfuehrer.email.trim() !== '') {
- availableEmails.push(config.vorstand.schriftfuehrer.email)
- }
-
- // Fallback: Wenn keine E-Mails verfügbar sind, verwende tsschulz@tsschulz.de
- if (availableEmails.length === 0) {
- recipients = ['tsschulz@tsschulz.de']
- } else {
- recipients = availableEmails
- }
-
- // In nicht-Produktionsumgebung: Alle E-Mails an tsschulz@tsschulz.de
- if (process.env.NODE_ENV !== 'production') {
- recipients = ['tsschulz@tsschulz.de']
- }
-
- const message = `Ein neuer Mitgliedschaftsantrag wurde eingereicht.
-
-Antragsteller: ${data.vorname} ${data.nachname}
-Mitgliedschaftsart: ${data.mitgliedschaftsart}
-Volljährig: ${data.isVolljaehrig ? 'Ja' : 'Nein'}
-
-Das ausgefüllte Formular ist als Anhang verfügbar.`
-
- // E-Mail-Versand implementieren (hier würde normalerweise nodemailer verwendet)
- console.log('E-Mail würde gesendet werden an:', recipients)
- console.log('Betreff:', subject)
- console.log('Nachricht:', message)
-
- return { success: true, recipients, subject, message }
- } catch (error) {
- console.error('Fehler beim Senden der E-Mail:', error)
- return { success: false, error: error.message }
- }
-}
+// Use central email service
export default defineEventHandler(async (event) => {
try {
@@ -678,8 +627,8 @@ export default defineEventHandler(async (event) => {
let emailResult
if (usedTemplate) {
- // E-Mail senden
- emailResult = await sendMembershipEmail(data, filename, event)
+ // E-Mail senden via zentralen Service (pass full path)
+ emailResult = await sendMembershipEmailUtil(data, finalPdfPath)
// Antragsdaten verschlüsselt speichern
const encryptionKey = process.env.ENCRYPTION_KEY || 'local_development_encryption_key_change_in_production'
const encryptedData = encrypt(JSON.stringify(data), encryptionKey)
@@ -731,8 +680,8 @@ export default defineEventHandler(async (event) => {
const finalPdfPath = path.join(uploadsDir, `${filename}.pdf`)
await fs.copyFile(pdfPath, finalPdfPath)
- // E-Mail senden
- emailResult = await sendMembershipEmail(data, filename, event)
+ // E-Mail senden via zentralen Service (pass full path)
+ emailResult = await sendMembershipEmailUtil(data, finalPdfPath)
// Antragsdaten verschlüsselt speichern
const encryptionKey = process.env.ENCRYPTION_KEY || 'local_development_encryption_key_change_in_production'
@@ -763,8 +712,8 @@ export default defineEventHandler(async (event) => {
// Fallback: Einfache Textdatei generieren
const fallbackFilename = await generateSimplePDF(data, filename, event)
- // E-Mail senden (Fallback)
- const emailResult = await sendMembershipEmail(data, filename, event)
+ // E-Mail senden (Fallback)
+ const emailResult = await sendMembershipEmailUtil(data, path.join(uploadsDir, `${filename}.txt`))
console.log('LaTeX nicht verfügbar, verwende Fallback-Lösung')
console.log('E-Mail würde gesendet werden an:', emailResult.recipients || [])
diff --git a/server/utils/email-service.js b/server/utils/email-service.js
index 368b4f9..bbfa745 100644
--- a/server/utils/email-service.js
+++ b/server/utils/email-service.js
@@ -55,25 +55,29 @@ function getEmailRecipients(data, config) {
}
const recipients = []
-
- // Add 1. Vorsitzender
- if (config.vorsitzender && config.vorsitzender.email) {
- recipients.push(config.vorsitzender.email)
+
+ // Config uses a 'vorstand' object with nested roles; collect all emails
+ if (config.vorstand && typeof config.vorstand === 'object') {
+ Object.values(config.vorstand).forEach((member) => {
+ if (member && member.email && typeof member.email === 'string' && member.email.trim() !== '') {
+ recipients.push(member.email.trim())
+ }
+ })
}
-
- // Add Schriftführer
- if (config.schriftfuehrer && config.schriftfuehrer.email) {
- recipients.push(config.schriftfuehrer.email)
- }
-
- // For minors, also add 1. Trainer
- if (!data.isVolljaehrig && config.trainer && config.trainer.email) {
- recipients.push(config.trainer.email)
+
+ // For minors, also add first trainer email if configured (trainer is an array)
+ if (!data.isVolljaehrig && Array.isArray(config.trainer) && config.trainer.length > 0 && config.trainer[0].email) {
+ recipients.push(config.trainer[0].email)
}
// Fallback if no recipients found
if (recipients.length === 0) {
- recipients.push('tsschulz@tsschulz.de')
+ // Prefer website verantwortlicher if set
+ if (config.website && config.website.verantwortlicher && config.website.verantwortlicher.email) {
+ recipients.push(config.website.verantwortlicher.email)
+ } else {
+ recipients.push('tsschulz@tsschulz.de')
+ }
}
return recipients
@@ -94,7 +98,7 @@ function createTransporter() {
)
}
- return nodemailer.createTransporter({
+ return nodemailer.createTransport({
host: process.env.SMTP_HOST || 'localhost',
port: parseInt(process.env.SMTP_PORT) || 587,
secure: process.env.SMTP_SECURE === 'true',
@@ -161,4 +165,61 @@ Das ausgefüllte Formular ist als Anhang verfügbar.`
error: error.message
}
}
+}
+
+/**
+ * Sends a simple registration notification to Vorstand/admin and a confirmation to user.
+ * @param {Object} data - { name, email, phone }
+ */
+export async function sendRegistrationNotification(data) {
+ try {
+ const config = await loadConfig()
+ const recipients = getEmailRecipients(data, config)
+
+ // Create transporter
+ const transporter = createTransporter()
+
+ // Notify Vorstand/admin
+ const adminSubject = 'Neue Registrierung - Harheimer TC'
+ const adminHtml = `
+ Neue Registrierung
+ Ein neuer Benutzer hat sich registriert und wartet auf Freigabe:
+
+ - Name: ${data.name}
+ - E-Mail: ${data.email}
+ - Telefon: ${data.phone || 'Nicht angegeben'}
+
+ Bitte prüfen Sie die Registrierung im CMS.
+ `
+
+ await transporter.sendMail({
+ from: process.env.SMTP_FROM || 'noreply@harheimertc.de',
+ to: recipients.join(', '),
+ subject: adminSubject,
+ html: adminHtml
+ })
+
+ // Confirmation to user
+ const userSubject = 'Registrierung erhalten - Harheimer TC'
+ const userHtml = `
+ Registrierung erhalten
+ Hallo ${data.name},
+ vielen Dank für Ihre Registrierung beim Harheimer TC!
+ Ihre Anfrage wird vom Vorstand geprüft. Sie erhalten eine E-Mail, sobald Ihr Zugang freigeschaltet wurde.
+
+ Mit sportlichen Grüßen,
Ihr Harheimer TC
+ `
+
+ await transporter.sendMail({
+ from: process.env.SMTP_FROM || 'noreply@harheimertc.de',
+ to: data.email,
+ subject: userSubject,
+ html: userHtml
+ })
+
+ return { success: true, recipients }
+ } catch (error) {
+ console.error('sendRegistrationNotification failed:', error.message || error)
+ throw error
+ }
}
\ No newline at end of file