Skip to content

Commit 33f4e84

Browse files
committed
completely refactor the mail service provider
1 parent 1457ba4 commit 33f4e84

1 file changed

Lines changed: 122 additions & 130 deletions

File tree

Lines changed: 122 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
<?php namespace Illuminate\Mail;
22

3-
use Swift_Mailer;
3+
use Illuminate\Foundation\Application;
4+
use Illuminate\Mail\Transport\LogTransportV2;
5+
use Illuminate\Support\Arr;
46
use Illuminate\Support\ServiceProvider;
5-
use Swift_SmtpTransport as SmtpTransport;
6-
use Swift_MailTransport as MailTransport;
7-
use Illuminate\Mail\Transport\LogTransport;
8-
use Illuminate\Mail\Transport\MailgunTransport;
9-
use Illuminate\Mail\Transport\MandrillTransport;
10-
use Swift_SendmailTransport as SendmailTransport;
7+
use Symfony\Component\HttpClient\HttpClient;
8+
use Symfony\Component\Mailer\Bridge\Mailgun\Transport\MailgunTransportFactory;
9+
use Symfony\Component\Mailer\Transport\Dsn;
10+
use Symfony\Component\Mailer\Transport\SendmailTransport;
11+
use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport;
12+
use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransportFactory;
13+
use Symfony\Component\Mailer\Transport\Smtp\Stream\SocketStream;
14+
use Symfony\Contracts\HttpClient\HttpClientInterface;
1115

