From 849211a780b95ad05284d9cf11906d3dfba47b17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Deruss=C3=A9?= Date: Mon, 21 Dec 2020 18:33:12 +0100 Subject: [PATCH 1/3] Handle failure when sending DATA --- .../Transport/Smtp/SmtpTransportTest.php | 31 +++++++++++++++++++ .../Mailer/Transport/Smtp/SmtpTransport.php | 17 +++++++--- 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Mailer/Tests/Transport/Smtp/SmtpTransportTest.php b/src/Symfony/Component/Mailer/Tests/Transport/Smtp/SmtpTransportTest.php index 38229ce844..91b1685077 100644 --- a/src/Symfony/Component/Mailer/Tests/Transport/Smtp/SmtpTransportTest.php +++ b/src/Symfony/Component/Mailer/Tests/Transport/Smtp/SmtpTransportTest.php @@ -18,6 +18,8 @@ use Symfony\Component\Mailer\Transport\Smtp\SmtpTransport; use Symfony\Component\Mailer\Transport\Smtp\Stream\AbstractStream; use Symfony\Component\Mailer\Transport\Smtp\Stream\SocketStream; use Symfony\Component\Mime\Address; +use Symfony\Component\Mime\Email; +use Symfony\Component\Mime\Exception\InvalidArgumentException; use Symfony\Component\Mime\RawMessage; class SmtpTransportTest extends TestCase @@ -86,6 +88,29 @@ class SmtpTransportTest extends TestCase $transport->send(new RawMessage('Message 3'), $envelope); $this->assertContains("NOOP\r\n", $stream->getCommands()); } + + public function testSendInvalidMessage() + { + $stream = new DummyStream(); + + $transport = new SmtpTransport($stream); + $transport->setPingThreshold(1); + + $message = new Email(); + $message->to('recipient@example.org'); + $message->from('sender@example.org'); + $message->attachFromPath('/does_not_exists'); + + try { + $transport->send($message); + $this->fail('Expected Symfony\Component\Mime\Exception\InvalidArgumentException to be thrown'); + } catch (InvalidArgumentException $e) { + $this->assertMatchesRegularExpression('{Path "/does_not_exists"}i', $e->getMessage()); + } + + $this->assertNotContains("\r\n.\r\n", $stream->getCommands()); + $this->assertTrue($stream->isClosed()); + } } class DummyStream extends AbstractStream @@ -164,4 +189,10 @@ class DummyStream extends AbstractStream { return $this->closed; } + + public function terminate(): void + { + parent::terminate(); + $this->closed = true; + } } diff --git a/src/Symfony/Component/Mailer/Transport/Smtp/SmtpTransport.php b/src/Symfony/Component/Mailer/Transport/Smtp/SmtpTransport.php index 5ef8a88255..9e5ead35a3 100644 --- a/src/Symfony/Component/Mailer/Transport/Smtp/SmtpTransport.php +++ b/src/Symfony/Component/Mailer/Transport/Smtp/SmtpTransport.php @@ -159,7 +159,7 @@ class SmtpTransport extends AbstractTransport return $name; } - return sprintf('smtp://sendmail'); + return 'smtp://sendmail'; } /** @@ -200,10 +200,19 @@ class SmtpTransport extends AbstractTransport } $this->executeCommand("DATA\r\n", [354]); - foreach (AbstractStream::replace("\r\n.", "\r\n..", $message->toIterable()) as $chunk) { - $this->stream->write($chunk, false); + try { + foreach (AbstractStream::replace("\r\n.", "\r\n..", $message->toIterable()) as $chunk) { + $this->stream->write($chunk, false); + } + $this->stream->flush(); + } catch (TransportExceptionInterface $e) { + throw $e; + } catch (\Exception $e) { + $this->stream->terminate(); + $this->started = false; + $this->getLogger()->debug(sprintf('Email transport "%s" stopped', __CLASS__)); + throw $e; } - $this->stream->flush(); $this->executeCommand("\r\n.\r\n", [250]); $message->appendDebug($this->stream->getDebug()); $this->lastMessageTime = microtime(true); From 87dc6940946e6bed774912de54ff8a9beab92b62 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sat, 26 Dec 2020 12:22:20 +0100 Subject: [PATCH 2/3] [VarDumper] fixed displaying "mixed" as "?mixed" --- src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php b/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php index e0181ba0ee..6b6d8943b6 100644 --- a/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php @@ -183,7 +183,7 @@ class ReflectionCaster if (isset($a[$prefix.'returnType'])) { $v = $a[$prefix.'returnType']; $v = $v instanceof \ReflectionNamedType ? $v->getName() : (string) $v; - $a[$prefix.'returnType'] = new ClassStub($a[$prefix.'returnType']->allowsNull() ? '?'.$v : $v, [class_exists($v, false) || interface_exists($v, false) || trait_exists($v, false) ? $v : '', '']); + $a[$prefix.'returnType'] = new ClassStub($a[$prefix.'returnType']->allowsNull() && 'mixed' !== $v ? '?'.$v : $v, [class_exists($v, false) || interface_exists($v, false) || trait_exists($v, false) ? $v : '', '']); } if (isset($a[$prefix.'class'])) { $a[$prefix.'class'] = new ClassStub($a[$prefix.'class']); @@ -323,7 +323,7 @@ class ReflectionCaster if (!$type instanceof \ReflectionNamedType) { $signature .= $type.' '; } else { - if (!$param->isOptional() && $param->allowsNull()) { + if (!$param->isOptional() && $param->allowsNull() && 'mixed' !== $type->getName()) { $signature .= '?'; } $signature .= substr(strrchr('\\'.$type->getName(), '\\'), 1).' '; From efeb2dcf70754ef07fda543d312fa47505bf01ed Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Sat, 26 Dec 2020 14:58:16 +0100 Subject: [PATCH 3/3] [VarDumper] Fix display of nullable union return types. --- .../VarDumper/Caster/ReflectionCaster.php | 2 +- .../Tests/Caster/ReflectionCasterTest.php | 128 ++++++++++++++++++ 2 files changed, 129 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php b/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php index 6b6d8943b6..4634335fe6 100644 --- a/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php @@ -183,7 +183,7 @@ class ReflectionCaster if (isset($a[$prefix.'returnType'])) { $v = $a[$prefix.'returnType']; $v = $v instanceof \ReflectionNamedType ? $v->getName() : (string) $v; - $a[$prefix.'returnType'] = new ClassStub($a[$prefix.'returnType']->allowsNull() && 'mixed' !== $v ? '?'.$v : $v, [class_exists($v, false) || interface_exists($v, false) || trait_exists($v, false) ? $v : '', '']); + $a[$prefix.'returnType'] = new ClassStub($a[$prefix.'returnType'] instanceof \ReflectionNamedType && $a[$prefix.'returnType']->allowsNull() && 'mixed' !== $v ? '?'.$v : $v, [class_exists($v, false) || interface_exists($v, false) || trait_exists($v, false) ? $v : '', '']); } if (isset($a[$prefix.'class'])) { $a[$prefix.'class'] = new ClassStub($a[$prefix.'class']); diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php index a4183e21af..e1214765ef 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php @@ -149,6 +149,68 @@ EOTXT ); } + /** + * @requires PHP 8 + */ + public function testReflectionParameterMixed() + { + $f = eval('return function (mixed $a) {};'); + $var = new \ReflectionParameter($f, 0); + + $this->assertDumpMatchesFormat( + <<<'EOTXT' +ReflectionParameter { + +name: "a" + position: 0 + allowsNull: true + typeHint: "mixed" +} +EOTXT + , $var + ); + } + + /** + * @requires PHP 8 + */ + public function testReflectionParameterUnion() + { + $f = eval('return function (int|float $a) {};'); + $var = new \ReflectionParameter($f, 0); + + $this->assertDumpMatchesFormat( + <<<'EOTXT' +ReflectionParameter { + +name: "a" + position: 0 + typeHint: "int|float" +} +EOTXT + , $var + ); + } + + /** + * @requires PHP 8 + */ + public function testReflectionParameterNullableUnion() + { + $f = eval('return function (int|float|null $a) {};'); + $var = new \ReflectionParameter($f, 0); + + $this->assertDumpMatchesFormat( + <<<'EOTXT' +ReflectionParameter { + +name: "a" + position: 0 + allowsNull: true + typeHint: "int|float|null" +} +EOTXT + , $var + ); + } + public function testReturnType() { $f = eval('return function ():int {};'); @@ -168,6 +230,72 @@ EOTXT ); } + /** + * @requires PHP 8 + */ + public function testMixedReturnType() + { + $f = eval('return function (): mixed {};'); + $line = __LINE__ - 1; + + $this->assertDumpMatchesFormat( + <<assertDumpMatchesFormat( + <<assertDumpMatchesFormat( + <<