admin: Mail-Sperrliste, Markierung nicht erreichbarer Newsrooms (Roadmap 1b.6, Schritt 4)
Admin ▸ Mail-Sperrliste mit Freigabe, manueller Sperre, nicht lesbaren Rückläufern und Breaker-Zustand. Firmenseite markiert gesperrte Firmen-E-Mail und Pressekontakte. Die Claim-Seite zählt gesperrte Adressen nicht mehr als Empfänger und erklärt, warum kein Link geht. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
f9c97ccf2f
commit
e7e12b9436
12 changed files with 426 additions and 9 deletions
|
|
@ -6,6 +6,7 @@ use App\Enums\ConversionSource;
|
|||
use App\Models\Company;
|
||||
use App\Scopes\PortalScope;
|
||||
use App\Services\Auth\ContactAccessService;
|
||||
use App\Services\Mail\EmailSuppressionService;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
|
|
@ -26,7 +27,10 @@ use Illuminate\Support\Str;
|
|||
*/
|
||||
class NewsroomClaimService
|
||||
{
|
||||
public function __construct(private readonly ContactAccessService $contactAccess) {}
|
||||
public function __construct(
|
||||
private readonly ContactAccessService $contactAccess,
|
||||
private readonly EmailSuppressionService $suppressions,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Firma zu einem Slug auf diesen Portalen — auch ohne veröffentlichte
|
||||
|
|
@ -48,16 +52,42 @@ class NewsroomClaimService
|
|||
/**
|
||||
* Empfänger des Anmeldelinks: die Firmen-E-Mail, sonst die Adressen der
|
||||
* Pressekontakte. Bewusst nicht beides — ein Klick eines Fremden soll
|
||||
* nicht fünf Postfächer treffen.
|
||||
* nicht fünf Postfächer treffen. Gesperrte Adressen (Bounce-Suppression,
|
||||
* 1b.6) zählen nicht: Ein Newsroom, dessen einzige Adresse tot ist, ist
|
||||
* nicht beanspruchbar — siehe isUnreachable().
|
||||
*
|
||||
* @return Collection<int, string>
|
||||
*/
|
||||
public function recipients(Company $company): Collection
|
||||
{
|
||||
$candidates = $this->candidateRecipients($company);
|
||||
|
||||
if ($candidates === []) {
|
||||
return collect();
|
||||
}
|
||||
|
||||
$suppressed = $this->suppressions->suppressedAmong($candidates);
|
||||
|
||||
return collect(array_values(array_filter($candidates, fn (string $email): bool => ! in_array($email, $suppressed, true))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Es gäbe Adressen, aber alle sind gesperrt.
|
||||
*/
|
||||
public function isUnreachable(Company $company): bool
|
||||
{
|
||||
return $this->candidateRecipients($company) !== [] && $this->recipients($company)->isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<string>
|
||||
*/
|
||||
private function candidateRecipients(Company $company): array
|
||||
{
|
||||
$companyEmail = Company::emailKey($company->email);
|
||||
|
||||
if ($companyEmail !== null) {
|
||||
return collect([$companyEmail]);
|
||||
return [$companyEmail];
|
||||
}
|
||||
|
||||
$emails = [];
|
||||
|
|
@ -70,7 +100,7 @@ class NewsroomClaimService
|
|||
}
|
||||
}
|
||||
|
||||
return collect(array_values($emails));
|
||||
return array_values($emails);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue