Let a form send from its own address in 1.15.1
Umut asked where a contact form's mail is sent from: it was the recipient address, `From` equal to `To`. That breaks as soon as the recipient is a mailbox at another provider, because most hosts only deliver mail that claims an address of their own domain, and the provider's SPF/DMARC then treats it as forged. Each form now has an optional `sender` setting, validated like the recipient; empty keeps the old behaviour, so stored forms need no migration. Delivery uses `sender ?: recipient`; the reply-to field is untouched. The administration shows the field under the recipient with a note on why it matters. The pilot launch config moves to port 8091 because 8087 was held by another session. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
4d1f51801c
commit
d05dba3042
10 files changed
+70
-7
No files matched your search
@@ -11,6 +11,7 @@ use App\Content\PageRepository;
|
||||
use App\Content\PartialRepository;
|
||||
use App\Content\SiteSettings;
|
||||
use App\Content\Theme;
|
||||
use App\Domain\InvalidForm;
|
||||
use App\Infrastructure\ConnectionFactory;
|
||||
use App\Kernel;
|
||||
use App\Security\UserProvider;
|
||||
@@ -322,7 +323,8 @@ final class EditorSecurityTest extends WebTestCase
|
||||
self::assertSame('Neu', $this->db->fetchOne('SELECT name FROM menu WHERE slot = ?', ['header']));
|
||||
}
|
||||
|
||||
private function contactForm(): FormRepository
|
||||
/** @param array<string, string> $settings overrides for the mail settings */
|
||||
private function contactForm(array $settings = []): FormRepository
|
||||
{
|
||||
$forms = new FormRepository($this->db);
|
||||
$forms->save('kontakt', 'Kontakt', [
|
||||
@@ -331,7 +333,7 @@ final class EditorSecurityTest extends WebTestCase
|
||||
['name' => 'thema', 'type' => 'select', 'label' => 'Thema', 'required' => true, 'options' => ['Beratung', 'Support']],
|
||||
['name' => 'nachricht', 'type' => 'textarea', 'label' => 'Nachricht', 'required' => false],
|
||||
['name' => 'datenschutz', 'type' => 'consent', 'label' => 'Ich willige ein.'],
|
||||
], ['recipient' => 'info@kant-it.de', 'subject' => 'Anfrage', 'replyToField' => 'email', 'success' => 'Danke.'], 0);
|
||||
], ['recipient' => 'info@kant-it.de', 'subject' => 'Anfrage', 'replyToField' => 'email', 'success' => 'Danke.', ...$settings], 0);
|
||||
|
||||
return $forms;
|
||||
}
|
||||
@@ -380,6 +382,12 @@ final class EditorSecurityTest extends WebTestCase
|
||||
// Post/Redirect/Get, so reloading the result page sends nothing twice.
|
||||
self::assertResponseStatusCodeSame(303);
|
||||
self::assertStringContainsString('?gesendet=kontakt#formblock', (string) $client->getResponse()->headers->get('Location'));
|
||||
// Ohne eigene Absenderadresse geht die Post vom Empfaenger an sich selbst.
|
||||
$mail = self::getMailerMessage();
|
||||
self::assertNotNull($mail);
|
||||
self::assertEmailAddressContains($mail, 'From', 'info@kant-it.de');
|
||||
self::assertEmailAddressContains($mail, 'To', 'info@kant-it.de');
|
||||
self::assertEmailAddressContains($mail, 'Reply-To', 'umut@example.com');
|
||||
|
||||
$row = $this->db->fetchAssociative('SELECT * FROM form_submission');
|
||||
self::assertNotFalse($row);
|
||||
@@ -396,6 +404,33 @@ final class EditorSecurityTest extends WebTestCase
|
||||
self::assertStringContainsString('Danke.', $client->getResponse()->getContent());
|
||||
}
|
||||
|
||||
public function testAFormMaySendFromItsOwnAddress(): void
|
||||
{
|
||||
// Umut: die Versandadresse soll sich festlegen lassen - bisher war sie immer der
|
||||
// Empfaenger, und manche Hoster nehmen fremde Absender gar nicht erst an.
|
||||
$forms = $this->contactForm(['sender' => 'formular@kant-it.de']);
|
||||
$this->pageWithForm();
|
||||
$client = self::createClient();
|
||||
|
||||
$client->request('POST', '/formular/kontakt', $this->validBody((string) (time() - 10)));
|
||||
self::assertResponseStatusCodeSame(303);
|
||||
$mail = self::getMailerMessage();
|
||||
self::assertNotNull($mail);
|
||||
self::assertEmailAddressContains($mail, 'From', 'formular@kant-it.de');
|
||||
self::assertEmailAddressContains($mail, 'To', 'info@kant-it.de');
|
||||
self::assertEmailAddressContains($mail, 'Reply-To', 'umut@example.com');
|
||||
|
||||
// Eine kaputte Absenderadresse wird abgewiesen, eine leere bedeutet: wie der Empfaenger.
|
||||
try {
|
||||
$forms->save('kontakt', 'Kontakt', [['name' => 'email', 'type' => 'email', 'label' => 'E-Mail']], ['recipient' => 'info@kant-it.de', 'sender' => 'kein-postfach'], 1);
|
||||
self::fail('Eine ungueltige Absenderadresse darf nicht gespeichert werden.');
|
||||
} catch (InvalidForm $e) {
|
||||
self::assertStringContainsString('Absenderadresse', $e->getMessage());
|
||||
}
|
||||
$forms->save('kontakt', 'Kontakt', [['name' => 'email', 'type' => 'email', 'label' => 'E-Mail']], ['recipient' => 'info@kant-it.de', 'sender' => ' '], 1);
|
||||
self::assertSame('', $forms->findBySlug('kontakt')['settings']['sender']);
|
||||
}
|
||||
|
||||
public function testInvalidSubmissionKeepsEveryEntryAndNamesTheOffendingFields(): void
|
||||
{
|
||||
$this->contactForm();
|
||||
|
||||
Reference in new issue
Block a user