Skip to the content
Documentation
Help Start
Reading in:
  • German: 9,090 of 9,090 pages
About the help in other languages
All help pages

E-Mail-Einstellungen und Einwilligung: die Spezifikation

Die Referenz des Systems für E-Mail-Einstellungen von Exponential 6.0.15: die Klassen, die Tabellen, die Einstellungen, die Abläufe, die Entscheidungen des Mail-Gates und das Format der Links. Lesen Sie sie, wenn Sie…

Download as PDF

Address: https://doc.exponential.earth/exphelp/viewer/specifications/6.0/mail-preferences.md

On this page

This page is a translation. Read the English original

E-Mail-Einstellungen und Einwilligung: die Spezifikation

Die Referenz des Systems für E-Mail-Einstellungen von Exponential 6.0.15: die Klassen, die Tabellen, die Einstellungen, die Abläufe, die Entscheidungen des Mail-Gates und das Format der Links. Lesen Sie sie, wenn Sie eine genaue Antwort brauchen; die Schritt-für-Schritt-Darstellungen sind die Anleitung für Administratoren und die Anleitung für Entwickler. Die rechtlichen Anforderungen und die Tests, die sie belegen, stehen auf der Rechts-Checkliste.

Bestandteile

BestandteilWo
Klassen (per Autoload geladen, Kernel)kernel/classes/mailpreferences/: expMailCategory, expMailCategoryRegistry, expMailCategoryHandler, expMailRecipient, expMailPreferences, expConsentContext, expConsentLog, expMailSuppression, expMailToken, expMailSecret, expMailGate, expMailPreferencesService, die Zeilenklassen expMailCategoryRow, expMailPreferenceRow, expMailPendingRow
Der Einhängepunkt des Gateslib/ezutils/classes/ezmailtransport.php (eZMailTransport::send() ruft expMailGate::dispatch() auf), lib/ezutils/classes/ezmail.php (setCategory(), category())
Modulkernel/mailpreferences/module.php; View-Klassen kernel/private/classes/views/mailpreferences/; gemeinsamer Seitencode Exponential\Service\MailPreferencesPage (kernel/private/classes/services/mailpreferencespage.php)
Templatesdesign/standard/templates/mailpreferences/ (Seiten, parts/, admin/, mail/); Rahmen in design/admin und design/admin4 (parts/page_start.tpl, page_end.tpl)
Befehleexp:mail:status, exp:mail:preferences, exp:mail:suppression, exp:mail:consent, exp:mail:gate (Referenz)
Cronjob-Teilmailpreferences (cronjobs/mailpreferences.php), auch in der Gruppe infrequent
Einstellungensettings/mailpreferences.ini; site.ini [RoleSettings] PolicyOmitList[]; menu.ini-Einträge my_mail und mailpreferences; cronjob.ini
Texteshare/translations/ger-DE/translation.ts, Kontexte design/standard/mailpreferences, design/admin/mailpreferences, kernel/mailpreferences, kernel/mailpreferences/categories, kernel/mailpreferences/mail, kernel/mailpreferences/status

Kategorien

expMailCategory ist ein Wertobjekt: identifier, name, description, essential, defaultOn (bei einer essenziellen Kategorie immer false), frequencies (Teilmenge von immediate, daily, weekly), doubleOptIn, source (ini, extension, admin), handlerClass. Ein Bezeichner besteht aus Kleinbuchstaben, Ziffern und Unterstrichen und beginnt mit einem Buchstaben.

expMailCategoryRegistry::instance() führt in dieser Reihenfolge zusammen:

  1. mailpreferences.ini [CategorySettings] Categories[] mit je einem Block [Category_<identifier>]; Quelle ini für die Bezeichner, die in der mitgelieferten settings/mailpreferences.ini aufgeführt sind, extension für die übrigen.
  2. Zeilen von expmail_category. Eine Zeile mit dem Bezeichner einer Kategorie aus Schritt 1 überschreibt deren Name, Beschreibung, Standardwert, Häufigkeiten und Double-Opt-in; essential und eine leere handler_class bleiben, wie die Einstellungen sie vorgeben. Andere Zeilen sind Kategorien der Quelle admin.
  3. register(): Kategorien, die im Code für diesen Prozess hinzugefügt wurden.

