admin: Verlauf protokolliert jede versendete E-Mail
Neuer Listener RecordMailActivity am MessageSent-Event erfasst zentral alle Versandwege (Mailables, Notifications, Fortify, Queue-Mails beim realen Versand im Worker). Neuer ActivityType "E-Mail" mit Empfänger, Betreff und Mailable-Klasse in den Metadaten; bekannte Empfänger werden mit ihrem User verknüpft. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
e59e1320a3
commit
33e84afa2a
6 changed files with 165 additions and 74 deletions
|
|
@ -20,6 +20,7 @@ enum ActivityType: string
|
|||
case TerminationRequest = 'termination_request';
|
||||
case NewsletterSubscription = 'newsletter_subscription';
|
||||
case SubscriptionChange = 'subscription_change';
|
||||
case MailSent = 'mail_sent';
|
||||
|
||||
public function label(): string
|
||||
{
|
||||
|
|
@ -35,6 +36,7 @@ enum ActivityType: string
|
|||
self::TerminationRequest => 'Kündigung',
|
||||
self::NewsletterSubscription => 'Newsletter',
|
||||
self::SubscriptionChange => 'Abo',
|
||||
self::MailSent => 'E-Mail',
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -50,6 +52,7 @@ enum ActivityType: string
|
|||
self::BookingPaid, self::CreditTopup => 'amber',
|
||||
self::ContactRequest, self::NewsletterSubscription => 'cyan',
|
||||
self::LegalRequest, self::WithdrawalRequest, self::TerminationRequest, self::SubscriptionChange => 'red',
|
||||
self::MailSent => 'purple',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
57
app/Listeners/RecordMailActivity.php
Normal file
57
app/Listeners/RecordMailActivity.php
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
|
||||
namespace App\Listeners;
|
||||
|
||||
use App\Enums\ActivityType;
|
||||
use App\Models\User;
|
||||
use App\Services\ActivityLog;
|
||||
use Illuminate\Mail\Events\MessageSent;
|
||||
|
||||
/**
|
||||
* Protokolliert jede tatsächlich versendete E-Mail im Aktivitäts-Verlauf.
|
||||
*
|
||||
* Hängt zentral am MessageSent-Event des Mailers und erfasst damit alle
|
||||
* Versandwege (Mailables, Notifications, Fortify). Bei Queue-Mails feuert
|
||||
* das Event erst beim realen Versand im Worker — der Eintrag entsteht also
|
||||
* zum echten Versandzeitpunkt.
|
||||
*
|
||||
* Die Methode heißt bewusst NICHT `handle`: Laravels Event-Discovery würde
|
||||
* sie sonst zusätzlich zur manuellen Verdrahtung im AppServiceProvider
|
||||
* registrieren (doppelte Einträge).
|
||||
*/
|
||||
class RecordMailActivity
|
||||
{
|
||||
public function __construct(private readonly ActivityLog $activityLog) {}
|
||||
|
||||
public function recordSent(MessageSent $event): void
|
||||
{
|
||||
$recipients = array_values(array_map(
|
||||
fn ($address): string => $address->getAddress(),
|
||||
$event->message->getTo() ?? [],
|
||||
));
|
||||
|
||||
if ($recipients === []) {
|
||||
return;
|
||||
}
|
||||
|
||||
$subject = (string) $event->message->getSubject();
|
||||
$user = User::query()->whereIn('email', $recipients)->first();
|
||||
|
||||
$this->activityLog->record(
|
||||
ActivityType::MailSent,
|
||||
sprintf(
|
||||
'E-Mail „%s" an %s versendet.',
|
||||
$subject !== '' ? $subject : __('(ohne Betreff)'),
|
||||
implode(', ', $recipients),
|
||||
),
|
||||
user: $user,
|
||||
actorLabel: $user?->name ?? $recipients[0],
|
||||
meta: array_filter([
|
||||
'to' => $recipients,
|
||||
'subject' => $subject,
|
||||
'mailable' => $event->data['__laravel_mailable'] ?? null,
|
||||
'notification' => $event->data['__laravel_notification'] ?? null,
|
||||
], fn ($value): bool => $value !== null && $value !== ''),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -11,6 +11,7 @@ use App\Http\Middleware\LogSlowAdminRequests;
|
|||
use App\Http\Middleware\SetEdition;
|
||||
use App\Listeners\ActivateUserAfterVerification;
|
||||
use App\Listeners\RecordAuthActivity;
|
||||
use App\Listeners\RecordMailActivity;
|
||||
use App\Listeners\SyncCompanyMembershipsOnLogin;
|
||||
use App\Models\AdminPreset;
|
||||
use App\Models\Category;
|
||||
|
|
@ -38,6 +39,7 @@ use Illuminate\Auth\Notifications\ResetPassword;
|
|||
use Illuminate\Auth\Notifications\VerifyEmail;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Events\QueryExecuted;
|
||||
use Illuminate\Mail\Events\MessageSent;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Queue\Events\JobFailed;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
|
@ -129,6 +131,9 @@ class AppServiceProvider extends ServiceProvider
|
|||
Event::listen(Registered::class, [RecordAuthActivity::class, 'recordRegistered']);
|
||||
Event::listen(Login::class, [RecordAuthActivity::class, 'recordLogin']);
|
||||
|
||||
// Jede tatsächlich versendete E-Mail landet ebenfalls im Verlauf.
|
||||
Event::listen(MessageSent::class, [RecordMailActivity::class, 'recordSent']);
|
||||
|
||||
// Framework-Auth-Mails (Passwort-Reset, E-Mail-Verifizierung) im
|
||||
// pressekonto-CI rendern statt im Laravel-Standard-Markdown-Theme —
|
||||
// gleiches Layout wie alle übrigen System-Mails (emails/layout).
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue