vendor/symfony/mailer/Transport/AbstractTransport.php line 61

  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\Transport;
  11. use Psr\EventDispatcher\EventDispatcherInterface;
  12. use Psr\Log\LoggerInterface;
  13. use Psr\Log\NullLogger;
  14. use Symfony\Bridge\Twig\Mime\TemplatedEmail;
  15. use Symfony\Component\Mailer\Envelope;
  16. use Symfony\Component\Mailer\Event\FailedMessageEvent;
  17. use Symfony\Component\Mailer\Event\MessageEvent;
  18. use Symfony\Component\Mailer\Event\SentMessageEvent;
  19. use Symfony\Component\Mailer\Exception\LogicException;
  20. use Symfony\Component\Mailer\SentMessage;
  21. use Symfony\Component\Mime\Address;
  22. use Symfony\Component\Mime\BodyRendererInterface;
  23. use Symfony\Component\Mime\RawMessage;
  24. /**
  25.  * @author Fabien Potencier <fabien@symfony.com>
  26.  */
  27. abstract class AbstractTransport implements TransportInterface
  28. {
  29.     private ?EventDispatcherInterface $dispatcher;
  30.     private LoggerInterface $logger;
  31.     private float $rate 0;
  32.     private float $lastSent 0;
  33.     public function __construct(EventDispatcherInterface $dispatcher nullLoggerInterface $logger null)
  34.     {
  35.         $this->dispatcher $dispatcher;
  36.         $this->logger $logger ?? new NullLogger();
  37.     }
  38.     /**
  39.      * Sets the maximum number of messages to send per second (0 to disable).
  40.      *
  41.      * @return $this
  42.      */
  43.     public function setMaxPerSecond(float $rate): static
  44.     {
  45.         if (>= $rate) {
  46.             $rate 0;
  47.         }
  48.         $this->rate $rate;
  49.         $this->lastSent 0;
  50.         return $this;
  51.     }
  52.     public function send(RawMessage $messageEnvelope $envelope null): ?SentMessage
  53.     {
  54.         $message = clone $message;
  55.         $envelope null !== $envelope ? clone $envelope Envelope::create($message);
  56.         try {
  57.             if (!$this->dispatcher) {
  58.                 $sentMessage = new SentMessage($message$envelope);
  59.                 $this->doSend($sentMessage);
  60.                 return $sentMessage;
  61.             }
  62.             $event = new MessageEvent($message$envelope, (string) $this);
  63.             $this->dispatcher->dispatch($event);
  64.             $envelope $event->getEnvelope();
  65.             $message $event->getMessage();
  66.             if ($message instanceof TemplatedEmail && !$message->isRendered()) {
  67.                 throw new LogicException(sprintf('You must configure a "%s" when a "%s" instance has a text or HTML template set.'BodyRendererInterface::class, get_debug_type($message)));
  68.             }
  69.             $sentMessage = new SentMessage($message$envelope);
  70.             try {
  71.                 $this->doSend($sentMessage);
  72.             } catch (\Throwable $error) {
  73.                 $this->dispatcher->dispatch(new FailedMessageEvent($message$error));
  74.                 $this->checkThrottling();
  75.                 throw $error;
  76.             }
  77.             $this->dispatcher->dispatch(new SentMessageEvent($sentMessage));
  78.             return $sentMessage;
  79.         } finally {
  80.             $this->checkThrottling();
  81.         }
  82.     }
  83.     abstract protected function doSend(SentMessage $message): void;
  84.     /**
  85.      * @param Address[] $addresses
  86.      *
  87.      * @return string[]
  88.      */
  89.     protected function stringifyAddresses(array $addresses): array
  90.     {
  91.         return array_map(function (Address $a) {
  92.             return $a->toString();
  93.         }, $addresses);
  94.     }
  95.     protected function getLogger(): LoggerInterface
  96.     {
  97.         return $this->logger;
  98.     }
  99.     private function checkThrottling()
  100.     {
  101.         if (== $this->rate) {
  102.             return;
  103.         }
  104.         $sleep = ($this->rate) - (microtime(true) - $this->lastSent);
  105.         if ($sleep) {
  106.             $this->logger->debug(sprintf('Email transport "%s" sleeps for %.2f seconds'__CLASS__$sleep));
  107.             usleep($sleep 1000000);
  108.         }
  109.         $this->lastSent microtime(true);
  110.     }
  111. }