Description
Symfony version(s) affected
5.4
Description
If stream timeouts on some network that is blocking the connection, PHP function fgets(resource $stream, ?int $length = null): string|false returns false
instead of empty string ''
so the 'timed_out'
metadata check will not be executed and you will end up with the error Expected response code "220" but got empty code.
.
AbstractStream.php#L77
$line = fgets($this->out);
if ('' === $line) {
$metas = stream_get_meta_data($this->out);
if ($metas['timed_out']) {
throw new TransportException(sprintf('Connection to "%s" timed out.', $this->getReadConnectionDescription()));
}
if ($metas['eof']) {
throw new TransportException(sprintf('Connection to "%s" has been closed unexpectedly.', $this->getReadConnectionDescription()));
}
}
How to reproduce
In my case, there is a blocked port 587 so when I try to connect to any XOauth2 SMTP servers it will wait for the amount of time set by the timeout setting and then throw Expected response code "220" but got empty code.
instead of Connection to "SMTP" timed out.
.
Since the PHP documentation clearly states that fgets
can return false
I don't see the point in trying to reproduce it, stream metadata should be checked even if $line = false
.
Possible Solution
stream metadata should be checked even if $line = false
.
$line = fgets($this->out);
if ('' === $line || false === $line) {
$metas = stream_get_meta_data($this->out);
if ($metas['timed_out']) {
throw new TransportException(sprintf('Connection to "%s" timed out.', $this->getReadConnectionDescription()));
}
if ($metas['eof']) {
throw new TransportException(sprintf('Connection to "%s" has been closed unexpectedly.', $this->getReadConnectionDescription()));
}
}
Additional Context
EXCEPTION
Class: Symfony\Component\Mailer\Exception\TransportException
Message: Expected response code "220" but got empty code.
Code: 0
Stack trace:
- 0 ...\vendor\symfony\mailer\Transport\Smtp\SmtpTransport.php(252): Symfony\Component\Mailer\Transport\Smtp\SmtpTransport->assertResponseCode('', Array)
- 1 ...\vendor\symfony\mailer\Transport\Smtp\SmtpTransport.php(194): Symfony\Component\Mailer\Transport\Smtp\SmtpTransport->start()
- 2 ...\vendor\symfony\mailer\Transport\AbstractTransport.php(71): Symfony\Component\Mailer\Transport\Smtp\SmtpTransport->doSend(Object(Symfony\Component\Mailer\SentMessage))