const express = require('express'); const router = express.Router(); const db = require('../config/database'); const mailer = require('../config/mailer'); const { requireAdmin } = require('../middleware/auth'); // ============================================ // GET /admin/mailing – Übersicht // ============================================ router.get('/', requireAdmin, async (req, res) => { try { const [members] = await db.query(` SELECT m.id, m.first_name, m.last_name, m.email, m.status, t.name as tariff_name FROM memberships m LEFT JOIN tariffs t ON m.tariff_id = t.id WHERE m.status = 'active' ORDER BY m.last_name ASC `); const [log] = await db.query(` SELECT e.id, e.membership_id, e.type, e.recipient, e.subject, e.status, e.sent_at, m.first_name, m.last_name FROM email_log e LEFT JOIN memberships m ON e.membership_id = m.id ORDER BY e.sent_at DESC LIMIT 50 `); res.render('admin/mailing', { admin: req.session.adminUser, members, log, success: req.query.success || null, error: req.query.error || null }); } catch (err) { console.error(err); res.redirect('/admin?error=' + encodeURIComponent('Fehler im Mailing: ' + err.message)); } }); // ============================================ // POST /admin/mailing/send-all – An alle aktiven // ============================================ router.post('/send-all', requireAdmin, async (req, res) => { const { subject, body, include_name } = req.body; if (!subject || !body) return res.redirect('/admin/mailing?error=Betreff+und+Text+erforderlich'); try { const [members] = await db.query( "SELECT * FROM memberships WHERE status = 'active'" ); let sent = 0, failed = 0; for (const member of members) { const personalBody = include_name ? `Hallo ${member.first_name} ${member.last_name},\n\n${body}` : body; const html = bodyToHtml(personalBody, subject); try { await mailer.sendMail({ from: process.env.MAIL_FROM, to: member.email, subject: subject, html: html }); await db.query( 'INSERT INTO email_log (membership_id, type, recipient, subject, status) VALUES (?,?,?,?,?)', [member.id, 'bulk', member.email, subject, 'sent'] ); sent++; } catch (err) { await db.query( 'INSERT INTO email_log (membership_id, type, recipient, subject, status) VALUES (?,?,?,?,?)', [member.id, 'bulk', member.email, subject, 'failed'] ); failed++; } } res.redirect(`/admin/mailing?success=${sent}+E-Mails+gesendet${failed > 0 ? '+(' + failed + '+Fehler)' : ''}`); } catch (err) { console.error(err); res.redirect('/admin/mailing?error=' + encodeURIComponent(err.message)); } }); // ============================================ // POST /admin/mailing/send-one – An einzelnes Mitglied // ============================================ router.post('/send-one', requireAdmin, async (req, res) => { const { membership_id, subject, body } = req.body; const backUrl = req.headers.referer || '/admin/mailing'; if (!membership_id || !subject || !body) { return res.redirect(backUrl + '?error=Alle+Felder+erforderlich'); } try { const [rows] = await db.query( 'SELECT * FROM memberships WHERE id = ?', [membership_id] ); if (rows.length === 0) return res.redirect(backUrl + '?error=Mitglied+nicht+gefunden'); const member = rows[0]; const html = bodyToHtml(body, subject); await mailer.sendMail({ from: process.env.MAIL_FROM, to: member.email, subject: subject, html: html }); await db.query( 'INSERT INTO email_log (membership_id, type, recipient, subject, status) VALUES (?,?,?,?,?)', [member.id, 'direct', member.email, subject, 'sent'] ); res.redirect(backUrl + '?success=E-Mail+an+' + encodeURIComponent(member.email) + '+gesendet'); } catch (err) { console.error(err); await db.query( 'INSERT INTO email_log (membership_id, type, recipient, subject, status) VALUES (?,?,?,?,?)', [membership_id, 'direct', '', subject, 'failed'] ).catch(() => {}); res.redirect(backUrl + '?error=E-Mail+Fehler:+' + encodeURIComponent(err.message)); } }); // ============================================ // HTML Template // ============================================ function bodyToHtml(text, subject) { const paragraphs = text.split('\n') .map(l => l.trim()) .map(l => l ? `
${l}
` : '