Die Liste wird für jede Anfrage neu gelesen ($_SERVER['REQUEST_TIME_FLOAT']), sodass persistente Worker Änderungen in der Administration sehen. all(), optional(), essential(), get(), iniCategories(), saveAdmin(), removeAdmin(), reset().

Die mitgelieferten Kategorien:

BezeichnerArtHäufigkeitenDouble-Opt-inHandler
contentoptionalsofort, täglich, wöchentlichneinexpNotificationMailCategoryHandler
collaborationoptionalsofort, täglich, wöchentlichneinexpNotificationMailCategoryHandler
newsletteroptionaleigener Zeitplanja(die Newsletter-Brücke)
marketingoptionaleigener Zeitplanja
systemoptionaleigener Zeitplannein
securityessenziell
ordersessenziell
legalessenziell
adminessenziell

Empfänger

expMailRecipient bezeichnet eine Person. Sein Schlüssel ist u:<user id> für ein Konto und a:<hash> für eine Adresse ohne Konto, wobei <hash> gleich expMailSuppression::hash( $email ) ist. fromAddress() liefert das Konto, wenn die Adresse zu einem gehört (zweites Argument false: die bloße Adresse). Außerdem fromUser(), fromUserId(), fromToken(), fromPayload(), fromKey(). logKey() ist das, was das Gate-Protokoll speichert: die Benutzer-ID oder die ersten Zeichen des Hashs.

Tabellen

Alle fünf stehen im Kernel-Schema von MySQL, PostgreSQL und SQLite, in share/db_schema.dba und in update/database/<engine>/6.0/dbupdate-6.0.0-6.0.15.sql. Zeiten sind Unix-Zeitstempel.

expmail_preference

Eine Zeile je Person und Kategorie, dazu der Hauptschalter (Kategorie _master).

SpalteBedeutung
idSchlüssel
recipient_keyu:<id> oder a:<hash>; eindeutig zusammen mit category
user_iddas Konto, 0 für eine Adresse
categoryBezeichner oder _master
stateon, off, pending
frequencyimmediate, daily, weekly oder leer
created, modifiedZeiten

Keine Zeile bedeutet „keine Wahl getroffen“: Es gilt, was der Handler ermittelt, sonst der Standardwert der Kategorie (aus).

Eine Zeile je Änderung; wird nie aktualisiert, außer durch die Anonymisierung.

SpalteBedeutung
id, createdSchlüssel, Zeit
recipient_key, user_id, emaildie Person; email ist bei einem Konto leer
categoryBezeichner, leer beim Hauptschalter und bei Aktionen, die die ganze Person betreffen
actionon, off, pending, confirm, master_on, master_off, frequency, erase, export, suppress, unsuppress, email_change
old_value, new_valueder Zustand oder die Häufigkeit davor und danach
sourcepage, link, admin, import, signup, bridge, confirm, system
wordingder genaue Text, den die Person gesehen hat (oder das --wording eines Befehls)
ip, actor_user_id, siteaccesswoher die Änderung kam und wer sie vorgenommen hat
anonymised1 nach der Löschung: recipient_key ist x:<irreversible hash>, email, ip, user_id werden geleert

Jede Zeile schreibt außerdem ein Audit-Ereignis: access.user.consent.erase, access.user.consent.export oder access.user.consent.change für jede andere Aktion.

expmail_suppression

SpalteBedeutung
email_hashsha256( lowercase( trim( email ) ) . derive( 'hash' ) ), eindeutig; die Adresse wird nie gespeichert
reasonbounce, complaint, unsubscribe_all, legal, admin, bridge ([SuppressionSettings] Reasons[])
noteFreitext für Administratoren; eine darin enthaltene Adresse wird entfernt
created, created_byZeit und Benutzer-ID

expmail_pending

Ein Double-Opt-in, das auf seine Bestätigung wartet.

