Give mail delivery its own admin page and move the origin probe off /.well-known

The mail page under System tries SMTP, PHP mail() and both sendmail
modes one by one or all at once, and saves the chosen way to .env
without ever showing the password. IONOS answers everything under
/.well-known/ itself with 403, so the address and HTTPS checks never
reached the installation; the probe now lives at /kantsites-origin
(ADR 122).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
kantarciandClaude Opus 5.5 committed 2026-10-12 21:07:27 +02:00
1 parent 2497b8cb69
commit b982cb8944
17 files changed
+597 -148

No files matched your search

+41 -14
View File
@@ -201,7 +201,7 @@ final class SystemScreenTest extends WebTestCase
self::assertStringNotContainsString('kein-server', (string) file_get_contents(dirname(__DIR__).'/.env'));
// Die Gegenstelle der Prüfung: öffentlich, ohne Anmeldung, und nur die Kennung.
$client->request('GET', '/.well-known/kantsites-origin');
$client->request('GET', '/kantsites-origin');
self::assertSame(200, $client->getResponse()->getStatusCode());
self::assertSame(hash_hmac('sha256', 'site-origin', 'isolated-test-secret'), $client->getResponse()->getContent());
}
@@ -360,38 +360,65 @@ final class SystemScreenTest extends WebTestCase
self::assertStringContainsString('Migrationen stehen aus', (string) $admin->getResponse()->getContent(), 'Und es steht immer noch aus.');
}
public function testATestMailGoesToAnyAddressAndTheScreenSaysWhatHappened(): void
public function testTheMailPageTestsAWayAndSaysWhatHappened(): void
{
// Umut: „Bau mal in den Backend einen Knopf ein, Testmail an Mailadresse, wo man einträgt,
// und wo Logs angezeigt werden, woran es liegt“ (ADR 121).
// und wo Logs angezeigt werden, woran es liegt“ (ADR 121) - und dann: alle Wege probieren,
// SMTP dort setzen, auf einer eigenen Seite unter „System“ (ADR 122).
// MAILER_DSN gilt hier als Server-Umgebung: so schreibt kein Test in die echte .env.
$_SERVER['SYMFONY_DOTENV_VARS'] = '';
$client = $this->login();
$client->request('GET', '/admin/system');
$html = (string) $client->getResponse()->getContent();
self::assertStringContainsString('E-Mail-Versand', $html);
self::assertStringContainsString('Noch nichts versendet', $html);
$token = (string) $client->getCrawler()->filter('form[action$="/system/testmail"] input[name=_csrf_token]')->attr('value');
self::assertStringContainsString('href="/admin/system/e-mail"', $html, 'Ein Unterpunkt von System im Menü.');
self::assertStringNotContainsString('Alle Wege testen', $html, 'Die Systemseite trägt den Versand nicht mehr selbst.');
$client->request('POST', '/admin/system/testmail', ['_csrf_token' => $token, 'to' => 'kein-postfach']);
$client->request('GET', '/admin/system/e-mail');
self::assertSame(200, $client->getResponse()->getStatusCode());
$html = (string) $client->getResponse()->getContent();
self::assertStringContainsString('Alle Wege testen', $html);
self::assertStringContainsString('value="cms.test"', $html, 'Der eingestellte SMTP-Server steht im Feld.');
self::assertStringContainsString('Noch nichts versendet', $html);
// Im Test steht MAILER_DSN nicht in .env: testen ja, speichern nein.
self::assertStringNotContainsString('value="speichern"', $html);
$token = (string) $client->getCrawler()->filter('form[action$="/system/e-mail"] input[name=_csrf_token]')->attr('value');
$client->request('POST', '/admin/system/e-mail', ['_csrf_token' => $token, 'aktion' => 'test', 'weg' => 'smtp', 'server' => 'cms.test', 'port' => '587', 'to' => 'kein-postfach']);
$client->followRedirect();
self::assertStringContainsString('keine gültige E-Mail-Adresse', (string) $client->getResponse()->getContent());
$client->request('POST', '/admin/system/testmail', ['_csrf_token' => $token, 'to' => 'umut@cms.test', 'from' => 'formular@cms.test']);
self::assertStringEndsWith('/admin/system#mail', (string) $client->getResponse()->headers->get('Location'));
// Derselbe Weg wie eingestellt nimmt den Transport des Frameworks - im Test null://null.
$client->request('POST', '/admin/system/e-mail', ['_csrf_token' => $token, 'aktion' => 'test', 'weg' => 'smtp', 'server' => 'cms.test', 'port' => '587', 'to' => 'umut@cms.test', 'from' => 'formular@cms.test']);
self::assertStringEndsWith('/admin/system/e-mail', (string) $client->getResponse()->headers->get('Location'));
self::assertEmailCount(1);
$mail = self::getMailerMessage();
self::assertEmailAddressContains($mail, 'To', 'umut@cms.test');
self::assertEmailAddressContains($mail, 'From', 'formular@cms.test');
$client->request('GET', '/admin/system');
$client->request('GET', '/admin/system/e-mail');
$html = (string) $client->getResponse()->getContent();
self::assertStringContainsString('Testmail an umut@cms.test vom Mailserver angenommen.', $html);
self::assertStringContainsString('Testmail an <code>umut@cms.test</code>', $html, 'Der Versuch steht danach in „Letzte Versuche“.');
self::assertStringContainsString('Testmail an umut@cms.test vom Mailserver angenommen', $html);
self::assertStringContainsString('Testmail an <code>umut@cms.test</code>', $html, 'Der Versuch steht danach unter „Letzte Versuche“.');
self::assertStringContainsString('value="umut@cms.test"', $html, 'Die Eingabe bleibt stehen.');
// SMTP mit Benutzer, aber ohne Passwort und ohne gespeichertes: abgelehnt, bevor etwas rausgeht.
$client->request('POST', '/admin/system/e-mail', ['_csrf_token' => $token, 'aktion' => 'test', 'weg' => 'smtp', 'server' => 'smtp.anderer.test', 'port' => '587', 'benutzer' => 'x@anderer.test', 'to' => 'umut@cms.test']);
self::assertEmailCount(0);
$client->followRedirect();
self::assertStringContainsString('das Passwort des Postfachs eintragen', (string) $client->getResponse()->getContent());
// Speichern geht nur, wenn die Einstellung in .env steht.
$client->request('POST', '/admin/system/e-mail', ['_csrf_token' => $token, 'aktion' => 'speichern', 'weg' => 'native']);
$client->followRedirect();
self::assertStringContainsString('in der Server-Umgebung gesetzt', (string) $client->getResponse()->getContent());
// Nur für Administratoren, und nur mit Token.
$client->request('POST', '/admin/system/testmail', ['_csrf_token' => 'erfunden', 'to' => 'umut@cms.test']);
$client->request('POST', '/admin/system/e-mail', ['_csrf_token' => 'erfunden', 'aktion' => 'test', 'weg' => 'smtp', 'server' => 'cms.test', 'to' => 'umut@cms.test']);
self::assertEmailCount(0);
$redaktion = $this->login('editor');
$redaktion->request('POST', '/admin/system/testmail', ['_csrf_token' => $token, 'to' => 'umut@cms.test']);
$redaktion->request('GET', '/admin/system/e-mail');
self::assertSame(403, $redaktion->getResponse()->getStatusCode());
$redaktion->request('POST', '/admin/system/e-mail', ['_csrf_token' => $token, 'aktion' => 'test', 'weg' => 'smtp', 'server' => 'cms.test', 'to' => 'umut@cms.test']);
self::assertSame(403, $redaktion->getResponse()->getStatusCode());
}