- 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
65 lines
2.3 KiB
TypeScript
65 lines
2.3 KiB
TypeScript
/** 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}`
|
||
}
|