SpalteBedeutung
recipient_key, user_iddie Person
kindcategory oder email_change (und link für die Ratenbegrenzung von „Link zusenden“)
categorybei category
dataJSON; bei email_change die neue Adresse
created, expiresZeiten; expires = created + [ConsentSettings] PendingDays

expmail_category

Die Kategorien und Überschreibungen des Administrators: identifier (eindeutig), name, description, essential, default_on, frequencies (durch Kommas getrennt), double_opt_in, handler_class, priority, created, modified.

Die Entscheidung für einen Empfänger

expMailPreferences::decision( $category ), in dieser Reihenfolge:

ErgebnisWann
unknown_categorykeine solche Kategorie
alloweine essenzielle Kategorie
suppresseddie Adresse steht auf der Sperrliste
master_offdie Person hat alle optionalen E-Mails abgeschaltet
pendingdie Kategorie wartet auf ihre Bestätigung
offdie Kategorie ist aus (gespeichert, vom Handler ermittelt oder der Standardwert)
allowsonst

allows() ist decision() === 'allow'.

Das Gate

expMailGate::dispatch( eZMail, eZMailTransport ):

E-MailWas geschiehtProtokolliert als
Keine Kategorieunverändert gesendetuncategorised mit der sendenden Datei (why: no_category) oder essential (why: essential_sender), wenn die From-Adresse, die Datei oder eine Klasse des Aufrufstapels in [GateSettings] EssentialSenders[] steht
Unbekannte Kategorieunverändert gesendetuncategorised, why: unknown_category
Essenzielle Kategoriemit X-Exp-Mail-Category gesendet, ohne Fußzeilesent, why: essential
Optional, niemand zugelassennichts gesendet, true zurückgegebenblocked je Empfänger mit der Entscheidung
Optional, einige zugelasseneine E-Mail je zugelassenem Empfänger (To, Cc und Bcc bleiben in ihrem Feld), jede ergänzt; das Mail-Objekt erhält danach seine Empfänger und seinen Text zurücksent je Empfänger, blocked je blockiertem Empfänger
Optional, SplitRecipients=disabled und mehrere zugelasseneine E-Mail an alle Zugelassenen; Fußzeile mit der Seite „Link zusenden“, kein List-Unsubscribesent je Empfänger
Gate=disabledoptionale E-Mails gehen an alle außer gesperrten Adressen, weiterhin ergänztwie oben
Eine Exception im Gateoptionale E-Mails werden nicht gesendet (false); andere E-Mails gehen hinauserror

decorate( eZMail, recipient, category ) fügt X-Exp-Mail-Category hinzu und bei optionalen E-Mails mit bekanntem Empfänger die Header

List-Unsubscribe: <https://www.example.com/mailpreferences/unsubscribe/m1...>
List-Unsubscribe-Post: List-Unsubscribe=One-Click

sowie die Fußzeile aus [FooterSettings] Template (ein eingebauter Text, wenn das Template fehlt): bei Text-E-Mails am Ende nach -- , bei HTML vor </body>, in jedem Textteil eines ezcMailPart-Inhalts. Es ändert nie From, Reply-To, Subject oder andere Header.

Das Protokoll ([GateSettings] LogFile, Standard log/mailgate.jsonl im var-Verzeichnis, bei MaxLogSize nach .1 rotiert) enthält ein JSON-Objekt pro Zeile: t Zeit, d Entscheidung, c Kategorie, why, r der Protokollschlüssel des Empfängers, s die sendende Datei. Es enthält keine Adresse. expMailGate::stats( $since ) zählt es für die Statusseite aus; lastResult() beschreibt den letzten Versand (category, decision: sent, partly_blocked, blocked, essential, uncategorised, unknown_category; sent, blocked, result).

