From 41e9f6898fca584945b517d9d3b21bec4da2b8d4 Mon Sep 17 00:00:00 2001 From: Sascha Wolf Date: Tue, 11 Aug 2026 14:45:36 +0200 Subject: [PATCH] =?UTF-8?q?feat(kontakte):=20Einverst=C3=A4ndnis=20f=C3=BC?= =?UTF-8?q?r=20Mails=20und=20Mailingliste?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Am Kontakt gibt es unter der E-Mail-Adresse das Kästchen "Einverständnis für Mails". Ohne Adresse ist es gesperrt. Der Zeitpunkt wird in `mail_consent_at` mitgeschrieben und im Kontakt angezeigt: bei einer Beschwerde ist nicht die Frage, ob ein Einverständnis vorliegt, sondern seit wann. Beim Widerruf wird er geleert; ein erneutes Speichern verschiebt ihn nicht. Der Knopf "Mailingliste erstellen" in der Kontaktleiste sammelt alle Adressen mit Haken, durch Komma getrennt, mit Zähler am Knopf. Rechts im Feld ein Kopiersymbol (Zwischenablage, mit Fallback für Browser ohne die Schnittstelle) und ein Mailsymbol. Zum Mailsymbol zwei Entscheidungen: - Die Adressen gehen ins BCC, nicht ins An-Feld. Im An-Feld sähe jeder Empfänger die vollständige Kundenliste. - Windows gibt an das Mailprogramm nur rund 2000 Zeichen weiter. Ab 1900 Zeichen ist das Symbol deshalb gesperrt und der Dialog erklärt es - sonst wäre die Empfängerliste unbemerkt abgeschnitten. Nur für richtige Kontakte: Der Vorbereich "Aus Mails" hat das Kästchen nicht, und beim Übernehmen wird der Haken nicht mitgesetzt - dass jemand eine Mail geschrieben hat, ist keine Einwilligung in Werbung. Das Backend weist ein `mail_consent` für Einträge mit `mail_pool = 1` ab. Sichtbar ohne Öffnen: grünes Briefsymbol in der Kachel, Häkchen hinter der Adresse in der Liste. Geprüft im Browser gegen das Stub-Backend: Haken setzen und widerrufen, Zähler, Komma-Liste, Zwischenablage, mailto mit BCC, kein Kästchen im Vorbereich (15 Prüfungen). Co-Authored-By: Claude Opus 5 (1M context) --- docs/02-datenmodell.md | 2 + docs/07-anleitung-benutzer.md | 52 +++++ docs/09-quellcode.md | 1 + docs/10-glossar.md | 2 + docs/bilder/kontakt-einverstaendnis.png | Bin 0 -> 114101 bytes docs/bilder/kontakte-mailingliste.png | Bin 0 -> 149408 bytes server/src/routes/leads.js | 37 +++- server/src/schema.sql | 12 ++ src/components/leads/LeadGrid.tsx | 33 ++- src/components/leads/LeadList.tsx | 30 ++- src/components/leads/LeadModal.tsx | 41 ++++ src/components/leads/Leads.tsx | 37 ++++ src/components/leads/MailingListDialog.tsx | 226 +++++++++++++++++++++ src/types.ts | 8 + 14 files changed, 463 insertions(+), 18 deletions(-) create mode 100644 docs/bilder/kontakt-einverstaendnis.png create mode 100644 docs/bilder/kontakte-mailingliste.png create mode 100644 src/components/leads/MailingListDialog.tsx diff --git a/docs/02-datenmodell.md b/docs/02-datenmodell.md index 0280c47..90db0ba 100644 --- a/docs/02-datenmodell.md +++ b/docs/02-datenmodell.md @@ -43,6 +43,8 @@ erDiagram enum status "Neu .. Verloren" varchar source "z.B. 'Mail' bei Herkunft Postfach" tinyint mail_pool "1 = Vorbereich 'Aus Mails', noch kein Kontakt" + tinyint mail_consent "Einverständnis für Werbemails" + datetime mail_consent_at "wann erteilt - der Nachweis" longtext tags "JSON-Array als Text" longtext avatar int owner_id FK diff --git a/docs/07-anleitung-benutzer.md b/docs/07-anleitung-benutzer.md index d39af31..10df899 100644 --- a/docs/07-anleitung-benutzer.md +++ b/docs/07-anleitung-benutzer.md @@ -164,6 +164,58 @@ Sobald Kontakte aus dem Postfach übernommen wurden, erscheint neben dem Statusfilter ein **Herkunftsfilter**: *Aus Mails übernommen* zeigt nur die aus dem Postfach stammenden, *Selbst angelegt* nur die von Hand erfassten. +### Einverständnis für Mails + +Im Kontakt steht direkt unter der E-Mail-Adresse das Kästchen **Einverständnis +für Mails**. Nur mit diesem Haken kommt die Adresse in eine Mailingliste. Ohne +eingetragene Adresse ist das Kästchen gesperrt - es gibt dann nichts, wozu +jemand einwilligen könnte. + +![Kontakt mit gesetztem Einverständnis für Mails](bilder/kontakt-einverstaendnis.png) + +Der Zeitpunkt wird mitgespeichert und im Kontakt angezeigt („Erteilt am …"). +Beim Widerruf verschwindet er wieder. Bei einer Beschwerde ist nämlich nicht die +Frage, *ob* ein Einverständnis vorliegt, sondern *seit wann*. + +Wo der Haken gesetzt ist, erscheint das Briefsymbol der Kachel grün, in der +Liste steht ein Häkchen hinter der Adresse. So sieht man es ohne jeden Kontakt zu +öffnen. + +Zwei Dinge, die bewusst so sind: + +* **Im Vorbereich *Aus Mails* gibt es das Kästchen nicht.** Dass jemand eine Mail + geschrieben hat, ist keine Einwilligung in Werbung. +* **Beim Übernehmen aus *Aus Mails* wird der Haken nicht mitgesetzt.** Ein neu + übernommener Kontakt startet immer ohne Einverständnis. + +### Mailingliste erstellen + +Der Knopf **Mailingliste erstellen** in der Kontaktleiste sammelt alle Adressen +mit Einverständnis, durch Komma getrennt. Die Zahl am Knopf sagt vorab, wie viele +das sind. + +![Dialog Mailingliste mit Kopier- und Mailsymbol](bilder/kontakte-mailingliste.png) + +Rechts im Feld stehen zwei Symbole: + +| Symbol | Wirkung | +| --- | --- | +| **Kopieren** | legt die komplette Liste in die Zwischenablage - danach in Outlook ins BCC-Feld einfügen | +| **Brief** | öffnet direkt eine neue Mail im Mailprogramm, die Adressen stehen im **BCC** | + +Der Brief-Weg (`mailto:`) hat eine Grenze: Windows gibt nur rund 2000 Zeichen an +das Mailprogramm weiter. Wird die Liste länger, ist das Symbol gesperrt und der +Dialog sagt es - sonst würde die Empfängerliste unterwegs abgeschnitten, ohne +dass es jemand merkt. Dann bleibt der Weg über die Zwischenablage. + +Die Adressen gehen absichtlich ins **BCC** und nicht ins An-Feld: dort sähe jeder +Empfänger die vollständige Kundenliste. + +Unter *Wer ist dabei* stehen Name, Firma und Adresse aller Empfänger zum +Nachprüfen. Darunter steht, wie viele Kontakte fehlen - ohne Haken oder mit Haken +aber ohne Adresse. Das **Trennzeichen** lässt sich auf Semikolon umstellen, falls +Outlook die Komma-Liste nicht auflöst. + ### Aus Mails Der Menüpunkt *Kontakte* klappt zwei Unterpunkte auf: *Alle Kontakte* und diff --git a/docs/09-quellcode.md b/docs/09-quellcode.md index a171e3e..1187172 100644 --- a/docs/09-quellcode.md +++ b/docs/09-quellcode.md @@ -246,6 +246,7 @@ Warum genau diese Konstanten festgelegt sind, steht in | `components/leads/mailPool.ts` | `findMailPoolMatch()`, `diffFields()`, `isConflict()`, `MAIL_POOL_FIELDS` - Dublettenabgleich des Vorbereichs | | `components/leads/MailPoolLeads.tsx` | Ansicht „Aus Mails": Goldmarkierung, Abweichungen, Übernehmen, Sammelübernahme | | `components/leads/MailPoolMergeDialog.tsx` | Feldauswahl beim Ergänzen eines vorhandenen Kontakts | +| `components/leads/MailingListDialog.tsx` | Adressen der Kontakte mit Einverständnis: Zwischenablage und `mailto:` mit BCC, Längengrenze 1900 Zeichen | | `components/scanner/scannerUi.tsx` | `cardClass`, Buttonklassen, `MatchBadge`, `MatchStatusBadge`, `PortalStatusPill`, `formatDateTime`, `projectTimestamp` | | `components/mail/mailUi.tsx` | `Badge`, `ConfidenceBar`, Herkunfts- und Statusbeschriftungen, `formatAddresses`, `avatarColor` | | `components/mail/MailBody.tsx` | Mailinhalt im `