vendor/symfony/mailer/Transport.php line 134

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the Symfony package.
  4.  *
  5.  * (c) Fabien Potencier <fabien@symfony.com>
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  */
  10. namespace Symfony\Component\Mailer;
  11. use Psr\Log\LoggerInterface;
  12. use Symfony\Component\Mailer\Bridge\Amazon\Transport\SesTransportFactory;
  13. use Symfony\Component\Mailer\Bridge\Google\Transport\GmailTransportFactory;
  14. use Symfony\Component\Mailer\Bridge\Mailchimp\Transport\MandrillTransportFactory;
  15. use Symfony\Component\Mailer\Bridge\Mailgun\Transport\MailgunTransportFactory;
  16. use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkTransportFactory;
  17. use Symfony\Component\Mailer\Bridge\Sendgrid\Transport\SendgridTransportFactory;
  18. use Symfony\Component\Mailer\Exception\InvalidArgumentException;
  19. use Symfony\Component\Mailer\Exception\UnsupportedSchemeException;
  20. use Symfony\Component\Mailer\Transport\Dsn;
  21. use Symfony\Component\Mailer\Transport\FailoverTransport;
  22. use Symfony\Component\Mailer\Transport\NullTransportFactory;
  23. use Symfony\Component\Mailer\Transport\RoundRobinTransport;
  24. use Symfony\Component\Mailer\Transport\SendmailTransportFactory;
  25. use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransportFactory;
  26. use Symfony\Component\Mailer\Transport\TransportFactoryInterface;
  27. use Symfony\Component\Mailer\Transport\TransportInterface;
  28. use Symfony\Component\Mailer\Transport\Transports;
  29. use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
  30. use Symfony\Contracts\HttpClient\HttpClientInterface;
  31. /**
  32.  * @author Fabien Potencier <fabien@symfony.com>
  33.  * @author Konstantin Myakshin <molodchick@gmail.com>
  34.  */
  35. class Transport
  36. {
  37.     private const FACTORY_CLASSES = [
  38.         SesTransportFactory::class,
  39.         GmailTransportFactory::class,
  40.         MandrillTransportFactory::class,
  41.         MailgunTransportFactory::class,
  42.         PostmarkTransportFactory::class,
  43.         SendgridTransportFactory::class,
  44.     ];
  45.     private $factories;
  46.     public static function fromDsn(string $dsnEventDispatcherInterface $dispatcher nullHttpClientInterface $client nullLoggerInterface $logger null): TransportInterface
  47.     {
  48.         $factory = new self(iterator_to_array(self::getDefaultFactories($dispatcher$client$logger)));
  49.         return $factory->fromString($dsn);
  50.     }
  51.     public static function fromDsns(array $dsnsEventDispatcherInterface $dispatcher nullHttpClientInterface $client nullLoggerInterface $logger null): TransportInterface
  52.     {
  53.         $factory = new self(iterator_to_array(self::getDefaultFactories($dispatcher$client$logger)));
  54.         return $factory->fromStrings($dsns);
  55.     }
  56.     /**
  57.      * @param TransportFactoryInterface[] $factories
  58.      */
  59.     public function __construct(iterable $factories)
  60.     {
  61.         $this->factories $factories;
  62.     }
  63.     public function fromStrings(array $dsns): Transports
  64.     {
  65.         $transports = [];
  66.         foreach ($dsns as $name => $dsn) {
  67.             $transports[$name] = $this->fromString($dsn);
  68.         }
  69.         return new Transports($transports);
  70.     }
  71.     public function fromString(string $dsn): TransportInterface
  72.     {
  73.         list($transport$offset) = $this->parseDsn($dsn);
  74.         if ($offset !== \strlen($dsn)) {
  75.             throw new InvalidArgumentException(sprintf('The DSN has some garbage at the end: "%s".'substr($dsn$offset)));
  76.         }
  77.         return $transport;
  78.     }
  79.     private function parseDsn(string $dsnint $offset 0): array
  80.     {
  81.         static $keywords = [
  82.             'failover' => FailoverTransport::class,
  83.             'roundrobin' => RoundRobinTransport::class,
  84.         ];
  85.         while (true) {
  86.             foreach ($keywords as $name => $class) {
  87.                 $name .= '(';
  88.                 if ($name === substr($dsn$offset, \strlen($name))) {
  89.                     $offset += \strlen($name) - 1;
  90.                     preg_match('{\(([^()]|(?R))*\)}A'$dsn$matches0$offset);
  91.                     if (!isset($matches[0])) {
  92.                         continue;
  93.                     }
  94.                     ++$offset;
  95.                     $args = [];
  96.                     while (true) {
  97.                         list($arg$offset) = $this->parseDsn($dsn$offset);
  98.                         $args[] = $arg;
  99.                         if (\strlen($dsn) === $offset) {
  100.                             break;
  101.                         }
  102.                         ++$offset;
  103.                         if (')' === $dsn[$offset 1]) {
  104.                             break;
  105.                         }
  106.                     }
  107.                     return [new $class($args), $offset];
  108.                 }
  109.             }
  110.             if (preg_match('{(\w+)\(}A'$dsn$matches0$offset)) {
  111.                 throw new InvalidArgumentException(sprintf('The "%s" keyword is not valid (valid ones are "%s"), '$matches[1], implode('", "'array_keys($keywords))));
  112.             }
  113.             if ($pos strcspn($dsn' )'$offset)) {
  114.                 return [$this->fromDsnObject(Dsn::fromString(substr($dsn$offset$pos))), $offset $pos];
  115.             }
  116.             return [$this->fromDsnObject(Dsn::fromString(substr($dsn$offset))), \strlen($dsn)];
  117.         }
  118.     }
  119.     public function fromDsnObject(Dsn $dsn): TransportInterface
  120.     {
  121.         foreach ($this->factories as $factory) {
  122.             if ($factory->supports($dsn)) {
  123.                 return $factory->create($dsn);
  124.             }
  125.         }
  126.         throw new UnsupportedSchemeException($dsn);
  127.     }
  128.     private static function getDefaultFactories(EventDispatcherInterface $dispatcher nullHttpClientInterface $client nullLoggerInterface $logger null): iterable
  129.     {
  130.         foreach (self::FACTORY_CLASSES as $factoryClass) {
  131.             if (class_exists($factoryClass)) {
  132.                 yield new $factoryClass($dispatcher$client$logger);
  133.             }
  134.         }
  135.         yield new NullTransportFactory($dispatcher$client$logger);
  136.         yield new SendmailTransportFactory($dispatcher$client$logger);
  137.         yield new EsmtpTransportFactory($dispatcher$client$logger);
  138.     }
  139. }