- PHP 100%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| _config | ||
| src | ||
| .gitignore | ||
| composer.json | ||
| LICENSE | ||
| PLAN.md | ||
| README.md | ||
ErrorMailer für SilverStripe
Schickt SilverStripe-Fehlermeldungen per E-Mail — über einen eigenen Mail-Zugang, der vom Mail-Versand der Website vollständig unabhängig ist.
Läuft auf SilverStripe 4, 5 und 6 aus einem Paket.
ACHTUNG: Noch unvollständig funktioniert prinzipiell hat aber noch potentielle Sicherheitslücken noch nicht verwenden
Warum
Einen dedizierten „Error Mailer" gibt es seit SilverStripe 4 nicht mehr (Debug::send_errors_to()
ist entfallen). Die offizielle Doku
zeigt Monolog\Handler\NativeMailerHandler — der versendet aber über PHP-mail() und kennt
keine SMTP-Zugangsdaten.
Dieses Modul hängt stattdessen einen Monolog-Handler mit eigenem Transport an
Psr\Log\LoggerInterface. Weil SilverStripe\Logging\MonologErrorHandler diesen Logger als
PHP-Error-/Exception-Handler registriert, erfasst er:
- uncaught Exceptions und Fatal Errors,
- eigene Aufrufe von
Injector::inst()->get(LoggerInterface::class)->error(…).
Es gibt bewusst keinen Fallback auf den Mail-Zugang der Website. Ist nichts konfiguriert, wird
nichts versendet (NullHandler).
Installation
-
Ordner
errormailer/ins Projektstammverzeichnis kopieren. -
Zugangsdaten anlegen:
cd errormailer/_config cp errormailer-credentials.yml.dist errormailer-credentials.ymlDatei ausfüllen (Empfänger, Absender, SMTP-Zugang).
-
?flush=1.
Ein Ordner mit _config/ wird von SilverStripe als Modul erkannt, die Klassen findet der
Class-Manifest — ein Composer-Eintrag ist nicht nötig (composer.json liegt für die spätere
Packagist-Veröffentlichung bei). dev/build wird nicht gebraucht: das Modul legt keine
Datenbanktabellen an.
Die ausgefüllte errormailer-credentials.yml ist über die .gitignore des Moduls aus dem
Repository ausgeschlossen — ausgeliefert wird nur die .dist-Vorlage, die pro Umgebung einmal
händisch gepflegt wird.
Konfiguration
Die gesamte Konfiguration kommt aus der YAML — ohne jeden Datenbankzugriff. Das ist Absicht: Fehler-Mails müssen gerade dann rausgehen, wenn die Datenbank nicht erreichbar ist. Der Versandpfad berührt die Datenbank an keiner Stelle.
Zugangsdaten in _config/errormailer-credentials.yml (aus der .dist-Vorlage kopiert):
---
Name: errormailer-credentials
After:
- 'errormailer'
- 'errormailer-dev'
---
ErrorMailer\ErrorEmailer:
enabled: true
send_to: 'fehler@example.com'
send_from: 'noreply@example.com'
send_from_name: 'Website Fehler'
subject: '[example.com] %level_name%: %message%'
smtp_server: 'smtp.example.com'
smtp_port: 587
smtp_user: 'noreply@example.com'
smtp_password: 'geheim'
level: 'error'
deduplicate_seconds: 300
Statt der smtp_*-Felder geht auch eine vollständige DSN (dsn: 'smtp://user:pw@host:465');
sie hat Vorrang.
Optional: Pflege im CMS
Wer die Zugangsdaten lieber im CMS pflegt, kopiert zusätzlich
errormailer-siteconfig.yml.dist → errormailer-siteconfig.yml und führt dev/build aus. Dann
erscheinen die Felder unter Einstellungen → Fehler-Mails (bzw. im Tab Email Einstellungen, wenn
moritz-sauer-13/silverstripe-mailconfig installiert ist) und überschreiben die YAML-Werte — aber
nur, solange die Datenbank erreichbar ist. Für den Ausfall-Fall sollte in der YAML trotzdem ein
funktionierender Zugang stehen.
Das Modul hängt an keiner Stelle von silverstripe-mailconfig ab; es bringt seine eigenen Felder
mit und funktioniert deshalb auch auf SS4-/SS5-Sites, wo dieses Paket nicht installierbar ist.
Alle Optionen
| Option | Default | Bedeutung |
|---|---|---|
enabled |
true |
In der dev-Umgebung standardmäßig auf false |
level |
'error' |
Monolog-Level, z. B. warning, error, critical |
send_to |
'' |
Empfänger |
send_from / send_from_name |
'' |
Absender; leer = Empfänger |
subject |
'[SilverStripe] %level_name%: %message%' |
Monolog ersetzt die Platzhalter |
dsn |
'' |
Vollständige DSN, hat Vorrang vor den smtp_*-Feldern |
smtp_server, smtp_port, smtp_user, smtp_password |
'' / 587 |
SMTP-Zugang |
smtp_encryption |
'' |
tls / ssl; nur für SS4 (SwiftMailer) relevant |
deduplicate_seconds |
0 |
>0 bündelt gleichartige Fehler und schützt vor Mailfluten |
use_siteconfig |
false |
SiteConfig-Felder auswerten (braucht errormailer-siteconfig.yml) |
formatter |
SilverStripe\Logging\DetailedErrorFormatter |
Beliebiger Monolog-Formatter |
handler_class |
'auto' |
symfony, swift oder native erzwingen |
In der dev-Umgebung ist das Modul per Default abgeschaltet. Zum Testen:
---
Name: errormailer-dev-on
After: 'errormailer-dev'
Only:
environment: dev
---
ErrorMailer\ErrorEmailer:
enabled: true
Testen
/_errormailer zeigt die effektive Konfiguration (Passwörter maskiert) und das gewählte Backend,
/_errormailer/send schickt eine Testmeldung durch den Logger. Zugriff nur als Admin oder in der
dev-Umgebung. Auf der Konsole:
vendor/bin/sake navigate _errormailer/send # SS6
Fehler beim Versand landen ausschließlich im PHP-error_log ([errormailer] …) — niemals im
SilverStripe-Logger, sonst gäbe es eine Endlosschleife im Error-Handler.
Versions-Kompatibilität
| SS 4.13 | SS 5 | SS 6 | |
|---|---|---|---|
| PHP | ^7.4 || ^8.0 |
^8.1 |
^8.3 |
| Monolog | ^1.16 |
^3.2 |
^3.8 |
| Mail-Backend | swiftmailer | symfony/mailer | symfony/mailer |
| gewählter Adapter | SwiftMailerAdapter |
SymfonyMailerAdapter |
SymfonyMailerAdapter |
Das Modul entscheidet zur Laufzeit anhand der tatsächlich vorhandenen Klassen, nicht anhand der
SilverStripe-Version: SymfonyMailerAdapter → SwiftMailerAdapter → NativeMailerAdapter.
Damit ein Paket für alle drei Versionen reicht:
- Keine Monolog-Interfaces werden selbst implementiert — die Signaturen unterscheiden sich
zwischen Monolog 1 (
array $record) und 3 (LogRecord). Das Modul baut nur vorhandene Handler. - Backend-spezifische Klassen werden als anonyme Klassen in Methodenrümpfen deklariert. Sie entstehen erst, wenn das jeweilige Backend tatsächlich verwendet wird — die Dateien sind auf jeder Version gefahrlos ladbar.
Factory::create()wird alscreate($service, array $params = []): ?objectdeklariert: untypisierter Parameter (erlaubt gegenüber SS6sstring $service), gesetzter Rückgabetyp (erlaubt gegenüber den untypisierten Interfaces in SS4/5).- Die SiteConfig-Extension erbt von
SilverStripe\Core\Extension(DataExtensionist in SS6 entfernt);$dbaus Extensions wird vom Config-Layer unabhängig von der Basisklasse gemergt. - Sprachniveau durchgängig PHP 7.4.
Aufbau
| Datei | Aufgabe |
|---|---|
src/ErrorEmailer.php |
Config-Klasse; ermittelt Empfänger, Absender und Zugangsdaten |
src/ErrorEmailHandlerFactory.php |
baut den Monolog-Handler, wählt das Backend |
src/ErrorMailTransportFactory.php |
optionaler benannter Symfony-Transport (SS5/6) |
src/Mail/*Adapter.php |
die drei Mail-Backends |
src/Extension/SiteConfigErrorMailExtension.php |
CMS-Felder (optional, nicht standardmäßig aktiv) |
src/Control/ErrorMailTestController.php |
Diagnose-Route /_errormailer |
Warum alles „lazy" ist
CoreKernel::boot() startet das Error-Handling vor dem Datenbank-Bootstrap
(CoreKernel.php:48) — der Handler
entsteht also, bevor überhaupt eine Datenbankverbindung existiert. Deshalb lösen die Adapter
Empfänger, Absender und Transport erst beim Versand auf: über ein Closure als
Nachrichten-Template und einen Mailer, der seinen Transport erst in send() erzeugt.
Für den YAML-Standardweg ist das reine Robustheit — dort wird ohnehin nie die Datenbank berührt.
Gebraucht wird die Lazy-Auflösung erst bei aktivierter CMS-Pflege (use_siteconfig: true), weil die
SiteConfig zum Boot-Zeitpunkt noch nicht lesbar ist.
Einzige Ausnahme: handler_class: 'native'. NativeMailerHandler baut Empfänger, Absender und
Betreff schon im Konstruktor ein — dort greifen nur die YAML-Werte.
Bekannte Einschränkungen
- Bei aktivierter CMS-Pflege (
use_siteconfig: true) liegt das SMTP-Passwort im Klartext in der Datenbank. - Kein Rate-Limit über
deduplicate_secondshinaus. - Auf SS4 ist die
$db-Übernahme aus einer reinenExtension(stattDataExtension) noch nicht praktisch verifiziert — betrifft nur die optionale CMS-Pflege, nicht den YAML-Standardweg.