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