diff --git a/framework/core/src/Mail/MailgunDriver.php b/framework/core/src/Mail/MailgunDriver.php index 1d28a05bee..9b33f90de4 100644 --- a/framework/core/src/Mail/MailgunDriver.php +++ b/framework/core/src/Mail/MailgunDriver.php @@ -18,6 +18,8 @@ class MailgunDriver implements DriverInterface { + use ValidatesMailSettings; + public function availableSettings(): array { return [ @@ -33,7 +35,7 @@ public function availableSettings(): array public function validate(SettingsRepositoryInterface $settings, Factory $validator): MessageBag { return $validator->make($settings->all(), [ - 'mail_mailgun_secret' => 'required', + 'mail_mailgun_secret' => ['required', $this->noWhitespace()], 'mail_mailgun_domain' => 'required|regex:/^(?!\-)(?:[a-zA-Z\d\-]{0,62}[a-zA-Z\d]\.){1,126}(?!\d+)[a-zA-Z\d]{1,63}$/', 'mail_mailgun_region' => 'required|in:api.mailgun.net,api.eu.mailgun.net', ])->errors(); diff --git a/framework/core/src/Mail/SmtpDriver.php b/framework/core/src/Mail/SmtpDriver.php index 5cca7addef..d23fb6637b 100644 --- a/framework/core/src/Mail/SmtpDriver.php +++ b/framework/core/src/Mail/SmtpDriver.php @@ -17,6 +17,8 @@ class SmtpDriver implements DriverInterface { + use ValidatesMailSettings; + public function availableSettings(): array { return [ @@ -31,11 +33,11 @@ public function availableSettings(): array public function validate(SettingsRepositoryInterface $settings, Factory $validator): MessageBag { return $validator->make($settings->all(), [ - 'mail_host' => 'required', - 'mail_port' => 'nullable|integer', + 'mail_host' => ['required', $this->noWhitespace()], + 'mail_port' => ['nullable', 'integer', $this->noWhitespace()], 'mail_encryption' => 'nullable|in:tls,ssl,TLS,SSL', - 'mail_username' => 'nullable|string', - 'mail_password' => 'nullable|string', + 'mail_username' => ['nullable', 'string', $this->noWhitespace()], + 'mail_password' => ['nullable', 'string', $this->noWhitespace()], ])->errors(); } diff --git a/framework/core/src/Mail/ValidatesMailSettings.php b/framework/core/src/Mail/ValidatesMailSettings.php new file mode 100644 index 0000000000..c49b9fb26c --- /dev/null +++ b/framework/core/src/Mail/ValidatesMailSettings.php @@ -0,0 +1,27 @@ +prepareDatabase([ + 'users' => [ + $this->normalUser(), + ], + ]); + } + + /** + * @test + */ + public function smtpDriverWithWhitespaceIsInvalidated() + { + $this->setting('mail_driver', 'smtp'); + $this->setting('mail_host', ' world'); + $this->setting('mail_port', ' 587 '); + $this->setting('mail_encryption', 'tls'); + $this->setting('mail_username', 'user '); + $this->setting('mail_password', ' password'); + + $mailSettingsResponse = $this->send( + $this->request('GET', '/api/mail/settings', [ + 'authenticatedAs' => 1, + ]) + ); + + $this->assertEquals(200, $mailSettingsResponse->getStatusCode()); + + $data = json_decode((string) $mailSettingsResponse->getBody(), true); + + $this->assertFalse($data['data']['attributes']['sending']); + + $this->assertArrayHasKey('errors', $data['data']['attributes']); + + $this->assertArrayHasKey('mail_host', $data['data']['attributes']['errors']); + $this->assertEquals('The mail host must not contain leading or trailing whitespace.', $data['data']['attributes']['errors']['mail_host'][0]); + + $this->assertArrayHasKey('mail_port', $data['data']['attributes']['errors']); + $this->assertEquals('The mail port must not contain leading or trailing whitespace.', $data['data']['attributes']['errors']['mail_port'][0]); + + $this->assertArrayHasKey('mail_username', $data['data']['attributes']['errors']); + $this->assertEquals('The mail username must not contain leading or trailing whitespace.', $data['data']['attributes']['errors']['mail_username'][0]); + + $this->assertArrayHasKey('mail_password', $data['data']['attributes']['errors']); + $this->assertEquals('The mail password must not contain leading or trailing whitespace.', $data['data']['attributes']['errors']['mail_password'][0]); + } + + /** + * @test + */ + public function smtpDriverWithValidSettingsIsNotInvalidated() + { + $this->setting('mail_driver', 'smtp'); + $this->setting('mail_host', 'mail.example.com'); + $this->setting('mail_port', '587'); + $this->setting('mail_encryption', 'tls'); + $this->setting('mail_username', 'user'); + $this->setting('mail_password', 'password'); + + $mailSettingsResponse = $this->send( + $this->request('GET', '/api/mail/settings', [ + 'authenticatedAs' => 1, + ]) + ); + + $this->assertEquals(200, $mailSettingsResponse->getStatusCode()); + + $data = json_decode((string) $mailSettingsResponse->getBody(), true); + + $this->assertEmpty($data['data']['attributes']['errors']); + $this->assertTrue($data['data']['attributes']['sending']); + } + + /** + * @test + */ + public function mailgunDriverWithWhitespaceIsInvalidated() + { + $this->setting('mail_driver', 'mailgun'); + $this->setting('mail_mailgun_secret', 'key '); + $this->setting('mail_mailgun_domain', ' example.com'); + $this->setting('mail_mailgun_region', 'api.mailgun.net'); + + $mailSettingsResponse = $this->send( + $this->request('GET', '/api/mail/settings', [ + 'authenticatedAs' => 1, + ]) + ); + + $this->assertEquals(200, $mailSettingsResponse->getStatusCode()); + + $data = json_decode((string) $mailSettingsResponse->getBody(), true); + + $this->assertFalse($data['data']['attributes']['sending']); + + $this->assertArrayHasKey('errors', $data['data']['attributes']); + + $this->assertArrayHasKey('mail_mailgun_secret', $data['data']['attributes']['errors']); + $this->assertEquals('The mail mailgun secret must not contain leading or trailing whitespace.', $data['data']['attributes']['errors']['mail_mailgun_secret'][0]); + + $this->assertArrayHasKey('mail_mailgun_domain', $data['data']['attributes']['errors']); + $this->assertEquals('The mail mailgun domain format is invalid.', $data['data']['attributes']['errors']['mail_mailgun_domain'][0]); + } + + /** + * @test + */ + public function mailgunDriverWithValidSettingsIsNotInvalidated() + { + $this->setting('mail_driver', 'mailgun'); + $this->setting('mail_mailgun_secret', 'key'); + $this->setting('mail_mailgun_domain', 'example.com'); + $this->setting('mail_mailgun_region', 'api.mailgun.net'); + + $mailSettingsResponse = $this->send( + $this->request('GET', '/api/mail/settings', [ + 'authenticatedAs' => 1, + ]) + ); + + $this->assertEquals(200, $mailSettingsResponse->getStatusCode()); + + $data = json_decode((string) $mailSettingsResponse->getBody(), true); + + $this->assertEmpty($data['data']['attributes']['errors']); + $this->assertTrue($data['data']['attributes']['sending']); + } +}