Subversion-Projekte lars-tiefland.laravel_shop

Revision

Revision 399 | Details | Vergleich mit vorheriger | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
namespace Illuminate\Mail;
4
 
5
use Aws\Ses\SesClient;
621 lars 6
use Aws\SesV2\SesV2Client;
148 lars 7
use Closure;
8
use Illuminate\Contracts\Mail\Factory as FactoryContract;
9
use Illuminate\Log\LogManager;
10
use Illuminate\Mail\Transport\ArrayTransport;
11
use Illuminate\Mail\Transport\LogTransport;
12
use Illuminate\Mail\Transport\SesTransport;
621 lars 13
use Illuminate\Mail\Transport\SesV2Transport;
148 lars 14
use Illuminate\Support\Arr;
15
use Illuminate\Support\Str;
16
use InvalidArgumentException;
17
use Psr\Log\LoggerInterface;
150 lars 18
use Symfony\Component\HttpClient\HttpClient;
148 lars 19
use Symfony\Component\Mailer\Bridge\Mailgun\Transport\MailgunTransportFactory;
20
use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkTransportFactory;
21
use Symfony\Component\Mailer\Transport\Dsn;
22
use Symfony\Component\Mailer\Transport\FailoverTransport;
23
use Symfony\Component\Mailer\Transport\SendmailTransport;
24
use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport;
25
use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransportFactory;
26
use Symfony\Component\Mailer\Transport\Smtp\Stream\SocketStream;
27
 
28
/**
29
 * @mixin \Illuminate\Mail\Mailer
30
 */
