feat(akquise): Mail an Berater bei neuem Projekt

Wird in der Akquise ein Projekt mit Berater angelegt (oder ein Berater
beim Bearbeiten hinzugefuegt), bekommt er eine Mail ueber Graph sendMail
aus crm@perinco.de; Reply-To ist der eintragende Benutzer. Je Berater
abschaltbar unter Einstellungen -> Akquise (Spalte notify, Vorgabe an).
Versand laeuft nach der Antwort und kippt das Speichern nie.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Sascha Wolf
2026-10-21 09:38:13 +02:00
co-authored by Claude Opus 5.5
parent 907b010f3c
commit eaef454442
15 changed files with 402 additions and 24 deletions
+40 -2
View File
@@ -66,6 +66,9 @@ Login.
3. **API-Berechtigung** Microsoft Graph &rarr; *Anwendungsberechtigungen* &rarr;
`Mail.Read`, danach Administratorzustimmung erteilen.
`Mail.ReadBasic` genügt nicht, es liefert keinen Mailtext.
Seit 21.10.2026 zusätzlich `Mail.Send` (erteilt) - damit verschickt das CRM
die [Berater-Mail bei neuem Projekt](#berater-mail-bei-neuem-projekt) aus
diesem Postfach.
4. **Zugriff auf dieses eine Postfach begrenzen.** Anwendungsberechtigungen
gelten tenant-weit; ohne Richtlinie darf die App jedes Postfach lesen:
@@ -386,10 +389,45 @@ Fremdschlüssel nicht.
| HTML-Anzeige | ungefiltert | serverseitig entschärft, `sandbox=""`, externe Bilder gesperrt |
| Zeitangaben | gemischt | durchgehend UTC in der Datenbank, Umrechnung im Frontend |
## Berater-Mail bei neuem Projekt
Seit 21.10.2026 verschickt das CRM selbst Mails - bisher nur eine Sorte: Wird in
der Akquise ein Projekt eingetragen und dabei ein Berater ausgewählt, bekommt
dieser eine Mail mit Titel, Endkunde, Anbieter, Tagessatz, Zeitraum, Link zur
Ausschreibung und Beschreibung (gekürzt auf 1500 Zeichen).
```mermaid
sequenceDiagram
participant B as Browser
participant API as POST/PATCH /api/acquisitions
participant N as acquisitionNotify.js
participant G as Graph sendMail
B->>API: Eintrag mit Berater speichern
API-->>B: 201 / 200 (sofort)
API->>N: notifyConsultants(eintrag, neue Berater, benutzer)
N->>N: Adresse + Schalter je Berater aus crm_acquisition_options
N->>G: POST /users/crm@perinco.de/sendMail
```
* **Absender** ist `MS_MAILBOX` (crm@perinco.de), Kopie in *Gesendete
Elemente*. **Reply-To** ist der Benutzer, der den Eintrag gespeichert hat -
eine Antwort des Beraters landet also bei ihm, nicht im CRM-Postfach.
* **Wer** eine Mail bekommt: Beim Anlegen alle ausgewählten Berater, beim
Bearbeiten nur die neu hinzugekommenen. Voraussetzung je Berater: Adresse
hinterlegt und Schalter *Mail bei neuem Projekt* an (*Einstellungen →
Akquise*). Der Schalter war bei Einführung für alle an.
* **Fehler** brechen das Speichern nie ab. Der Versand läuft nach der Antwort an
den Browser; Erfolg und Fehler stehen im Log:
`journalctl -u perinco-crm-backend | grep 'Akquise] Mail'`.
* **Ohne M365-Anbindung** (Secret fehlt) wird nur eine Warnung geloggt.
* Die `ApplicationAccessPolicy` (siehe oben) gilt auch für `Mail.Send` - die App
darf also nur aus crm@perinco.de senden, nicht im Namen anderer.
## Was noch nicht drin ist
* **Senden, Antworten, Weiterleiten.** Braucht `Mail.ReadWrite` und `Mail.Send`
und damit eine erneute Administratorzustimmung.
* **Antworten, Weiterleiten aus dem Postfachreiter.** Senden geht seit der
Berater-Mail (`Mail.Send`); Antworten auf eine konkrete Mail bräuchte
zusätzlich `Mail.ReadWrite`.
* **Anhänge.** `has_attachments` wird geführt und angezeigt, die Dateien
selbst werden nicht geholt.
* **Automatische Zuordnung zu Opportunities.** Die Zuordnung erfolgt per Hand;