From 5dcfee9957ac6facb7229d38e3fce5aa7ed99ee4 Mon Sep 17 00:00:00 2001 From: nexxo Date: Mon, 3 Aug 2026 12:43:31 +0200 Subject: [PATCH] Wegwahl je Mailart: welche Mail aus welchem Postfach geht MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MailCatalogue haelt die eine Liste aller sechzehn Mailarten (Schluessel, Beschriftung, Vorgabe-Zweck), aus MailPreviews herausgezogen, damit es nur noch eine Stelle gibt, die beim naechsten Mailtyp vergessen werden kann. MailRoute sitzt darueber: ein Eintrag ist eine Ausnahme fuer GENAU diese eine Mailart, keine zweite Zuordnungsebene — ohne Eintrag oder bei abgeschaltetem Zielpostfach faellt sie unveraendert auf den Zweck zurueck, den MailboxResolver schon kennt. SendsFromMailbox bekommt dafuer einen optionalen $mailKey; alle bestehenden Aufrufer (inklusive ContactRequestMail, das mailboxAddresses selbst zusammensetzt) bleiben bei null und damit beim alten Verhalten. Jede Mailklasse und die CloudReady-Benachrichtigung nennen jetzt ihren Katalog-Schluessel. Die Konsole bekommt eine vierte Karte unter der Zweck-Zuordnung: eine Zeile je Mailart, ein pro Zeile, R20's + stated exception, genau wie die Zuordnung darüber. --}} + +

{{ __('mail_settings.routes_title') }}

+

{{ __('mail_settings.routes_hint') }}

+ +
+ @foreach ($mailCatalogue as $key => $entry) +
+ {{ $entry['label'] }} + +
+ @endforeach +
+ + + {{ __('mail_settings.save') }} + +
diff --git a/tests/Feature/Admin/MailRoutingTest.php b/tests/Feature/Admin/MailRoutingTest.php new file mode 100644 index 0000000..5007c3a --- /dev/null +++ b/tests/Feature/Admin/MailRoutingTest.php @@ -0,0 +1,69 @@ + clearMailboxSeed()); + +it('schickt ohne Eintrag genau dorthin, wo die Mail vorher hinging', function () { + // Der wichtigste Test dieser Aufgabe: der Umbau darf am heutigen Verhalten + // NICHTS ändern, solange niemand etwas einstellt. Sonst wandern beim + // Ausrollen still die Rechnungen in ein anderes Postfach. + $system = Mailbox::factory()->create(['key' => 'no-reply', 'active' => true]); + Settings::set(MailPurpose::settingKey(MailPurpose::SYSTEM), 'no-reply'); + + expect(MailRoute::purposeOrMailbox('new-device', MailPurpose::SYSTEM)?->id) + ->toBe($system->id); +}); + +it('legt eine einzelne Mailart auf ein anderes Postfach', function () { + Mailbox::factory()->create(['key' => 'no-reply', 'active' => true]); + $info = Mailbox::factory()->create(['key' => 'info', 'active' => true]); + Settings::set(MailPurpose::settingKey(MailPurpose::SYSTEM), 'no-reply'); + Settings::set(MailRoute::settingKey('new-device'), 'info'); + + // Und nur diese eine: der Nachbar bleibt, wo er war. Mit einem EIGENEN + // Postfach fuer Abrechnung — ohne das waere die Zusicherung leer, weil der + // Resolver dann null liefert und null nun einmal nicht 'info' ist. + $billing = Mailbox::factory()->create(['key' => 'billing', 'active' => true]); + Settings::set(MailPurpose::settingKey(MailPurpose::BILLING), 'billing'); + + expect(MailRoute::purposeOrMailbox('new-device', MailPurpose::SYSTEM)?->id)->toBe($info->id) + ->and(MailRoute::purposeOrMailbox('invoice', MailPurpose::BILLING)?->id)->toBe($billing->id); +}); + +it('faellt auf den Zweck zurueck, wenn das eingetragene Postfach abgeschaltet ist', function () { + // Eine Mail, die nicht rausgeht, ist schlimmer als eine aus der zweitbesten + // Adresse. + Mailbox::factory()->create(['key' => 'no-reply', 'active' => true]); + Mailbox::factory()->create(['key' => 'info', 'active' => false]); + Settings::set(MailPurpose::settingKey(MailPurpose::SYSTEM), 'no-reply'); + Settings::set(MailRoute::settingKey('new-device'), 'info'); + + expect(MailRoute::purposeOrMailbox('new-device', MailPurpose::SYSTEM)?->key)->toBe('no-reply'); +}); + +it('kennt zu jeder Mailart einen Vorgabe-Zweck', function () { + // Ohne Vorgabe stünde eine Mailart ohne Postfach da, sobald jemand die + // Wegwahl leert. + foreach (MailCatalogue::all() as $key => $eintrag) { + expect($eintrag['purpose'])->toBeIn(MailPurpose::ALL, "[{$key}] hat keinen gueltigen Vorgabe-Zweck."); + expect($eintrag['label'])->not->toBe(''); + } +}); + +it('fuehrt die Liste der Mailarten nur an EINER Stelle', function () { + // Zwei Listen bedeuten, dass die zweite beim siebzehnten Mail vergessen + // wird. Die Vorschau muss aus dem Katalog lesen. + expect(array_keys(app(\App\Services\Mail\MailPreviews::class)->all())) + ->toEqualCanonicalizing(array_keys(MailCatalogue::all())); +});