Файл: vendor/symfony/mailer/Transport.php
Строк: 390
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SymfonyComponentMailer;
use PsrEventDispatcherEventDispatcherInterface;
use PsrLogLoggerInterface;
use SymfonyComponentMailerBridgeAmazonTransportSesTransportFactory;
use SymfonyComponentMailerBridgeBrevoTransportBrevoTransportFactory;
use SymfonyComponentMailerBridgeGoogleTransportGmailTransportFactory;
use SymfonyComponentMailerBridgeInfobipTransportInfobipTransportFactory;
use SymfonyComponentMailerBridgeMailchimpTransportMandrillTransportFactory;
use SymfonyComponentMailerBridgeMailerSendTransportMailerSendTransportFactory;
use SymfonyComponentMailerBridgeMailgunTransportMailgunTransportFactory;
use SymfonyComponentMailerBridgeMailjetTransportMailjetTransportFactory;
use SymfonyComponentMailerBridgeMailPaceTransportMailPaceTransportFactory;
use SymfonyComponentMailerBridgeOhMySmtpTransportOhMySmtpTransportFactory;
use SymfonyComponentMailerBridgePostmarkTransportPostmarkTransportFactory;
use SymfonyComponentMailerBridgeScalewayTransportScalewayTransportFactory;
use SymfonyComponentMailerBridgeSendgridTransportSendgridTransportFactory;
use SymfonyComponentMailerBridgeSendinblueTransportSendinblueTransportFactory;
use SymfonyComponentMailerExceptionInvalidArgumentException;
use SymfonyComponentMailerExceptionUnsupportedSchemeException;
use SymfonyComponentMailerTransportDsn;
use SymfonyComponentMailerTransportFailoverTransport;
use SymfonyComponentMailerTransportNativeTransportFactory;
use SymfonyComponentMailerTransportNullTransportFactory;
use SymfonyComponentMailerTransportRoundRobinTransport;
use SymfonyComponentMailerTransportSendmailTransportFactory;
use SymfonyComponentMailerTransportSmtpEsmtpTransportFactory;
use SymfonyComponentMailerTransportTransportFactoryInterface;
use SymfonyComponentMailerTransportTransportInterface;
use SymfonyComponentMailerTransportTransports;
use SymfonyContractsHttpClientHttpClientInterface;
/**
* @author Fabien Potencier <fabien@symfony.com>
* @author Konstantin Myakshin <molodchick@gmail.com>
*/
final class Transport
{
private const FACTORY_CLASSES = [
BrevoTransportFactory::class,
GmailTransportFactory::class,
InfobipTransportFactory::class,
MailerSendTransportFactory::class,
MailgunTransportFactory::class,
MailjetTransportFactory::class,
MailPaceTransportFactory::class,
MandrillTransportFactory::class,
OhMySmtpTransportFactory::class,
PostmarkTransportFactory::class,
ScalewayTransportFactory::class,
SendgridTransportFactory::class,
SendinblueTransportFactory::class,
SesTransportFactory::class,
];
private iterable $factories;
public static function fromDsn(#[SensitiveParameter] string $dsn, ?EventDispatcherInterface $dispatcher = null, ?HttpClientInterface $client = null, ?LoggerInterface $logger = null): TransportInterface
{
$factory = new self(iterator_to_array(self::getDefaultFactories($dispatcher, $client, $logger)));
return $factory->fromString($dsn);
}
public static function fromDsns(#[SensitiveParameter] array $dsns, ?EventDispatcherInterface $dispatcher = null, ?HttpClientInterface $client = null, ?LoggerInterface $logger = null): TransportInterface
{
$factory = new self(iterator_to_array(self::getDefaultFactories($dispatcher, $client, $logger)));
return $factory->fromStrings($dsns);
}
/**
* @param TransportFactoryInterface[] $factories
*/
public function __construct(iterable $factories)
{
$this->factories = $factories;
}
public function fromStrings(#[SensitiveParameter] array $dsns): Transports
{
$transports = [];
foreach ($dsns as $name => $dsn) {
$transports[$name] = $this->fromString($dsn);
}
return new Transports($transports);
}
public function fromString(#[SensitiveParameter] string $dsn): TransportInterface
{
[$transport, $offset] = $this->parseDsn($dsn);
if ($offset !== strlen($dsn)) {
throw new InvalidArgumentException('The mailer DSN has some garbage at the end.');
}
return $transport;
}
private function parseDsn(#[SensitiveParameter] string $dsn, int $offset = 0): array
{
static $keywords = [
'failover' => FailoverTransport::class,
'roundrobin' => RoundRobinTransport::class,
];
while (true) {
foreach ($keywords as $name => $class) {
$name .= '(';
if ($name === substr($dsn, $offset, strlen($name))) {
$offset += strlen($name) - 1;
preg_match('{(([^()]|(?R))*)}A', $dsn, $matches, 0, $offset);
if (!isset($matches[0])) {
continue;
}
++$offset;
$args = [];
while (true) {
[$arg, $offset] = $this->parseDsn($dsn, $offset);
$args[] = $arg;
if (strlen($dsn) === $offset) {
break;
}
++$offset;
if (')' === $dsn[$offset - 1]) {
break;
}
}
return [new $class($args), $offset];
}
}
if (preg_match('{(w+)(}A', $dsn, $matches, 0, $offset)) {
throw new InvalidArgumentException(sprintf('The "%s" keyword is not valid (valid ones are "%s"), ', $matches[1], implode('", "', array_keys($keywords))));
}
if ($pos = strcspn($dsn, ' )', $offset)) {
return [$this->fromDsnObject(Dsn::fromString(substr($dsn, $offset, $pos))), $offset + $pos];
}
return [$this->fromDsnObject(Dsn::fromString(substr($dsn, $offset))), strlen($dsn)];
}
}
public function fromDsnObject(Dsn $dsn): TransportInterface
{
foreach ($this->factories as $factory) {
if ($factory->supports($dsn)) {
return $factory->create($dsn);
}
}
throw new UnsupportedSchemeException($dsn);
}
/**
* @return Traversable<int, TransportFactoryInterface>
*/
public static function getDefaultFactories(?EventDispatcherInterface $dispatcher = null, ?HttpClientInterface $client = null, ?LoggerInterface $logger = null): Traversable
{
foreach (self::FACTORY_CLASSES as $factoryClass) {
if (class_exists($factoryClass)) {
yield new $factoryClass($dispatcher, $client, $logger);
}
}
yield new NullTransportFactory($dispatcher, $client, $logger);
yield new SendmailTransportFactory($dispatcher, $client, $logger);
yield new EsmtpTransportFactory($dispatcher, $client, $logger);
yield new NativeTransportFactory($dispatcher, $client, $logger);
}
}