Package and individual mail sender, new report, and other changes

Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
Simon Pocrnjič
2026-05-11 21:32:30 +02:00
parent b6bfa17980
commit e3bc5da7e3
49 changed files with 4754 additions and 249 deletions
+54
View File
@@ -0,0 +1,54 @@
<?php
namespace App\Services\Contact;
use App\Models\Email;
use App\Models\Person\Person;
class EmailSelector
{
/**
* Select the best email for a person following priority rules.
* Priority:
* 1) verified primary email that is active
* 2) primary email that is active
* 3) any active and valid email
* 4) first active email
*
* Returns an array shape: ['email' => ?Email, 'reason' => ?string]
*/
public function selectForPerson(Person $person): array
{
$emails = Email::query()
->where('person_id', $person->id)
->where('is_active', true)
->orderBy('is_primary', 'desc')
->orderBy('id')
->get();
if ($emails->isEmpty()) {
return ['email' => null, 'reason' => 'no_active_emails'];
}
// 1) verified primary
$email = $emails->first(fn (Email $e) => $e->is_primary && $e->verified_at !== null);
if ($email) {
return ['email' => $email, 'reason' => null];
}
// 2) primary (any verification)
$email = $emails->first(fn (Email $e) => $e->is_primary);
if ($email) {
return ['email' => $email, 'reason' => null];
}
// 3) valid (any)
$email = $emails->first(fn (Email $e) => $e->valid);
if ($email) {
return ['email' => $email, 'reason' => null];
}
// 4) first active
return ['email' => $emails->first(), 'reason' => null];
}
}