v1.2: E-Mail-Benachrichtigungen an Portal angeschlossen
- nginx-Proxy POST /api/mail/send -> mp-mail-api:8080 (nur POST, 64k Limit) - Token serverseitig via envsubst-Template + portal.env (gitignored, nur Server) - src/lib/mail.ts: fire-and-forget Versand, Empfaenger-Aufloesung (Verwaltung/Mieter) - Benachrichtigung: neue Schadensmeldung -> Verwaltung, Nachrichten/Antworten -> Gegenstelle - E2E live verifiziert (versandt: true an axel@hocks.eu), GET 403 - Doku (kimi.md, README) nachgefuehrt
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
/** E-Mail-Benachrichtigungen über die Portal-Mail-API.
|
||||
*
|
||||
* Der Browser ruft nur denselben Ursprung an: POST /api/mail/send wird vom
|
||||
* Portal-nginx (Container mp-portal) an die Mail-API (mp-mail-api:8080)
|
||||
* weitergereicht und dabei serverseitig mit dem API-Token authentifiziert.
|
||||
* Das Token liegt also weder im Repo noch im JavaScript.
|
||||
*
|
||||
* Versand ist bewusst „fire-and-forget": Klappt der Versand nicht (Offline,
|
||||
* API down), bleibt die Portal-Aktion trotzdem erhalten – der Fehler landet
|
||||
* nur in der Browser-Konsole.
|
||||
*/
|
||||
|
||||
import type { Benutzer } from '../types'
|
||||
|
||||
const ENDPUNKT = '/api/mail/send'
|
||||
|
||||
export async function sendeMail(an: string, betreff: string, text: string): Promise<boolean> {
|
||||
try {
|
||||
const res = await fetch(ENDPUNKT, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ to: an, subject: betreff, text }),
|
||||
})
|
||||
return res.ok
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/** Fire-and-forget an eine oder mehrere Adressen (null/leer = nichts senden). */
|
||||
export function sendeBenachrichtigung(an: string | string[] | null | undefined, betreff: string, text: string) {
|
||||
const adressen = (Array.isArray(an) ? an : an ? [an] : []).filter(Boolean)
|
||||
for (const adresse of adressen) {
|
||||
sendeMail(adresse, betreff, text).then((ok) => {
|
||||
if (!ok) console.warn(`[mail] Versand an ${adresse} fehlgeschlagen`)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const FUSSZEILE =
|
||||
'\n\n— Automatische Benachrichtigung aus dem Mieterportal der Hinterstein Immobilien'
|
||||
|
||||
export function nachrichtenText(koerper: string): string {
|
||||
return `${koerper}${FUSSZEILE}`
|
||||
}
|
||||
|
||||
/** E-Mail-Adressen aller aktiven Verwaltungsbenutzer. */
|
||||
export function verwaltungsAdressen(benutzer: Benutzer[]): string[] {
|
||||
return benutzer
|
||||
.filter((b) => b.rolle === 'verwaltung' && b.aktiv && b.email)
|
||||
.map((b) => b.email)
|
||||
}
|
||||
|
||||
/** E-Mail-Adressen der Mieter einer bestimmten Wohnung. */
|
||||
export function mieterAdressenFuerEinheit(benutzer: Benutzer[], einheitId: string): string[] {
|
||||
return benutzer
|
||||
.filter((b) => b.rolle === 'mieter' && b.aktiv && b.einheitId === einheitId && b.email)
|
||||
.map((b) => b.email)
|
||||
}
|
||||
|
||||
/** Anzeigename einer Wohnung, z. B. „Hauptstraße 12, Whg. 7". */
|
||||
export function einheitLabel(einheit: { building: string; number: string }): string {
|
||||
return `${einheit.building}, Whg. ${einheit.number}`
|
||||
}
|
||||
Reference in New Issue
Block a user