vendor/symfony/mailer/Transport/Smtp/Stream/SocketStream.php line 154

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\Transport\Smtp\Stream;
  11. use Symfony\Component\Mailer\Exception\TransportException;
  12. /**
  13.  * A stream supporting remote sockets.
  14.  *
  15.  * @author Fabien Potencier <fabien@symfony.com>
  16.  * @author Chris Corbyn
  17.  *
  18.  * @internal
  19.  */
  20. final class SocketStream extends AbstractStream
  21. {
  22.     private string $url;
  23.     private string $host 'localhost';
  24.     private int $port 465;
  25.     private float $timeout;
  26.     private bool $tls true;
  27.     private ?string $sourceIp null;
  28.     private array $streamContextOptions = [];
  29.     /**
  30.      * @return $this
  31.      */
  32.     public function setTimeout(float $timeout): static
  33.     {
  34.         $this->timeout $timeout;
  35.         return $this;
  36.     }
  37.     public function getTimeout(): float
  38.     {
  39.         return $this->timeout ?? (float) \ini_get('default_socket_timeout');
  40.     }
  41.     /**
  42.      * Literal IPv6 addresses should be wrapped in square brackets.
  43.      *
  44.      * @return $this
  45.      */
  46.     public function setHost(string $host): static
  47.     {
  48.         $this->host $host;
  49.         return $this;
  50.     }
  51.     public function getHost(): string
  52.     {
  53.         return $this->host;
  54.     }
  55.     /**
  56.      * @return $this
  57.      */
  58.     public function setPort(int $port): static
  59.     {
  60.         $this->port $port;
  61.         return $this;
  62.     }
  63.     public function getPort(): int
  64.     {
  65.         return $this->port;
  66.     }
  67.     /**
  68.      * Sets the TLS/SSL on the socket (disables STARTTLS).
  69.      *
  70.      * @return $this
  71.      */
  72.     public function disableTls(): static
  73.     {
  74.         $this->tls false;
  75.         return $this;
  76.     }
  77.     public function isTLS(): bool
  78.     {
  79.         return $this->tls;
  80.     }
  81.     /**
  82.      * @return $this
  83.      */
  84.     public function setStreamOptions(array $options): static
  85.     {
  86.         $this->streamContextOptions $options;
  87.         return $this;
  88.     }
  89.     public function getStreamOptions(): array
  90.     {
  91.         return $this->streamContextOptions;
  92.     }
  93.     /**
  94.      * Sets the source IP.
  95.      *
  96.      * IPv6 addresses should be wrapped in square brackets.
  97.      *
  98.      * @return $this
  99.      */
  100.     public function setSourceIp(string $ip): static
  101.     {
  102.         $this->sourceIp $ip;
  103.         return $this;
  104.     }
  105.     /**
  106.      * Returns the IP used to connect to the destination.
  107.      */
  108.     public function getSourceIp(): ?string
  109.     {
  110.         return $this->sourceIp;
  111.     }
  112.     public function initialize(): void
  113.     {
  114.         $this->url $this->host.':'.$this->port;
  115.         if ($this->tls) {
  116.             $this->url 'ssl://'.$this->url;
  117.         }
  118.         $options = [];
  119.         if ($this->sourceIp) {
  120.             $options['socket']['bindto'] = $this->sourceIp.':0';
  121.         }
  122.         if ($this->streamContextOptions) {
  123.             $options array_merge($options$this->streamContextOptions);
  124.         }
  125.         // do it unconditionnally as it will be used by STARTTLS as well if supported
  126.         $options['ssl']['crypto_method'] = $options['ssl']['crypto_method'] ?? \STREAM_CRYPTO_METHOD_TLS_CLIENT \STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT \STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT;
  127.         $streamContext stream_context_create($options);
  128.         $timeout $this->getTimeout();
  129.         set_error_handler(function ($type$msg) {
  130.             throw new TransportException(sprintf('Connection could not be established with host "%s": '$this->url).$msg);
  131.         });
  132.         try {
  133.             $this->stream stream_socket_client($this->url$errno$errstr$timeout\STREAM_CLIENT_CONNECT$streamContext);
  134.         } finally {
  135.             restore_error_handler();
  136.         }
  137.         stream_set_blocking($this->streamtrue);
  138.         stream_set_timeout($this->stream$timeout);
  139.         $this->in = &$this->stream;
  140.         $this->out = &$this->stream;
  141.     }
  142.     public function startTLS(): bool
  143.     {
  144.         set_error_handler(function ($type$msg) {
  145.             throw new TransportException('Unable to connect with STARTTLS: '.$msg);
  146.         });
  147.         try {
  148.             return stream_socket_enable_crypto($this->streamtrue);
  149.         } finally {
  150.             restore_error_handler();
  151.         }
  152.     }
  153.     public function terminate(): void
  154.     {
  155.         if (null !== $this->stream) {
  156.             fclose($this->stream);
  157.         }
  158.         parent::terminate();
  159.     }
  160.     protected function getReadConnectionDescription(): string
  161.     {
  162.         return $this->url;
  163.     }
  164. }