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:
2026-10-02 12:21:12 +02:00
parent fbe033ebd6
commit 5503ce5fc5
9 changed files with 225 additions and 18 deletions
+25 -4
View File
@@ -48,7 +48,7 @@ Hauptstraße 12 Whg. 7), `m.wolf` (Mieter). Demo-Registrierungscode: `MP-2026-08
| Auth | `src/lib/auth.ts` (SHA-256, Session 8 h, Keys `mp_benutzer`/`mp_benutzer_session`), Route-Guard in `App.tsx` |
| Branding | Kunde: `src/assets/hinterstein/` (logo.png, joseph-hinterstein.jpg, kontakt.jpg); KI-generiert: `src/assets/logo.png`, `hero.jpg`, `modules.jpg` |
| Webserver (Ziel) | Docker-Container `mp-portal` (nginx), statisches `dist/`, gemountet `/opt/mieterportal/dist` |
| Mail | `mail-server/`: Postfix-Relay (`mp-mail`) + Python-API (`mp-mail-api`) – **live auf dem Server** unter `/opt/mp-mail` |
| Mail | `mail-server/`: Postfix-Relay (`mp-mail`) + Python-API (`mp-mail-api`) – **live**, `/opt/mp-mail` auf dem Server; **verkabelt**: Portal-nginx proxyt `POST /api/mail/send` → `mp-mail-api:8080` und injiziert das Token aus `portal.env` (serverseitig, nie im Browser/Repo) |
| Server | Root-VPS hocks.eu (IONOS), Docker + Portainer, Subdomain via NPM (Nginx Proxy Manager, Let's Encrypt) |
## 3. Wichtige Dateien
@@ -68,6 +68,8 @@ ausgesperrt via `.gitignore` (`mail-server/mail.env` etc.).
| `src/components/ThemeToggle.tsx` | Dark-Mode-Umschalter (Sonne/Mond) |
| `src/lib/theme.ts` | `mp-theme` in localStorage, Init vor erstem Render (main.tsx) |
| `src/pages/Login.tsx` | Login-Pflicht: Hero mit Joseph-Hinterstein-Portrait, Logo, Feature-Liste, Login-Formular + Registrierung-Link + Demo-Einstiege |
| `src/lib/mail.ts` | E-Mail-Benachrichtigungen: `sendeBenachrichtigung` (fire-and-forget) an `/api/mail/send`, Empfänger-Auflösung (Verwaltung / Mieter je Wohnung) |
| `docker/templates/default.conf.template` | nginx-Site als envsubst-Template; proxiet `POST /api/mail/send` → `mp-mail-api:8080` mit `${MAIL_API_TOKEN}` aus `portal.env` |
| `src/pages/Benutzer.tsx` | Benutzerverwaltung (nur Verwaltung): Nutzer, Gruppen, Registrierungscodes |
| `Dockerfile` | Optionaler All-in-One-Build (node build → nginx) für `docker build`-Workflow |
| `docker/nginx.conf` | nginx-Site: SPA-Fallback, Gzip, Cache-Header für /assets/, Security-Header |
@@ -101,6 +103,10 @@ tar -czf mp-dist.tar.gz -C dist .
```
- SSH: Port **38592**, Key `Z:\Devel\ssh\priv_ionos_hocks_vps.ppk` (Pageant), Hostkey-Flag zwingend.
- **`portal.env` auf dem Server wird vom compose als `env_file` gebraucht**
(liefert `MAIL_API_TOKEN` für den nginx-envsubst). Einmalig angelegt:
`grep '^MAIL_API_TOKEN=' /opt/mp-mail/mail.env > /opt/mieterportal/portal.env`
Liegt nur auf dem Server (gitignored), wird von deploy.sh nicht hochgeladen.
- **Vorsicht Fail2Ban:** zu viele gescheiterte SSH-Versuche von einer IP führen zu einem
Ban (Timeout-Verbindungsbild). Ban aufheben auf dem Server: `fail2ban-client unban --all`.
- **Live (seit 02.10.2026):** Container `mp-portal` läuft auf hocks.eu, statisches `dist/`
@@ -126,7 +132,17 @@ 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.
Noch nicht mit dem Portal-Frontend verkabelt (keine automatischen Benachrichtigungen).
- **Mail-Benachrichtigungen im Portal (seit 02.10., v1.2):** Der Portal-nginx
(`docker/templates/default.conf.template`, envsubst) proxiet ausschließlich
`POST /api/mail/send` an `http://mp-mail-api:8080/send` und setzt das Token
aus `/opt/mieterportal/portal.env` (chmod 600, **nicht im Repo**, gitignored).
Das Frontend (`src/lib/mail.ts`) sendet fire-and-forget: neue Schadensmeldung →
alle aktiven Verwaltungsbenutzer, neue Nachricht/Antwort → Gegenstelle
(Mieter ↔ Verwaltung, Empfänger über Wohnungsbezug). E2E verifiziert:
POST über `https://mieterportal.hocks.eu/api/mail/send` → `versandt: true`
(Test an axel@hocks.eu); GET wird mit 403 blockiert. Demo-Empfängeradressen
(z. B. joseph@hinterstein-immo.de) sind fiktiv → dort kein Empfang möglich,
echte Adressen in der Benutzerverwaltung pflegen.
## 6. Konventionen & Besonderheiten
@@ -174,11 +190,16 @@ aktiviert (`/opt/mp-mail`, Testmail + API-/send verifiziert). Store-Key auf
`hinterstein-mieterportal-v2` gehoben. Live deployed und geprüft (HTTP 200, Titel
„Hinterstein Immobilien · Mieterportal").
**Erledigt 02.10. (v1.2 live):** E-Mail-Benachrichtigungen an das Portal
angeschlossen: nginx-Proxy `/api/mail/send` mit serverseitig injiziertem Token
(envsubst-Template + `portal.env` auf dem Server), `src/lib/mail.ts` sendet bei
neuen Schadensmeldungen (→ Verwaltung) und Nachrichten/Antworten (→ Gegenstelle).
E2E-Versand live verifiziert (versandt: true), GET auf den Endpunkt 403.
**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.
- Portal-Frontend an Mail-API verkabeln: automatische E-Mail an die Verwaltung bei neuen
Schadensmeldungen und an Mieter bei Antworten.
- Demo-Empfängeradressen durch echte ersetzen, sobald bekannt.
- Mögliche nächste Schritte: serverseitige Datenbank (PostgreSQL/Node-API) statt localStorage,
Mehrseitigkeit für 50 echte Mietverhältnisse.