expMailToken::create( recipient, purpose, category = null, ttl = null, extra = array() ):

  • Zwecke unsubscribe, manage, confirm;
  • Nutzdaten als JSON { p: purpose, t: issued, x: expires (0 never), u: user id, e: address (only without account), c: category, i: pending id };
  • verschlüsselt mit AES-256-GCM, 12-Byte-IV, 16-Byte-Tag, zusätzliche Daten exp-mail-token, Schlüssel HMAC-SHA-256( 'exp-mailpreferences:token', site secret );
  • geschrieben als m1 + base64url( IV . ciphertext . tag ).

verify( $token, $purpose ) liefert purpose, user, email, category, pending, issued, expires oder null; lastError(): malformed, tampered, purpose, expired. Standard-Gültigkeitsdauern, [TokenSettings] TTL[]: unsubscribe 0 (nie ablaufend), manage 0, confirm 604800 (7 Tage); ein „Link zusenden“-Link RequestLinkTTL (86400). Die Adresse lautet <BaseURL>/mailpreferences/<view>/<token>.

Das Site-Geheimnis (expMailSecret): 32 Zufallsbytes, base64-kodiert in settings/override/mailpreferences.ini.append.php [SecretSettings] TokenSecret, beim ersten Gebrauch unter einer Sperre erzeugt. derive( $purpose ) liefert den Schlüssel für token, hash (Sperrlisten- und Adressschlüssel) und anonymise.

Abläufe

Eine Kategorie einschalten (expMailPreferences::set( $category, true, $context )): Eine Kategorie ohne Double-Opt-in oder ein Kontext der Quelle confirm, bridge oder import ist sofort on (Protokoll on bzw. confirm). Andernfalls wird der Zustand pending, eine Zeile in expmail_pending wird geschrieben, das Protokoll vermerkt pending, und die Bestätigungs-E-Mail (Kategorie security, Template mail/confirm.tpl) geht mit einem confirm-Link an die Adresse, es sei denn, $context->sendConfirmation ist false oder die Adresse ist wegen eines Bounce, einer Beschwerde oder aus rechtlichem Grund gesperrt. Das Einschalten über page, link, confirm oder signup hebt die eigene unsubscribe_all-Sperre der Person auf.

Bestätigen (mailpreferences/confirm/<token>): GET zeigt eine Schaltfläche; das POST von Ja, bestätigen ruft expMailPreferencesService::confirm() auf: confirmed, already, expired (die ausstehende Zeile wird entfernt) oder invalid.

Abmelden (mailpreferences/unsubscribe/<token>): GET zeigt eine Schaltfläche; deren POST oder ein POST mit dem Inhalt List-Unsubscribe=One-Click (RFC 8058; kein Cookie, kein Formular-Token) ruft expMailPreferencesService::unsubscribe() auf: Ein Link mit Kategorie schaltet die Kategorie ab, ein Link ohne Kategorie schaltet den Hauptschalter ab. Das One-Click-POST antwortet mit 200 text/plain („Sie sind abgemeldet.“) oder mit 400 bei einem Link, der nicht funktioniert. unsubscribeAll() schaltet den Hauptschalter ab und setzt die Adresse auf die Sperrliste (unsubscribe_all).

Link zusenden (mailpreferences/request): requestLink( $email ) liefert sent, invalid, rate_limited ([TokenSettings] RequestLinkLimit pro Stunde) oder blocked; die Seite zeigt für jede formal gültige Adresse dieselbe Antwort.

Adressänderung (requestEmailChange( $user, $email, $context )): invalid, unchanged, in_use oder pending_confirmation; das Konto behält seine Adresse, bis der an die neue Adresse gesendete Link bestätigt ist.

Registrierung: MailPreferencesPage::signupCategories() liefert die Kästchen des Registrierungsformulars, keines angekreuzt; storeSignup() speichert nur, was angekreuzt wurde, mit der Quelle signup und dem Text des Formulars.

Export und Löschung: export() liefert den Empfänger, den Hauptschalter, jede Kategorie mit Zustand, Häufigkeit und Zeit, ausstehende Bestätigungen und das gesamte Einwilligungsprotokoll; exportToCsv() schreibt das als Zeilen section,key,value,detail. erase( $context ) schreibt eine erase-Zeile, löscht die Einstellungen und die ausstehenden Zeilen und anonymisiert jede Protokollzeile der Person.