31
class MailManager implements FactoryContract
32
{
33
    /**
34
     * The application instance.
35
     *
36
     * @var \Illuminate\Contracts\Foundation\Application
37
     */
38
    protected $app;
39
 
40
    /**
41
     * The array of resolved mailers.
42
     *
43
     * @var array
44
     */
45
    protected $mailers = [];
46
 
47
    /**
48
     * The registered custom driver creators.
49
     *
50
     * @var array
51
     */
52
    protected $customCreators = [];
53
 
54
    /**
55
     * Create a new Mail manager instance.
56
     *
57
     * @param  \Illuminate\Contracts\Foundation\Application  $app
58
     * @return void
59
     */
60
    public function __construct($app)
61
    {
62
        $this->app = $app;
63
    }
64
 
65
    /**
66
     * Get a mailer instance by name.
67
     *
68
     * @param  string|null  $name
69
     * @return \Illuminate\Contracts\Mail\Mailer
70
     */
71
    public function mailer($name = null)
72
    {
73
        $name = $name ?: $this->getDefaultDriver();
74
 
75
        return $this->mailers[$name] = $this->get($name);
76
    }
77
 
78
    /**
79
     * Get a mailer driver instance.
80
     *
81
     * @param  string|null  $driver
82
     * @return \Illuminate\Mail\Mailer
83
     */
84
    public function driver($driver = null)
85
    {
86
        return $this->mailer($driver);
87
    }
88
 
89
    /**
90
     * Attempt to get the mailer from the local cache.
91
     *
92
     * @param  string  $name
93
     * @return \Illuminate\Mail\Mailer
94
     */
95
    protected function get($name)
96
    {
97
        return $this->mailers[$name] ?? $this->resolve($name);
98
    }
99
 
100
    /**
101
     * Resolve the given mailer.
102
     *
103
     * @param  string  $name
104
     * @return \Illuminate\Mail\Mailer
105
     *
106
     * @throws \InvalidArgumentException
107
     */
108
    protected function resolve($name)
109
    {
110
        $config = $this->getConfig($name);
111
 
112
        if (is_null($config)) {
113
            throw new InvalidArgumentException("Mailer [{$name}] is not defined.");
114
        }
115
 
116
        // Once we have created the mailer instance we will set a container instance
117
        // on the mailer. This allows us to resolve mailer classes via containers
118
        // for maximum testability on said classes instead of passing Closures.
119
        $mailer = new Mailer(
120
            $name,
121
            $this->app['view'],
122
            $this->createSymfonyTransport($config),
123
            $this->app['events']
124
        );
125
 
126
        if ($this->app->bound('queue')) {
127
            $mailer->setQueue($this->app['queue']);
128
        }
129
 
130
        // Next we will set all of the global addresses on this mailer, which allows
131
        // for easy unification of all "from" addresses as well as easy debugging
132
        // of sent messages since these will be sent to a single email address.
133
        foreach (['from', 'reply_to', 'to', 'return_path'] as $type) {
134
            $this->setGlobalAddress($mailer, $config, $type);
135
        }
136
 
137
        return $mailer;
138
    }
139
 
140
    /**
141
     * Create a new transport instance.
142
     *
143
     * @param  array  $config
144
     * @return \Symfony\Component\Mailer\Transport\TransportInterface
145
     *
146
     * @throws \InvalidArgumentException
147
     */
148
    public function createSymfonyTransport(array $config)
149
    {
150
        // Here we will check if the "transport" key exists and if it doesn't we will
151
        // assume an application is still using the legacy mail configuration file
152
        // format and use the "mail.driver" configuration option instead for BC.
153
        $transport = $config['transport'] ?? $this->app['config']['mail.driver'];
154
 
155
        if (isset($this->customCreators[$transport])) {
156
            return call_user_func($this->customCreators[$transport], $config);
157
        }
158
 
621 lars 159
        if (trim($transport ?? '') === '' ||
160
            ! method_exists($this, $method = 'create'.ucfirst(Str::camel($transport)).'Transport')) {
148 lars 161
            throw new InvalidArgumentException("Unsupported mail transport [{$transport}].");
162
        }
163
 
164
        return $this->{$method}($config);
165
    }
166
 
167
    /**
168
     * Create an instance of the Symfony SMTP Transport driver.
169
     *
170
     * @param  array  $config
171
     * @return \Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport
172
     */
173
    protected function createSmtpTransport(array $config)
174
    {
175
        $factory = new EsmtpTransportFactory;
176
 
399 lars 177
        $scheme = $config['scheme'] ?? null;
178
 
179
        if (! $scheme) {
180
            $scheme = ! empty($config['encryption']) && $config['encryption'] === 'tls'
181
                ? (($config['port'] == 465) ? 'smtps' : 'smtp')
182
                : '';
183
        }
184
 
148 lars 185
        $transport = $factory->create(new Dsn(
399 lars 186
            $scheme,
148 lars 187
            $config['host'],
188
            $config['username'] ?? null,
189
            $config['password'] ?? null,
190
            $config['port'] ?? null,
191
            $config
192
        ));
193
 
194
        return $this->configureSmtpTransport($transport, $config);
195
    }
196
 
197
    /**
198
     * Configure the additional SMTP driver options.
199
     *
200
     * @param  \Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport  $transport
201
     * @param  array  $config
202
     * @return \Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport
203
     */
204
    protected function configureSmtpTransport(EsmtpTransport $transport, array $config)
205
    {
206
        $stream = $transport->getStream();
207
 
208
        if ($stream instanceof SocketStream) {
209
            if (isset($config['source_ip'])) {
210
                $stream->setSourceIp($config['source_ip']);
211
            }
212
 
213
            if (isset($config['timeout'])) {
214
                $stream->setTimeout($config['timeout']);
215
            }
216
        }
217
 
218
        return $transport;
219
    }
220
 
221
    /**
222
     * Create an instance of the Symfony Sendmail Transport driver.
223
     *
224
     * @param  array  $config
225
     * @return \Symfony\Component\Mailer\Transport\SendmailTransport
226
     */
227
    protected function createSendmailTransport(array $config)
228
    {
229
        return new SendmailTransport(
230
            $config['path'] ?? $this->app['config']->get('mail.sendmail')
231
        );
232
    }
233
 
234
    /**
235
     * Create an instance of the Symfony Amazon SES Transport driver.
236
     *
237
     * @param  array  $config
150 lars 238
     * @return \Illuminate\Mail\Transport\SesTransport
148 lars 239
     */
240
    protected function createSesTransport(array $config)
241
    {
242
        $config = array_merge(
243
            $this->app['config']->get('services.ses', []),
244
            ['version' => 'latest', 'service' => 'email'],
245
            $config
246
        );
247
 
248
        $config = Arr::except($config, ['transport']);
249
 
250
        return new SesTransport(
251
            new SesClient($this->addSesCredentials($config)),
252
            $config['options'] ?? []
253
        );
254
    }
255
 
256
    /**
621 lars 257
     * Create an instance of the Symfony Amazon SES V2 Transport driver.
258
     *
259
     * @param  array  $config
260
     * @return \Illuminate\Mail\Transport\Se2VwTransport
261
     */
262
    protected function createSesV2Transport(array $config)
263
    {
264
        $config = array_merge(
265
            $this->app['config']->get('services.ses', []),
266
            ['version' => 'latest'],
267
            $config
268
        );
269
 
270
        $config = Arr::except($config, ['transport']);
271
 
272
        return new SesV2Transport(
273
            new SesV2Client($this->addSesCredentials($config)),
274
            $config['options'] ?? []
275
        );
276
    }
277
 
278
    /**
148 lars 279
     * Add the SES credentials to the configuration array.
280
     *
281
     * @param  array  $config
282
     * @return array
283
     */
284
    protected function addSesCredentials(array $config)
285
    {
286
        if (! empty($config['key']) && ! empty($config['secret'])) {
287
            $config['credentials'] = Arr::only($config, ['key', 'secret', 'token']);
288
        }
289
 
290
        return Arr::except($config, ['token']);
291
    }
292
 
293
    /**
294
     * Create an instance of the Symfony Mail Transport driver.
295
     *
296
     * @return \Symfony\Component\Mailer\Transport\SendmailTransport
297
     */
298
    protected function createMailTransport()
299
    {
300
        return new SendmailTransport;
301
    }
302
 
303
    /**
304
     * Create an instance of the Symfony Mailgun Transport driver.
305
     *
306
     * @param  array  $config
399 lars 307
     * @return \Symfony\Component\Mailer\Transport\TransportInterface
148 lars 308
     */
309
    protected function createMailgunTransport(array $config)
310
    {
150 lars 311
        $factory = new MailgunTransportFactory(null, $this->getHttpClient($config));
148 lars 312
 
313
        if (! isset($config['secret'])) {
314
            $config = $this->app['config']->get('services.mailgun', []);
315
        }
316
 
317
        return $factory->create(new Dsn(
318
            'mailgun+'.($config['scheme'] ?? 'https'),
319
            $config['endpoint'] ?? 'default',
320
            $config['secret'],
321
            $config['domain']
322
        ));
323
    }
324
 
325
    /**
326
     * Create an instance of the Symfony Postmark Transport driver.
327
     *
328
     * @param  array  $config
329
     * @return \Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkApiTransport
330
     */
331
    protected function createPostmarkTransport(array $config)
332
    {
150 lars 333
        $factory = new PostmarkTransportFactory(null, $this->getHttpClient($config));
148 lars 334
 
335
        $options = isset($config['message_stream_id'])
336
                    ? ['message_stream' => $config['message_stream_id']]
337
                    : [];
338
 
339
        return $factory->create(new Dsn(
340
            'postmark+api',
341
            'default',
342
            $config['token'] ?? $this->app['config']->get('services.postmark.token'),
343
            null,
344
            null,
345
            $options
346
        ));
347
    }
348
 
349
    /**
350
     * Create an instance of the Symfony Failover Transport driver.
351
     *
352
     * @param  array  $config
353
     * @return \Symfony\Component\Mailer\Transport\FailoverTransport
354
     */
355
    protected function createFailoverTransport(array $config)
356
    {
357
        $transports = [];
358
 
359
        foreach ($config['mailers'] as $name) {
360
            $config = $this->getConfig($name);
361
 
362
            if (is_null($config)) {
363
                throw new InvalidArgumentException("Mailer [{$name}] is not defined.");
364
            }
365
 
366
            // Now, we will check if the "driver" key exists and if it does we will set
367
            // the transport configuration parameter in order to offer compatibility
368
            // with any Laravel <= 6.x application style mail configuration files.
369
            $transports[] = $this->app['config']['mail.driver']
370
                ? $this->createSymfonyTransport(array_merge($config, ['transport' => $name]))
371
                : $this->createSymfonyTransport($config);
372
        }
373
 
374
        return new FailoverTransport($transports);
375
    }
376
 
377
    /**
378
     * Create an instance of the Log Transport driver.
379
     *
380
     * @param  array  $config
381
     * @return \Illuminate\Mail\Transport\LogTransport
382
     */
383
    protected function createLogTransport(array $config)
384
    {
385
        $logger = $this->app->make(LoggerInterface::class);
386
 
387
        if ($logger instanceof LogManager) {
388
            $logger = $logger->channel(
389
                $config['channel'] ?? $this->app['config']->get('mail.log_channel')
390
            );
391
        }
392
 
393
        return new LogTransport($logger);
394
    }
395
 
396
    /**
397
     * Create an instance of the Array Transport Driver.
398
     *
399
     * @return \Illuminate\Mail\Transport\ArrayTransport
400
     */
401
    protected function createArrayTransport()
402
    {
403
        return new ArrayTransport;
404
    }
405
 
406
    /**
150 lars 407
     * Get a configured Symfony HTTP client instance.
408
     *
409
     * @return \Symfony\Contracts\HttpClient\HttpClientInterface|null
410
     */
411
    protected function getHttpClient(array $config)
412
    {
413
        if ($options = ($config['client'] ?? false)) {
414
            $maxHostConnections = Arr::pull($options, 'max_host_connections', 6);
415
            $maxPendingPushes = Arr::pull($options, 'max_pending_pushes', 50);
416
 
417
            return HttpClient::create($options, $maxHostConnections, $maxPendingPushes);
418
        }
419
    }
420
 
421
    /**
148 lars 422
     * Set a global address on the mailer by type.
423
     *
424
     * @param  \Illuminate\Mail\Mailer  $mailer
425
     * @param  array  $config
426
     * @param  string  $type
427
     * @return void
428
     */
429
    protected function setGlobalAddress($mailer, array $config, string $type)
430
    {
431
        $address = Arr::get($config, $type, $this->app['config']['mail.'.$type]);
432
 
433
        if (is_array($address) && isset($address['address'])) {
434
            $mailer->{'always'.Str::studly($type)}($address['address'], $address['name']);
435
        }
436
    }
437
 
438
    /**
439
     * Get the mail connection configuration.
440
     *
441
     * @param  string  $name
442
     * @return array
443
     */
444
    protected function getConfig(string $name)
445
    {
446
        // Here we will check if the "driver" key exists and if it does we will use
447
        // the entire mail configuration file as the "driver" config in order to
448
        // provide "BC" for any Laravel <= 6.x style mail configuration files.
449
        return $this->app['config']['mail.driver']
450
            ? $this->app['config']['mail']
451
            : $this->app['config']["mail.mailers.{$name}"];
452
    }
453
 
454
    /**
455
     * Get the default mail driver name.
456
     *
457
     * @return string
458
     */
459
    public function getDefaultDriver()
460
    {
461
        // Here we will check if the "driver" key exists and if it does we will use
462
        // that as the default driver in order to provide support for old styles
463
        // of the Laravel mail configuration file for backwards compatibility.
464
        return $this->app['config']['mail.driver'] ??
465
            $this->app['config']['mail.default'];
466
    }
467
 
468
    /**
469
     * Set the default mail driver name.
470
     *
471
     * @param  string  $name
472
     * @return void
473
     */
474
    public function setDefaultDriver(string $name)
475
    {
476
        if ($this->app['config']['mail.driver']) {
477
            $this->app['config']['mail.driver'] = $name;
478
        }
479
 
480
        $this->app['config']['mail.default'] = $name;
481
    }
482
 
483
    /**
484
     * Disconnect the given mailer and remove from local cache.
485
     *
486
     * @param  string|null  $name
487
     * @return void
488
     */
489
    public function purge($name = null)
490
    {
491
        $name = $name ?: $this->getDefaultDriver();
492
 
493
        unset($this->mailers[$name]);
494
    }
495
 
496
    /**
497
     * Register a custom transport creator Closure.
498
     *
499
     * @param  string  $driver
500
     * @param  \Closure  $callback
501
     * @return $this
502
     */
503
    public function extend($driver, Closure $callback)
504
    {
505
        $this->customCreators[$driver] = $callback;
506
 
507
        return $this;
508
    }
509
 
510
    /**
511
     * Get the application instance used by the manager.
512
     *
513
     * @return \Illuminate\Contracts\Foundation\Application
514
     */
515
    public function getApplication()
516
    {
517
        return $this->app;
518
    }
519
 
520
    /**
521
     * Set the application instance used by the manager.
522
     *
523
     * @param  \Illuminate\Contracts\Foundation\Application  $app
524
     * @return $this
525
     */
526
    public function setApplication($app)
527
    {
528
        $this->app = $app;
529
 
530
        return $this;
531
    }
532
 
533
    /**
534
     * Forget all of the resolved mailer instances.
535
     *
536
     * @return $this
537
     */
538
    public function forgetMailers()
539
    {
540
        $this->mailers = [];
541
 
542
        return $this;
543
    }
544
 
545
    /**
546
     * Dynamically call the default driver instance.
547
     *
548
     * @param  string  $method
549
     * @param  array  $parameters
550
     * @return mixed
551
     */
552
    public function __call($method, $parameters)
553
    {
554
        return $this->mailer()->$method(...$parameters);
555
    }
556
}