Vier Punkte aus kontakterreichbarkeit-mx-bounces-2026-09-15.md, ohne Veroeffentlichungssperre: - PlausibleEmailDomain: Domain ohne Endung oder mit Tippfehler-TLD ist ein 422 an der Legacy-API, deterministisch ohne DNS. - email_domain_checks + MailDomainChecker ueber DnsResolver-Schnittstelle (RFC 5321 impliziter MX, RFC 7505 Null MX, Unresolved ist kein Befund), Observer an Company/Contact, Job nach Commit, taeglicher Refresh, mail:check-domains fuer den Bestand. Nie eine Adresssperre aus DNS. - Admin > Reports > Einlieferer-Bericht: tote Adressen aus Sperrliste und Domainbefund, automatisch abgelehnte Meldungen mit Grund, Text zum Kopieren und CSV. Versendet nichts. - EmailBounceKind::Policy: 5.7.x wird protokolliert, zaehlt aber nicht auf den Schwellwert. Statuscode entscheidet vor Diagnosetext. Messung vorab: 6 von 877 API-Domains ohne Zustellweg, eine davon fuer 66 der 151 Ruecklaeufer verantwortlich. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
57 lines
1.6 KiB
PHP
57 lines
1.6 KiB
PHP
<?php
|
|
|
|
namespace App\Observers;
|
|
|
|
use App\Jobs\CheckEmailDomain;
|
|
use App\Models\Company;
|
|
use App\Models\Contact;
|
|
use App\Models\EmailDomainCheck;
|
|
use App\Rules\PlausibleEmailDomain;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
|
|
/**
|
|
* Stößt die Domainprüfung an, sobald eine Kontaktadresse entsteht oder sich
|
|
* ändert (Kontakterreichbarkeit, Abschnitt 5.4).
|
|
*
|
|
* Am Model statt in den Controllern: API v1, Legacy-API, Admin und
|
|
* Kundenportal schreiben dieselben Felder und bekommen damit dieselbe
|
|
* Prüfung — ohne dass eine Strecke es vergessen kann. Der Job läuft nach dem
|
|
* Commit; die Anfrage wartet nie auf DNS.
|
|
*
|
|
* Eine Korrektur der Adresse macht den alten Befund gegenstandslos: geprüft
|
|
* wird die neue Domain, und der Datensatz zeigt danach deren Ergebnis.
|
|
*/
|
|
class EmailDomainObserver
|
|
{
|
|
public function created(Model $model): void
|
|
{
|
|
$this->queue($model);
|
|
}
|
|
|
|
public function updated(Model $model): void
|
|
{
|
|
if ($model->wasChanged('email')) {
|
|
$this->queue($model);
|
|
}
|
|
}
|
|
|
|
private function queue(Company|Contact|Model $model): void
|
|
{
|
|
$domain = PlausibleEmailDomain::domainOf($model->getAttribute('email'));
|
|
|
|
if ($domain === null) {
|
|
return;
|
|
}
|
|
|
|
// Frischer Befund vorhanden? Dann kostet die Einreichung keine
|
|
// DNS-Abfrage — bei einem Einlieferer mit 68 Meldungen aus derselben
|
|
// Domain ist das der Regelfall.
|
|
$known = EmailDomainCheck::query()->where('domain', $domain)->first();
|
|
|
|
if ($known?->isFresh()) {
|
|
return;
|
|
}
|
|
|
|
CheckEmailDomain::dispatch($domain)->afterCommit();
|
|
}
|
|
}
|