🔧
This commit is contained in:
@@ -28,7 +28,7 @@ abstract class AbstractHttpTransport extends AbstractTransport
|
||||
protected $port;
|
||||
protected $client;
|
||||
|
||||
public function __construct(HttpClientInterface $client = null, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null)
|
||||
public function __construct(?HttpClientInterface $client = null, ?EventDispatcherInterface $dispatcher = null, ?LoggerInterface $logger = null)
|
||||
{
|
||||
$this->client = $client;
|
||||
if (null === $client) {
|
||||
|
||||
@@ -35,7 +35,7 @@ abstract class AbstractTransport implements TransportInterface
|
||||
private float $rate = 0;
|
||||
private float $lastSent = 0;
|
||||
|
||||
public function __construct(EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null)
|
||||
public function __construct(?EventDispatcherInterface $dispatcher = null, ?LoggerInterface $logger = null)
|
||||
{
|
||||
$this->dispatcher = $dispatcher;
|
||||
$this->logger = $logger ?? new NullLogger();
|
||||
@@ -58,7 +58,7 @@ abstract class AbstractTransport implements TransportInterface
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function send(RawMessage $message, Envelope $envelope = null): ?SentMessage
|
||||
public function send(RawMessage $message, ?Envelope $envelope = null): ?SentMessage
|
||||
{
|
||||
$message = clone $message;
|
||||
$envelope = null !== $envelope ? clone $envelope : Envelope::create($message);
|
||||
|
||||
@@ -25,7 +25,7 @@ abstract class AbstractTransportFactory implements TransportFactoryInterface
|
||||
protected $client;
|
||||
protected $logger;
|
||||
|
||||
public function __construct(EventDispatcherInterface $dispatcher = null, HttpClientInterface $client = null, LoggerInterface $logger = null)
|
||||
public function __construct(?EventDispatcherInterface $dispatcher = null, ?HttpClientInterface $client = null, ?LoggerInterface $logger = null)
|
||||
{
|
||||
$this->dispatcher = $dispatcher;
|
||||
$this->client = $client;
|
||||
|
||||
20
vendor/symfony/mailer/Transport/Dsn.php
vendored
20
vendor/symfony/mailer/Transport/Dsn.php
vendored
@@ -25,7 +25,7 @@ final class Dsn
|
||||
private ?int $port;
|
||||
private array $options;
|
||||
|
||||
public function __construct(string $scheme, string $host, string $user = null, #[\SensitiveParameter] string $password = null, int $port = null, array $options = [])
|
||||
public function __construct(string $scheme, string $host, ?string $user = null, #[\SensitiveParameter] ?string $password = null, ?int $port = null, array $options = [])
|
||||
{
|
||||
$this->scheme = $scheme;
|
||||
$this->host = $host;
|
||||
@@ -37,24 +37,24 @@ final class Dsn
|
||||
|
||||
public static function fromString(#[\SensitiveParameter] string $dsn): self
|
||||
{
|
||||
if (false === $parsedDsn = parse_url($dsn)) {
|
||||
if (false === $params = parse_url($dsn)) {
|
||||
throw new InvalidArgumentException('The mailer DSN is invalid.');
|
||||
}
|
||||
|
||||
if (!isset($parsedDsn['scheme'])) {
|
||||
if (!isset($params['scheme'])) {
|
||||
throw new InvalidArgumentException('The mailer DSN must contain a scheme.');
|
||||
}
|
||||
|
||||
if (!isset($parsedDsn['host'])) {
|
||||
if (!isset($params['host'])) {
|
||||
throw new InvalidArgumentException('The mailer DSN must contain a host (use "default" by default).');
|
||||
}
|
||||
|
||||
$user = '' !== ($parsedDsn['user'] ?? '') ? urldecode($parsedDsn['user']) : null;
|
||||
$password = '' !== ($parsedDsn['pass'] ?? '') ? urldecode($parsedDsn['pass']) : null;
|
||||
$port = $parsedDsn['port'] ?? null;
|
||||
parse_str($parsedDsn['query'] ?? '', $query);
|
||||
$user = '' !== ($params['user'] ?? '') ? rawurldecode($params['user']) : null;
|
||||
$password = '' !== ($params['pass'] ?? '') ? rawurldecode($params['pass']) : null;
|
||||
$port = $params['port'] ?? null;
|
||||
parse_str($params['query'] ?? '', $query);
|
||||
|
||||
return new self($parsedDsn['scheme'], $parsedDsn['host'], $user, $password, $port, $query);
|
||||
return new self($params['scheme'], $params['host'], $user, $password, $port, $query);
|
||||
}
|
||||
|
||||
public function getScheme(): string
|
||||
@@ -77,7 +77,7 @@ final class Dsn
|
||||
return $this->password;
|
||||
}
|
||||
|
||||
public function getPort(int $default = null): ?int
|
||||
public function getPort(?int $default = null): ?int
|
||||
{
|
||||
return $this->port ?? $default;
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ class RoundRobinTransport implements TransportInterface
|
||||
$this->retryPeriod = $retryPeriod;
|
||||
}
|
||||
|
||||
public function send(RawMessage $message, Envelope $envelope = null): ?SentMessage
|
||||
public function send(RawMessage $message, ?Envelope $envelope = null): ?SentMessage
|
||||
{
|
||||
$exception = null;
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ class SendmailTransport extends AbstractTransport
|
||||
*
|
||||
* -f<sender> flag will be appended automatically if one is not present.
|
||||
*/
|
||||
public function __construct(string $command = null, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null)
|
||||
public function __construct(?string $command = null, ?EventDispatcherInterface $dispatcher = null, ?LoggerInterface $logger = null)
|
||||
{
|
||||
parent::__construct($dispatcher, $logger);
|
||||
|
||||
@@ -64,11 +64,12 @@ class SendmailTransport extends AbstractTransport
|
||||
$this->stream = new ProcessStream();
|
||||
if (str_contains($this->command, ' -bs')) {
|
||||
$this->stream->setCommand($this->command);
|
||||
$this->stream->setInteractive(true);
|
||||
$this->transport = new SmtpTransport($this->stream, $dispatcher, $logger);
|
||||
}
|
||||
}
|
||||
|
||||
public function send(RawMessage $message, Envelope $envelope = null): ?SentMessage
|
||||
public function send(RawMessage $message, ?Envelope $envelope = null): ?SentMessage
|
||||
{
|
||||
if ($this->transport) {
|
||||
return $this->transport->send($message, $envelope);
|
||||
@@ -113,7 +114,7 @@ class SendmailTransport extends AbstractTransport
|
||||
$this->stream->setCommand($command);
|
||||
$this->stream->initialize();
|
||||
foreach ($chunks as $chunk) {
|
||||
$this->stream->write($chunk);
|
||||
$this->stream->write($chunk, false);
|
||||
}
|
||||
$this->stream->flush();
|
||||
$this->stream->terminate();
|
||||
|
||||
@@ -15,6 +15,7 @@ use Psr\EventDispatcher\EventDispatcherInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Mailer\Exception\TransportException;
|
||||
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
|
||||
use Symfony\Component\Mailer\Exception\UnexpectedResponseException;
|
||||
use Symfony\Component\Mailer\Transport\Smtp\Auth\AuthenticatorInterface;
|
||||
use Symfony\Component\Mailer\Transport\Smtp\Stream\AbstractStream;
|
||||
use Symfony\Component\Mailer\Transport\Smtp\Stream\SocketStream;
|
||||
@@ -32,7 +33,7 @@ class EsmtpTransport extends SmtpTransport
|
||||
private string $password = '';
|
||||
private array $capabilities;
|
||||
|
||||
public function __construct(string $host = 'localhost', int $port = 0, bool $tls = null, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null, AbstractStream $stream = null, array $authenticators = null)
|
||||
public function __construct(string $host = 'localhost', int $port = 0, ?bool $tls = null, ?EventDispatcherInterface $dispatcher = null, ?LoggerInterface $logger = null, ?AbstractStream $stream = null, ?array $authenticators = null)
|
||||
{
|
||||
parent::__construct($stream, $dispatcher, $logger);
|
||||
|
||||
@@ -199,7 +200,7 @@ class EsmtpTransport extends SmtpTransport
|
||||
$authenticator->authenticate($this);
|
||||
|
||||
return;
|
||||
} catch (TransportExceptionInterface $e) {
|
||||
} catch (UnexpectedResponseException $e) {
|
||||
$code = $e->getCode();
|
||||
|
||||
try {
|
||||
|
||||
@@ -17,6 +17,7 @@ use Symfony\Component\Mailer\Envelope;
|
||||
use Symfony\Component\Mailer\Exception\LogicException;
|
||||
use Symfony\Component\Mailer\Exception\TransportException;
|
||||
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
|
||||
use Symfony\Component\Mailer\Exception\UnexpectedResponseException;
|
||||
use Symfony\Component\Mailer\SentMessage;
|
||||
use Symfony\Component\Mailer\Transport\AbstractTransport;
|
||||
use Symfony\Component\Mailer\Transport\Smtp\Stream\AbstractStream;
|
||||
@@ -38,10 +39,9 @@ class SmtpTransport extends AbstractTransport
|
||||
private int $pingThreshold = 100;
|
||||
private float $lastMessageTime = 0;
|
||||
private AbstractStream $stream;
|
||||
private string $mtaResult = '';
|
||||
private string $domain = '[127.0.0.1]';
|
||||
|
||||
public function __construct(AbstractStream $stream = null, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null)
|
||||
public function __construct(?AbstractStream $stream = null, ?EventDispatcherInterface $dispatcher = null, ?LoggerInterface $logger = null)
|
||||
{
|
||||
parent::__construct($dispatcher, $logger);
|
||||
|
||||
@@ -131,7 +131,7 @@ class SmtpTransport extends AbstractTransport
|
||||
return $this->domain;
|
||||
}
|
||||
|
||||
public function send(RawMessage $message, Envelope $envelope = null): ?SentMessage
|
||||
public function send(RawMessage $message, ?Envelope $envelope = null): ?SentMessage
|
||||
{
|
||||
try {
|
||||
$message = parent::send($message, $envelope);
|
||||
@@ -147,10 +147,6 @@ class SmtpTransport extends AbstractTransport
|
||||
throw $e;
|
||||
}
|
||||
|
||||
if ($this->mtaResult && $messageId = $this->parseMessageId($this->mtaResult)) {
|
||||
$message->setMessageId($messageId);
|
||||
}
|
||||
|
||||
$this->checkRestartThreshold();
|
||||
|
||||
return $message;
|
||||
@@ -209,11 +205,11 @@ class SmtpTransport extends AbstractTransport
|
||||
$this->ping();
|
||||
}
|
||||
|
||||
if (!$this->started) {
|
||||
$this->start();
|
||||
}
|
||||
|
||||
try {
|
||||
if (!$this->started) {
|
||||
$this->start();
|
||||
}
|
||||
|
||||
$envelope = $message->getEnvelope();
|
||||
$this->doMailFromCommand($envelope->getSender()->getEncodedAddress());
|
||||
foreach ($envelope->getRecipients() as $recipient) {
|
||||
@@ -234,9 +230,13 @@ class SmtpTransport extends AbstractTransport
|
||||
$this->getLogger()->debug(sprintf('Email transport "%s" stopped', __CLASS__));
|
||||
throw $e;
|
||||
}
|
||||
$this->mtaResult = $this->executeCommand("\r\n.\r\n", [250]);
|
||||
$mtaResult = $this->executeCommand("\r\n.\r\n", [250]);
|
||||
$message->appendDebug($this->stream->getDebug());
|
||||
$this->lastMessageTime = microtime(true);
|
||||
|
||||
if ($mtaResult && $messageId = $this->parseMessageId($mtaResult)) {
|
||||
$message->setMessageId($messageId);
|
||||
}
|
||||
} catch (TransportExceptionInterface $e) {
|
||||
$e->appendDebug($this->stream->getDebug());
|
||||
$this->lastMessageTime = 0;
|
||||
@@ -335,7 +335,7 @@ class SmtpTransport extends AbstractTransport
|
||||
$codeStr = $code ? sprintf('code "%s"', $code) : 'empty code';
|
||||
$responseStr = $response ? sprintf(', with message "%s"', trim($response)) : '';
|
||||
|
||||
throw new TransportException(sprintf('Expected response code "%s" but got ', implode('/', $codes)).$codeStr.$responseStr.'.', $code ?: 0);
|
||||
throw new UnexpectedResponseException(sprintf('Expected response code "%s" but got ', implode('/', $codes)).$codeStr.$responseStr.'.', $code ?: 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ abstract class AbstractStream
|
||||
protected $in;
|
||||
/** @var resource|null */
|
||||
protected $out;
|
||||
protected $err;
|
||||
|
||||
private string $debug = '';
|
||||
|
||||
@@ -68,7 +69,7 @@ abstract class AbstractStream
|
||||
|
||||
public function terminate(): void
|
||||
{
|
||||
$this->stream = $this->out = $this->in = null;
|
||||
$this->stream = $this->err = $this->out = $this->in = null;
|
||||
}
|
||||
|
||||
public function readLine(): string
|
||||
@@ -77,15 +78,17 @@ abstract class AbstractStream
|
||||
return '';
|
||||
}
|
||||
|
||||
$line = fgets($this->out);
|
||||
$line = @fgets($this->out);
|
||||
if ('' === $line || false === $line) {
|
||||
$metas = stream_get_meta_data($this->out);
|
||||
if ($metas['timed_out']) {
|
||||
if (stream_get_meta_data($this->out)['timed_out']) {
|
||||
throw new TransportException(sprintf('Connection to "%s" timed out.', $this->getReadConnectionDescription()));
|
||||
}
|
||||
if ($metas['eof']) {
|
||||
if (feof($this->out)) { // don't use "eof" metadata, it's not accurate on Windows
|
||||
throw new TransportException(sprintf('Connection to "%s" has been closed unexpectedly.', $this->getReadConnectionDescription()));
|
||||
}
|
||||
if (false === $line) {
|
||||
throw new TransportException(sprintf('Unable to read from connection to "%s": ', $this->getReadConnectionDescription().error_get_last()['message'] ?? ''));
|
||||
}
|
||||
}
|
||||
|
||||
$this->debug .= sprintf('< %s', $line);
|
||||
|
||||
@@ -24,12 +24,18 @@ use Symfony\Component\Mailer\Exception\TransportException;
|
||||
final class ProcessStream extends AbstractStream
|
||||
{
|
||||
private string $command;
|
||||
private bool $interactive = false;
|
||||
|
||||
public function setCommand(string $command): void
|
||||
{
|
||||
$this->command = $command;
|
||||
}
|
||||
|
||||
public function setInteractive(bool $interactive): void
|
||||
{
|
||||
$this->interactive = $interactive;
|
||||
}
|
||||
|
||||
public function initialize(): void
|
||||
{
|
||||
$descriptorSpec = [
|
||||
@@ -45,17 +51,27 @@ final class ProcessStream extends AbstractStream
|
||||
}
|
||||
$this->in = &$pipes[0];
|
||||
$this->out = &$pipes[1];
|
||||
$this->err = &$pipes[2];
|
||||
}
|
||||
|
||||
public function terminate(): void
|
||||
{
|
||||
if (null !== $this->stream) {
|
||||
fclose($this->in);
|
||||
$out = stream_get_contents($this->out);
|
||||
fclose($this->out);
|
||||
proc_close($this->stream);
|
||||
$err = stream_get_contents($this->err);
|
||||
fclose($this->err);
|
||||
if (0 !== $exitCode = proc_close($this->stream)) {
|
||||
$errorMessage = 'Process failed with exit code '.$exitCode.': '.$out.$err;
|
||||
}
|
||||
}
|
||||
|
||||
parent::terminate();
|
||||
|
||||
if (!$this->interactive && isset($errorMessage)) {
|
||||
throw new TransportException($errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
protected function getReadConnectionDescription(): string
|
||||
|
||||
@@ -160,7 +160,7 @@ final class SocketStream extends AbstractStream
|
||||
}
|
||||
|
||||
stream_set_blocking($this->stream, true);
|
||||
stream_set_timeout($this->stream, $timeout);
|
||||
stream_set_timeout($this->stream, (int) $timeout, (int) (($timeout - (int) $timeout) * 1000000));
|
||||
$this->in = &$this->stream;
|
||||
$this->out = &$this->stream;
|
||||
}
|
||||
|
||||
@@ -29,5 +29,5 @@ interface TransportInterface extends \Stringable
|
||||
/**
|
||||
* @throws TransportExceptionInterface
|
||||
*/
|
||||
public function send(RawMessage $message, Envelope $envelope = null): ?SentMessage;
|
||||
public function send(RawMessage $message, ?Envelope $envelope = null): ?SentMessage;
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ final class Transports implements TransportInterface
|
||||
}
|
||||
}
|
||||
|
||||
public function send(RawMessage $message, Envelope $envelope = null): ?SentMessage
|
||||
public function send(RawMessage $message, ?Envelope $envelope = null): ?SentMessage
|
||||
{
|
||||
/** @var Message $message */
|
||||
if (RawMessage::class === $message::class || !$message->getHeaders()->has('X-Transport')) {
|
||||
|
||||
Reference in New Issue
Block a user