vendor/symfony/mailer/Transport.php line 101

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\EventDispatcher\EventDispatcherInterface;
  12. use Psr\Log\LoggerInterface;
  13. use Symfony\Component\Mailer\Bridge\Amazon\Transport\SesTransportFactory;
  14. use Symfony\Component\Mailer\Bridge\Google\Transport\GmailTransportFactory;
  15. use Symfony\Component\Mailer\Bridge\Mailchimp\Transport\MandrillTransportFactory;
  16. use Symfony\Component\Mailer\Bridge\Mailgun\Transport\MailgunTransportFactory;
  17. use Symfony\Component\Mailer\Bridge\Mailjet\Transport\MailjetTransportFactory;
  18. use Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpTransportFactory;
  19. use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkTransportFactory;
  20. use Symfony\Component\Mailer\Bridge\Sendgrid\Transport\SendgridTransportFactory;
  21. use Symfony\Component\Mailer\Bridge\Sendinblue\Transport\SendinblueTransportFactory;
  22. use Symfony\Component\Mailer\Exception\InvalidArgumentException;
  23. use Symfony\Component\Mailer\Exception\UnsupportedSchemeException;
  24. use Symfony\Component\Mailer\Transport\Dsn;
  25. use Symfony\Component\Mailer\Transport\FailoverTransport;
  26. use Symfony\Component\Mailer\Transport\NativeTransportFactory;
  27. use Symfony\Component\Mailer\Transport\NullTransportFactory;
  28. use Symfony\Component\Mailer\Transport\RoundRobinTransport;
  29. use Symfony\Component\Mailer\Transport\SendmailTransportFactory;
  30. use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransportFactory;
  31. use Symfony\Component\Mailer\Transport\TransportFactoryInterface;
  32. use Symfony\Component\Mailer\Transport\TransportInterface;
  33. use Symfony\Component\Mailer\Transport\Transports;
  34. use Symfony\Contracts\HttpClient\HttpClientInterface;
  35. /**
  36.  * @author Fabien Potencier <fabien@symfony.com>
  37.  * @author Konstantin Myakshin <molodchick@gmail.com>
  38.  *
  39.  * @final since Symfony 5.4
  40.  */
  41. class Transport
  42. {
  43.     private const FACTORY_CLASSES = [
  44.         GmailTransportFactory::class,
  45.         MailgunTransportFactory::class,
  46.         MailjetTransportFactory::class,
  47.         MandrillTransportFactory::class,
  48.         OhMySmtpTransportFactory::class,
  49.         PostmarkTransportFactory::class,
  50.         SendgridTransportFactory::class,
  51.         SendinblueTransportFactory::class,
  52.         SesTransportFactory::class,
  53.     ];
  54.     private $factories;
  55.     /**
  56.      * @param EventDispatcherInterface|null $dispatcher
  57.      * @param HttpClientInterface|null      $client
  58.      * @param LoggerInterface|null          $logger
  59.      */
  60.     public static function fromDsn(string $dsn/* , EventDispatcherInterface $dispatcher = null, HttpClientInterface $client = null, LoggerInterface $logger = null */): TransportInterface
  61.     {
  62.         $dispatcher <= \func_num_args() ? func_get_arg(1) : null;
  63.         $client <= \func_num_args() ? func_get_arg(2) : null;
  64.         $logger <= \func_num_args() ? func_get_arg(3) : null;
  65.         $factory = new self(iterator_to_array(self::getDefaultFactories($dispatcher$client$logger)));
  66.         return $factory->fromString($dsn);
  67.     }
  68.     /**
  69.      * @param EventDispatcherInterface|null $dispatcher
  70.      * @param HttpClientInterface|null      $client
  71.      * @param LoggerInterface|null          $logger
  72.      */
  73.     public static function fromDsns(array $dsns/* , EventDispatcherInterface $dispatcher = null, HttpClientInterface $client = null, LoggerInterface $logger = null */): TransportInterface
  74.     {
  75.         $dispatcher <= \func_num_args() ? func_get_arg(1) : null;
  76.         $client <= \func_num_args() ? func_get_arg(2) : null;
  77.         $logger <= \func_num_args() ? func_get_arg(3) : null;
  78.         $factory = new self(iterator_to_array(self::getDefaultFactories($dispatcher$client$logger)));
  79.         return $factory->fromStrings($dsns);
  80.     }
  81.     /**
  82.      * @param TransportFactoryInterface[] $factories
  83.      */
  84.     public function __construct(iterable $factories)
  85.     {
  86.         $this->factories $factories;
  87.     }
  88.     public function fromStrings(array $dsns): Transports
  89.     {
  90.         $transports = [];
  91.         foreach ($dsns as $name => $dsn) {
  92.             $transports[$name] = $this->fromString($dsn);
  93.         }
  94.         return new Transports($transports);
  95.     }
  96.     public function fromString(string $dsn): TransportInterface
  97.     {
  98.         [$transport$offset] = $this->parseDsn($dsn);
  99.         if ($offset !== \strlen($dsn)) {
  100.             throw new InvalidArgumentException(sprintf('The DSN has some garbage at the end: "%s".'substr($dsn$offset)));
  101.         }
  102.         return $transport;
  103.     }
  104.     private function parseDsn(string $dsnint $offset 0): array
  105.     {
  106.         static $keywords = [
  107.             'failover' => FailoverTransport::class,
  108.             'roundrobin' => RoundRobinTransport::class,
  109.         ];
  110.         while (true) {
  111.             foreach ($keywords as $name => $class) {
  112.                 $name .= '(';
  113.                 if ($name === substr($dsn$offset, \strlen($name))) {
  114.                     $offset += \strlen($name) - 1;
  115.                     preg_match('{\(([^()]|(?R))*\)}A'$dsn$matches0$offset);
  116.                     if (!isset($matches[0])) {
  117.                         continue;
  118.                     }
  119.                     ++$offset;
  120.                     $args = [];
  121.                     while (true) {
  122.                         [$arg$offset] = $this->parseDsn($dsn$offset);
  123.                         $args[] = $arg;
  124.                         if (\strlen($dsn) === $offset) {
  125.                             break;
  126.                         }
  127.                         ++$offset;
  128.                         if (')' === $dsn[$offset 1]) {
  129.                             break;
  130.                         }
  131.                     }
  132.                     return [new $class($args), $offset];
  133.                 }
  134.             }
  135.             if (preg_match('{(\w+)\(}A'$dsn$matches0$offset)) {
  136.                 throw new InvalidArgumentException(sprintf('The "%s" keyword is not valid (valid ones are "%s"), '$matches[1], implode('", "'array_keys($keywords))));
  137.             }
  138.             if ($pos strcspn($dsn' )'$offset)) {
  139.                 return [$this->fromDsnObject(Dsn::fromString(substr($dsn$offset$pos))), $offset $pos];
  140.             }
  141.             return [$this->fromDsnObject(Dsn::fromString(substr($dsn$offset))), \strlen($dsn)];
  142.         }
  143.     }
  144.     public function fromDsnObject(Dsn $dsn): TransportInterface
  145.     {
  146.         foreach ($this->factories as $factory) {
  147.             if ($factory->supports($dsn)) {
  148.                 return $factory->create($dsn);
  149.             }
  150.         }
  151.         throw new UnsupportedSchemeException($dsn);
  152.     }
  153.     /**
  154.      * @param EventDispatcherInterface|null $dispatcher
  155.      * @param HttpClientInterface|null      $client
  156.      * @param LoggerInterface|null          $logger
  157.      *
  158.      * @return \Traversable<int, TransportFactoryInterface>
  159.      */
  160.     public static function getDefaultFactories(/* EventDispatcherInterface $dispatcher = null, HttpClientInterface $client = null, LoggerInterface $logger = null */): iterable
  161.     {
  162.         $dispatcher <= \func_num_args() ? func_get_arg(0) : null;
  163.         $client <= \func_num_args() ? func_get_arg(1) : null;
  164.         $logger <= \func_num_args() ? func_get_arg(2) : null;
  165.         foreach (self::FACTORY_CLASSES as $factoryClass) {
  166.             if (class_exists($factoryClass)) {
  167.                 yield new $factoryClass($dispatcher$client$logger);
  168.             }
  169.         }
  170.         yield new NullTransportFactory($dispatcher$client$logger);
  171.         yield new SendmailTransportFactory($dispatcher$client$logger);
  172.         yield new EsmtpTransportFactory($dispatcher$client$logger);
  173.         yield new NativeTransportFactory($dispatcher$client$logger);
  174.     }
  175. }