1216
class MailServiceProvider extends ServiceProvider {
1317

@@ -23,19 +27,19 @@ class MailServiceProvider extends ServiceProvider {
2327
*
2428
* @return void
2529
*/
26-
public function register()
30+
public function register(): void
2731
{
2832
$me = $this;
2933

3034
$this->app->bindShared('mailer', function($app) use ($me)
3135
{
32-
$me->registerSwiftMailer();
36+
$me->registerSymfonyMailer();
3337

3438
// Once we have create the mailer instance, we will set a container instance
3539
// on the mailer. This allows us to resolve mailer classes via containers
3640
// for maximum testability on said classes instead of passing Closures.
3741
$mailer = new Mailer(
38-
$app['view'], $app['swift.mailer'], $app['events']
42+
$app['view'], $app['symfony.transport'], $app['events']
3943
);
4044

4145
$this->setMailerDependencies($mailer, $app);
@@ -68,7 +72,7 @@ public function register()
6872
* @param \Illuminate\Foundation\Application $app
6973
* @return void
7074
*/
71-
protected function setMailerDependencies($mailer, $app)
75+
protected function setMailerDependencies(Mailer $mailer, Application $app): void
7276
{
7377
$mailer->setContainer($app);
7478

@@ -83,179 +87,167 @@ protected function setMailerDependencies($mailer, $app)
8387
}
8488
}
8589

86-
/**
87-
* Register the Swift Mailer instance.
88-
*
89-
* @return void
90-
*/
91-
public function registerSwiftMailer()
92-
{
93-
$config = $this->app['config']['mail'];
94-
95-
$this->registerSwiftTransport($config);
96-
97-
// Once we have the transporter registered, we will register the actual Swift
98-
// mailer instance, passing in the transport instances, which allows us to
99-
// override this transporter instances during app start-up if necessary.
100-
$this->app['swift.mailer'] = $this->app->share(function($app)
101-
{
102-
return new Swift_Mailer($app['swift.transport']);
103-
});
104-
}
105-
106-
/**
107-
* Register the Swift Transport instance.
108-
*
109-
* @param array $config
110-
* @return void
111-
*
112-
* @throws \InvalidArgumentException
113-
*/
114-
protected function registerSwiftTransport($config)
115-
{
116-
switch ($config['driver'])
117-
{
118-
case 'smtp':
119-
return $this->registerSmtpTransport($config);
120-
121-
case 'sendmail':
122-
return $this->registerSendmailTransport($config);
123-
124-
case 'mail':
125-
return $this->registerMailTransport($config);
126-
127-
case 'mailgun':
128-
return $this->registerMailgunTransport($config);
129-
130-
case 'mandrill':
131-
return $this->registerMandrillTransport($config);
132-
133-
case 'log':
134-
return $this->registerLogTransport($config);
135-
136-
default:
137-
throw new \InvalidArgumentException('Invalid mail driver.');
138-
}
139-
}
90+
public function registerSymfonyMailer(): void
91+
{
92+
$config = $this->app['config']['mail'];
93+
94+
switch ($config['driver'])
95+
{
96+
case 'smtp':
97+
$this->registerSmtpTransport($config);
98+
break;
99+
case 'sendmail':
100+
$this->registerSendmailTransport($config);
101+
break;
102+
case 'mail':
103+
$this->registerMailTransport($config);
104+
break;
105+
case 'mailgun':
106+
$this->registerMailgunTransport($config);
107+
break;
108+
// case 'mandrill':
109+
// $this->registerMandrillTransport($config);
110+
// break;
111+
case 'log':
112+
$this->registerLogTransport($config);
113+
break;
114+
default:
115+
throw new \InvalidArgumentException('Invalid mail driver.');
116+
}
117+
}
140118

141119
/**
142-
* Register the SMTP Swift Transport instance.
120+
* Register the SMTP symfony Transport instance.
143121
*
144122
* @param array $config
145123
* @return void
146124
*/
147-
protected function registerSmtpTransport($config)
125+
protected function registerSmtpTransport(array $config): void
148126
{
149-
$this->app['swift.transport'] = $this->app->share(function($app) use ($config)
127+
$this->app['symfony.transport'] = $this->app->share(function($app) use ($config)
150128
{
151-
extract($config);
152-
153-
// The Swift SMTP transport instance will allow us to use any SMTP backend
154-
// for delivering mail such as Sendgrid, Amazon SES, or a custom server
155-
// a developer has available. We will just pass this configured host.
156-
$transport = new SmtpTransport($host, $port);
157-
158-
if (isset($encryption))
159-
{
160-
$transport->setEncryption($encryption);
161-
}
162-
163-
// Once we have the transport we will check for the presence of a username
164-
// and password. If we have it we will set the credentials on the Swift
165-
// transporter instance so that we'll properly authenticate delivery.
166-
if (isset($username))
167-
{
168-
$transport->setUsername($username);
169-
170-
$transport->setPassword($password);
171-
}
129+
$factory = new EsmtpTransportFactory();
130+
131+
$scheme = $config['scheme'] ?? null;
132+
133+
if (! $scheme) {
134+
$scheme = ! empty($config['encryption']) && $config['encryption'] === 'tls'
135+
? (($config['port'] == 465) ? 'smtps' : 'smtp')
136+
: '';
137+
}
138+
139+
/** @var EsmtpTransport $transport */
140+
$transport = $factory->create(new Dsn(
141+
$scheme,
142+
$config['host'],
143+
$config['username'] ?? null,
144+
$config['password'] ?? null,
145+
$config['port'] ?? null,
146+
$config
147+
));
148+
149+
$stream = $transport->getStream();
150+
151+
if ($stream instanceof SocketStream) {
152+
if (isset($config['source_ip'])) {
153+
$stream->setSourceIp($config['source_ip']);
154+
}
155+
156+
if (isset($config['timeout'])) {
157+
$stream->setTimeout($config['timeout']);
158+
}
159+
}
172160

173161
return $transport;
174162
});
175163
}
176164

177165
/**
178-
* Register the Sendmail Swift Transport instance.
166+
* Register the Sendmail Symfony Transport instance.
179167
*
180168
* @param array $config
181169
* @return void
182170
*/
183-
protected function registerSendmailTransport($config)
171+
protected function registerSendmailTransport(array $config): void
184172
{
185-
$this->app['swift.transport'] = $this->app->share(function($app) use ($config)
186-
{
187-
return SendmailTransport::newInstance($config['sendmail']);
188-
});
173+
$this->app['symfony.transport'] = $this->app->share(fn($app) => new SendmailTransport(
174+
$config['path'] ?? $app['config']->get('mail.sendmail')
175+
));
189176
}
190177

191178
/**
192-
* Register the Mail Swift Transport instance.
179+
* Register the Mail Symfony Transport instance.
193180
*
194181
* @param array $config
195182
* @return void
196183
*/
197-
protected function registerMailTransport($config)
184+
protected function registerMailTransport(array $config): void
198185
{
199-
$this->app['swift.transport'] = $this->app->share(function()
200-
{
201-
return MailTransport::newInstance();
202-
});
186+
$this->app['symfony.transport'] = $this->app->share(fn() => new SendmailTransport());
203187
}
204188

205189
/**
206-
* Register the Mailgun Swift Transport instance.
190+
* Register the Mailgun Symfony Transport instance.
207191
*
208192
* @param array $config
209193
* @return void
210194
*/
211-
protected function registerMailgunTransport($config)
195+
protected function registerMailgunTransport(array $config): void
212196
{
213-
$mailgun = $this->app['config']->get('services.mailgun', array());
214-
215-
$this->app->bindShared('swift.transport', function() use ($mailgun)
197+
$this->app->bindShared('symfony.transport', function() use ($config)
216198
{
217-
return new MailgunTransport($mailgun['secret'], $mailgun['domain']);
199+
$factory = new MailgunTransportFactory(null, $this->getHttpClient($config));
200+
201+
if (! isset($config['secret'])) {
202+
$config = $this->app['config']->get('services.mailgun', []);
203+
}
204+
205+
return $factory->create(new Dsn(
206+
'mailgun+'.($config['scheme'] ?? 'https'),
207+
$config['endpoint'] ?? 'default',
208+
$config['secret'],
209+
$config['domain']
210+
));
218211
});
219212
}
220213

221214
/**
222-
* Register the Mandrill Swift Transport instance.
215+
* Register the "Log" Symfony Transport instance.
223216
*
224217
* @param array $config
225218
* @return void
226219
*/
227-
protected function registerMandrillTransport($config)
220+
protected function registerLogTransport(array $config): void
228221
{
229-
$mandrill = $this->app['config']->get('services.mandrill', array());
230-
231-
$this->app->bindShared('swift.transport', function() use ($mandrill)
232-
{
233-
return new MandrillTransport($mandrill['secret']);
234-
});
222+
$this->app->bindShared('symfony.transport', fn($app) => new LogTransportV2($app->make('Psr\Log\LoggerInterface')));
235223
}
236224

237-
/**
238-
* Register the "Log" Swift Transport instance.
239-
*
240-
* @param array $config
241-
* @return void
242-
*/
243-
protected function registerLogTransport($config)
244-
{
245-
$this->app->bindShared('swift.transport', function($app)
246-
{
247-
return new LogTransport($app->make('Psr\Log\LoggerInterface'));
248-
});
249-
}
225+
/**
226+
* Get a configured Symfony HTTP client instance.
227+
*
228+
* @return \Symfony\Contracts\HttpClient\HttpClientInterface|null
229+
*/
230+
protected function getHttpClient(array $config): ?HttpClientInterface
231+
{
232+
$clientOptions = $config['client'] ?? false;
233+
if ($clientOptions) {
234+
$maxHostConnections = Arr::pull($clientOptions, 'max_host_connections', 6);
235+
$maxPendingPushes = Arr::pull($clientOptions, 'max_pending_pushes', 50);
236+
237+
return HttpClient::create($clientOptions, $maxHostConnections, $maxPendingPushes);
238+
}
239+
240+
return null;
241+
}
250242

251243
/**
252244
* Get the services provided by the provider.
253245
*
254246
* @return array
255247
*/
256-
public function provides()
248+
public function provides(): array
257249
{
258-
return array('mailer', 'swift.mailer', 'swift.transport');
250+
return ['mailer', 'symfony.transport'];
259251
}
260252

261253
}

0 commit comments

Comments
 (0)