Aufbewahrung (expConsentLog::cleanup( $dryRun ), Cronjob-Teil mailpreferences): entfernt Protokollzeilen, die älter als [ConsentSettings] RetentionDays sind, von Personen, die nicht mehr da sind (anonymisiert, ein entferntes Konto, eine Adresse ohne Einstellung), entfernt abgelaufene ausstehende Zeilen und schaltet deren Kategorien ab, und entfernt Sperrlisteneinträge, die älter als [SuppressionSettings] RetentionDays sind, sofern dieser Wert über 0 liegt.

Modul-Views

ViewAnmeldungZweck
settingsangemeldetdie Seite der Person; sendet MailPreferencesForm = master (MasterOffButton, MasterOnButton) oder categories (CategoryShown[], Category[<id>], Frequency[<id>], StoreButton)
manage/<token>Linkdieselbe Seite über einen manage-Link
unsubscribe/<token>LinkAbschnitt „Abläufe“
confirm/<token>LinkAbschnitt „Abläufe“
requestkeine„Link zusenden“
export/<json|csv>[/(token)/<token>]angemeldet oder Linkder Datendownload
admin/<status|categories|suppression|consent|user>[/<id>]mailpreferences/administratedie Seiten des Administrators; Einwilligungsfilter /(person)/…/(category)/…/(source)/…/(from)/…/(to)/… (das Filterformular wird gesendet und mit 303 an diese Adresse beantwortet), /(export)/csv (Richtlinie mailpreferences/export; die Seite eines Benutzers auch /(export)/json), die Benutzersuche /(q)/…; /(offset)/<n>; nie Parameter im Query-String

Seiten, die über einen persönlichen Link erreicht werden, werden mit Cache-Control: private, no-store, max-age=0, Referrer-Policy: no-referrer und X-Robots-Tag: noindex, nofollow ausgeliefert. Jede Seite funktioniert ohne JavaScript.

Einstellungen: mailpreferences.ini

BlockSchlüsselStandardBedeutung
GateSettingsGateenableddisabled: optionale E-Mails gehen an alle außer gesperrten Adressen (weiterhin ergänzt)
EssentialSenders[]die Absender des Kernels für Konten, Bestellungen, Audit und Setup, expMailPreferencesServiceE-Mails ohne Kategorie von diesen Absendern werden als essenziell protokolliert
LogFilelog/mailgate.jsonlrelativ zum var-Verzeichnis
MaxLogSize5242880Bytes vor der Rotation
SplitRecipientsenabledeine optionale E-Mail je Empfänger
CategorySettingsCategories[]neun Bezeichnerdie Reihenfolge auf der Seite
Category_<id>Name, Description, Essential, DefaultOn, Frequencies[], DoubleOptIn, HandlerClasssiehe die Anleitung für Entwickler
FooterSettingsOrganisationName, OrganisationAddressleerAbsender und Postanschrift in der Fußzeile; \n für einen Zeilenumbruch
Templatedesign:mailpreferences/mail/footer.tpldas Template der Fußzeile
LinkSettingsBaseURLleer (https:// + SiteURL des Standard-Siteaccess)wohin Links zeigen
TokenSettingsTTL[unsubscribe], TTL[manage], TTL[confirm]0, 0, 604800Gültigkeitsdauer der Links in Sekunden
RequestLinkTTL, RequestLinkLimit86400, 3„Link zusenden“
ConsentSettingsRetentionDays, PendingDays1095, 7Aufbewahrung
SuppressionSettingsRetentionDays0 (unbegrenzt)
Reasons[]sechs Gründe
Listeners[]leerKlassen, die über hinzugefügte und aufgehobene Einträge informiert werden
SecretSettingsTokenSecretwird in den Override erzeugtniemals committen

Verwandte Seiten

Something wrong on this page? Report an error

Documentation license

This documentation is free documentation, licensed under the GNU Free Documentation License 1.3 or later.

Exponential Copyright © 1998-2026 Exponential Foundation and 7x