Subversion-Projekte lars-tiefland.laravel_shop

Revision

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