presseportale/app/Observers/EmailDomainObserver.php
Kevin Adametz f581e1eb3a mail: Kontakterreichbarkeit - Formpruefung, Domainpruefung, Einlieferer-Bericht
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>
2026-09-16 09:22:39 +00:00

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();
}
}