From 0bdf6e7b2896d4a003ad2126c31ee6b865f67a6d Mon Sep 17 00:00:00 2001 From: ah-admin Date: Fri, 2 Oct 2026 13:09:50 +0200 Subject: [PATCH] v1.4: HTML-E-Mail-Benachrichtigungen im Schulportal-Stil - server/src/mail.js: baueHtmlMail/buttonHtml (600-px-Karte, Kopfzeile in Hinterstein-Farben #22333b + Amber, Zeilen-Tabelle, Status-Box, Zitat-Box, Aktions-Button 'Zum Mieterportal', Footer), immer mit Plain-Text-Fallback - index.js: Ticket, neue Unterhaltung und Antwort versenden HTML + Text (multipart/alternative ueber die Mail-API) - Vorschauen: preview/08-mail-ticket.png, preview/08-mail-nachricht.png - E2E live verifiziert (Zustellung an axel@hocks.eu, status=sent), Doku --- kimi.md | 23 +++++-- preview/08-mail-nachricht.png | Bin 0 -> 29710 bytes preview/08-mail-ticket.png | Bin 0 -> 33793 bytes server/src/index.js | 58 +++++++++++++--- server/src/mail.js | 122 +++++++++++++++++++++++++++++++--- 5 files changed, 177 insertions(+), 26 deletions(-) create mode 100644 preview/08-mail-nachricht.png create mode 100644 preview/08-mail-ticket.png diff --git a/kimi.md b/kimi.md index 2ff9a56..be4b867 100644 --- a/kimi.md +++ b/kimi.md @@ -151,13 +151,16 @@ tar -czf mp-dist.tar.gz -C dist . - **Mail-Stack live (seit 02.10.2026):** Container `mp-mail` + `mp-mail-api` laufen auf hocks.eu unter `/opt/mp-mail` (Relay über `hocks-eu.mail.protection.outlook.com`). Testmail und API-`/send` (mit `X-Api-Token`) verifiziert (status=sent); ohne Token 401. -- **Mail-Benachrichtigungen (seit v1.2 nginx-Proxy, seit v1.3 serverseitig):** Der - Portal-nginx proxiet `POST /api/mail/send` an `http://mp-mail-api:8080/send` mit - Token aus `portal.env` (403 für alles außer POST). **Versand aus der Node-API** +- **Mail-Benachrichtigungen (seit v1.2 nginx-Proxy, seit v1.3 serverseitig, + seit v1.4 im HTML-Format wie im Schulportal):** Der Portal-nginx proxiet + `POST /api/mail/send` an `http://mp-mail-api:8080/send` mit Token aus + `portal.env` (403 für alles außer POST). **Versand aus der Node-API** (`server/src/mail.js`, fire-and-forget): neue Schadensmeldung → alle aktiven - Verwaltungsbenutzer, neue Nachricht/Antwort → Gegenstelle (Mieter ↔ Verwaltung, - Auflösung über Wohnungsbezug). E2E verifiziert: Zustellung an axel@hocks.eu - mit Postfix status=sent (02.10., 10:42 Uhr). + Verwaltungsbenutzer, neue Nachricht/Antwort → Gegenstelle. HTML im + Schulportal-Stil (`baueHtmlMail`: 600-px-Karte, Kopfzeile in Hinterstein- + Farben #22333b/Amber, Zeilen-Tabelle, Status-Box, Zitat-Box, Button „Zum + Mieterportal“, Footer) immer mit Plain-Text-Fallback (multipart/alternative). + E2E verifiziert: Zustellung an axel@hocks.eu, Postfix status=sent. ## 6. Konventionen & Besonderheiten @@ -229,6 +232,14 @@ an axel@hocks.eu) E2E verifiziert; Testdaten danach bereinigt. deploy.sh baut das API-Image auf dem Server; `.env`-Symlink auf portal.env für Compose-Interpolation beachten (POSTGRES_PASSWORD!). +**Erledigt 02.10. (v1.4 live):** HTML-E-Mail-Benachrichtigungen im Schulportal- +Stil: `baueHtmlMail`/`buttonHtml` in `server/src/mail.js` (600-px-Karte, +Kopfzeile Hinterstein-Farben, Zeilen, Status-Box, Zitat, Aktions-Button, Footer), +immer mit Plain-Text-Fallback (multipart/alternative). Umgesetzt für +Schadensmeldung, neue Unterhaltung und Antwort. Vorschauen lokal renderbar +(`mail-vorschau*.html`, Screenshots in `preview/08-*.png`). Live getestet: +Zustellung an axel@hocks.eu status=sent, Test-Ticket bereinigt. + **Offen:** - Zertifikatserneuerung prüfen (per 01.12.2026): NPM-Renewer sollte cert 9 über HTTP-Challenge erneuern; sonst certbot/webroot + Kopie nach npm-9 wiederholen. diff --git a/preview/08-mail-nachricht.png b/preview/08-mail-nachricht.png new file mode 100644 index 0000000000000000000000000000000000000000..0555bb9c54904912faee39526efcb4b3daccda5c GIT binary patch literal 29710 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 z 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 literal 0 HcmV?d00001 diff --git a/server/src/index.js b/server/src/index.js index 002bd9e..e49cb20 100644 --- a/server/src/index.js +++ b/server/src/index.js @@ -258,12 +258,25 @@ app.post('/api/tickets', auth, async (req, res, next) => { deutschesDatum()], ) const label = mail.einheitLabel(mapUnit(unitRows[0])) - mail.benachrichtigeVerwaltung( - `Neue Schadensmeldung: ${String(title).trim()} (${label})`, + const betreff = `Neue Schadensmeldung: ${String(title).trim()} (${label})` + const text = `Im Mieterportal wurde eine neue Schadensmeldung erstellt.\n\n` + - `Wohnung: ${label}\nMeldung von: ${mieterName}\nKategorie: ${String(category || 'Sonstiges')}\n\n` + - `${String(title).trim()}\n${String(description || '–').trim()}`, - ) + `Wohnung: ${label}\nMeldung von: ${mieterName}\nKategorie: ${String(category || 'Sonstiges')}\n\n` + + `${String(title).trim()}\n${String(description || '–').trim()}` + const html = mail.baueHtmlMail({ + titel: 'Neue Schadensmeldung', + untertitel: label, + einleitung: 'Im Mieterportal wurde eine neue Schadensmeldung erstellt:', + zeilen: [ + ['Wohnung', label], + ['Meldung von', mieterName], + ['Kategorie', String(category || 'Sonstiges')], + ], + statusBox: { hintergrund: '#f0fdfa', farbe: '#0f766e', text: 'Status: offen – neu eingegangen' }, + zitat: `${String(title).trim()}\n${String(description || '–').trim()}`, + aktionenHtml: mail.buttonHtml('Zum Mieterportal', `${process.env.PORTAL_URL || 'https://mieterportal.hocks.eu'}/schadensmeldungen`), + }) + mail.benachrichtigeVerwaltung(betreff, text, html) res.json({ ticket: mapTicket(rows[0]) }) } catch (e) { next(e) } }) @@ -308,9 +321,20 @@ app.post('/api/threads', auth, async (req, res, next) => { const betreff = vonRolle === 'tenant' ? `Neue Nachricht im Mieterportal: ${String(subject).trim()}` : `Nachricht der Verwaltung: ${String(subject).trim()}` - const inhalt = `Neue Unterhaltung von ${autor}:\n\n„${String(text).trim()}“` - if (vonRolle === 'tenant') mail.benachrichtigeVerwaltung(betreff, inhalt) - else mail.benachrichtigeMieter(unitId, betreff, inhalt) + const textVersion = `Neue Unterhaltung von ${autor}:\n\n„${String(text).trim()}“` + const html = mail.baueHtmlMail({ + titel: vonRolle === 'tenant' ? 'Neue Nachricht' : 'Nachricht der Verwaltung', + untertitel: String(subject).trim(), + einleitung: `Neue Unterhaltung von ${autor}:`, + zeilen: [ + ['Wohnung', mail.einheitLabel(mapUnit(unitRows[0]))], + ['Betreff', String(subject).trim()], + ], + zitat: String(text).trim(), + aktionenHtml: mail.buttonHtml('Zum Mieterportal', `${process.env.PORTAL_URL || 'https://mieterportal.hocks.eu'}/nachrichten`), + }) + if (vonRolle === 'tenant') mail.benachrichtigeVerwaltung(betreff, textVersion, html) + else mail.benachrichtigeMieter(unitId, betreff, textVersion, html) const { rows } = await pool.query('SELECT * FROM threads WHERE id = $1', [id]) const { rows: msgRows } = await pool.query('SELECT * FROM messages WHERE thread_id = $1 ORDER BY at', [id]) res.json({ thread: { ...mapThread(rows[0]), messages: msgRows.map(mapMessage) } }) @@ -340,9 +364,21 @@ app.post('/api/threads/:id/messages', auth, async (req, res, next) => { const betreff = vonRolle === 'tenant' ? `Neue Antwort im Mieterportal: ${th.subject}` : `Antwort der Verwaltung: ${th.subject}` - const inhalt = `Neue Nachricht von ${autor} in der Unterhaltung „${th.subject}“:\n\n„${text}“` - if (vonRolle === 'tenant') mail.benachrichtigeVerwaltung(betreff, inhalt) - else mail.benachrichtigeMieter(th.unit_id, betreff, inhalt) + const { rows: einheitRows } = await pool.query('SELECT * FROM units WHERE id = $1', [th.unit_id]) + const textVersion = `Neue Nachricht von ${autor} in der Unterhaltung „${th.subject}“:\n\n„${text}“` + const html = mail.baueHtmlMail({ + titel: vonRolle === 'tenant' ? 'Neue Antwort' : 'Antwort der Verwaltung', + untertitel: th.subject, + einleitung: `Neue Nachricht von ${autor}:`, + zeilen: [ + ['Wohnung', mail.einheitLabel(mapUnit(einheitRows[0]))], + ['Unterhaltung', th.subject], + ], + zitat: text, + aktionenHtml: mail.buttonHtml('Zum Mieterportal', `${process.env.PORTAL_URL || 'https://mieterportal.hocks.eu'}/nachrichten`), + }) + if (vonRolle === 'tenant') mail.benachrichtigeVerwaltung(betreff, textVersion, html) + else mail.benachrichtigeMieter(th.unit_id, betreff, textVersion, html) const { rows: msgRows } = await pool.query('SELECT * FROM messages WHERE thread_id = $1 ORDER BY at', [th.id]) const { rows } = await pool.query('SELECT * FROM threads WHERE id = $1', [th.id]) res.json({ thread: { ...mapThread(rows[0]), messages: msgRows.map(mapMessage) } }) diff --git a/server/src/mail.js b/server/src/mail.js index 7e54208..c1f5578 100644 --- a/server/src/mail.js +++ b/server/src/mail.js @@ -3,21 +3,118 @@ * Fire-and-forget: Ein Fehler (Mail-API down, Relay-Fehler) beeinträchtigt * die auslösende Portal-Aktion nie. Die Mail-API selbst puffert im Fehlerfall * in ihrer Outbox und versucht es erneut. + * + * Gestaltung wie im Schulportal: HTML-Karte (600 px, Kopfzeile in Portal-Farben, + * Zeilen-Tabelle, optional Status-Box/Zitat/Aktions-Button) plus Plain-Text- + * Fallback, immer beide an die Mail-API (sendet multipart/alternative). */ const MAIL_API_URL = process.env.MAIL_API_URL || '' // z. B. http://mp-mail-api:8080 const MAIL_API_TOKEN = process.env.MAIL_API_TOKEN || '' +const PORTAL_URL = process.env.PORTAL_URL || 'https://mieterportal.hocks.eu' -const FUSSZEILE = - '\n\n— Automatische Benachrichtigung aus dem Mieterportal der Hinterstein Immobilien' +// Portal-Farben (Hinterstein): dunkles Petrol + Amber-Akzent (vgl. Login-Seite) +const FARBE_KOPF = '#22333b' // Dunkel-Petrol +const FARBE_KOPF_ZEILE = '#fcd34d' // Amber-200 (Kicker-Zeile) +const FARBE_UNTERTITEL = '#cbd5e1' +const FARBE_BUTTON = '#f59e0b' // Amber-500 +const FARBE_BUTTON_TEXT = '#1c1917' +const HINTERGRUND = '#f1f5f9' +const KARTE = '#ffffff' +const TEXT = '#0f172a' +const TEXT_SOFT = '#64748b' +const RAND = '#e2e8f0' -async function sendeMail(an, betreff, text) { +const FUSSZEILE_TEXT = + '— Automatische Benachrichtigung aus dem Mieterportal der Hinterstein Immobilien' + +function htmlEscape(s) { + return String(s) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') +} + +/** Baut die HTML-Karte im Schulportal-Stil. Alle Inhalte werden escaped. */ +function baueHtmlMail(opts) { + const { titel, untertitel = '', einleitung = '', zeilen = [], statusBox, zitat, aktionenHtml = '', fussnote = '' } = opts + + const zeilenHtml = zeilen + .map( + ([label, wert]) => ` + + ${htmlEscape(label)} + ${htmlEscape(wert)} + `, + ) + .join('') + + const statusHtml = statusBox + ? ` +
${htmlEscape(statusBox.text)}
` + : '' + + const zitatHtml = zitat + ? ` +
${htmlEscape(zitat)}
` + : '' + + const fussnotenHtml = fussnote + ? `

${htmlEscape(fussnote)}

` + : '' + + return ` + +${htmlEscape(titel)} + +
${htmlEscape(einleitung || titel)}
+ + + + +
+ + + + + + + + + + +
+

Hinterstein Immobilien

+

${htmlEscape(titel)}

+ ${untertitel ? `

${htmlEscape(untertitel)}

` : ''} +
+ ${einleitung ? `

${htmlEscape(einleitung)}

` : ''} + ${statusHtml} + ${zitatHtml} + ${zeilenHtml}
+ ${aktionenHtml} + ${fussnotenHtml} +
+

Hinterstein Immobilien (Demo) · mieterportal.hocks.eu
Diese E-Mail wurde automatisch vom Mieterportal erzeugt. Bitte antworten Sie nicht direkt – nutzen Sie das Nachrichten-Modul im Portal.

+
+
+ +` +} + +/** Aktions-Button (portal-interne Links). */ +function buttonHtml(text, url) { + return `

${htmlEscape(text)}

` +} + +async function sendeMail(an, betreff, text, html) { if (!MAIL_API_URL || !MAIL_API_TOKEN || !an) return try { const res = await fetch(`${MAIL_API_URL}/send`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Api-Token': MAIL_API_TOKEN }, - body: JSON.stringify({ to: an, subject: betreff, text: `${text}${FUSSZEILE}` }), + body: JSON.stringify({ to: an, subject: betreff, text: `${text}\n\n${FUSSZEILE_TEXT}`, ...(html ? { html } : {}) }), }) if (!res.ok) console.warn(`[mail] Versand an ${an} fehlgeschlagen: HTTP ${res.status}`) } catch (e) { @@ -26,24 +123,31 @@ async function sendeMail(an, betreff, text) { } /** Alle aktiven Verwaltungsnutzer benachrichtigen. */ -async function benachrichtigeVerwaltung(betreff, text) { +async function benachrichtigeVerwaltung(betreff, text, html) { const { rows } = await require('./db').pool.query( `SELECT email FROM users WHERE rolle = 'verwaltung' AND aktiv AND email <> ''`, ) - for (const r of rows) sendeMail(r.email, betreff, text) + for (const r of rows) sendeMail(r.email, betreff, text, html) } /** Mieter einer bestimmten Wohnung benachrichtigen. */ -async function benachrichtigeMieter(einheitId, betreff, text) { +async function benachrichtigeMieter(einheitId, betreff, text, html) { const { rows } = await require('./db').pool.query( `SELECT email FROM users WHERE rolle = 'mieter' AND aktiv AND einheit_id = $1 AND email <> ''`, [einheitId], ) - for (const r of rows) sendeMail(r.email, betreff, text) + for (const r of rows) sendeMail(r.email, betreff, text, html) } function einheitLabel(u) { return u ? `${u.building}, Whg. ${u.number}` : '' } -module.exports = { sendeMail, benachrichtigeVerwaltung, benachrichtigeMieter, einheitLabel } +module.exports = { + sendeMail, + benachrichtigeVerwaltung, + benachrichtigeMieter, + einheitLabel, + baueHtmlMail, + buttonHtml, +}