Subversion-Projekte lars-tiefland.laravel_shop

Revision

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 Illuminate\Contracts\Events\Dispatcher;
6
use Illuminate\Contracts\Mail\Mailable as MailableContract;
7
use Illuminate\Contracts\Mail\Mailer as MailerContract;
8
use Illuminate\Contracts\Mail\MailQueue as MailQueueContract;
9
use Illuminate\Contracts\Queue\Factory as QueueContract;
10
use Illuminate\Contracts\Queue\ShouldQueue;
11
use Illuminate\Contracts\Support\Htmlable;
12
use Illuminate\Contracts\View\Factory;
13
use Illuminate\Mail\Events\MessageSending;
14
use Illuminate\Mail\Events\MessageSent;
15
use Illuminate\Support\HtmlString;
16
use Illuminate\Support\Traits\Macroable;
17
use InvalidArgumentException;
18
use Symfony\Component\Mailer\Envelope;
19
use Symfony\Component\Mailer\Transport\TransportInterface;
20
use Symfony\Component\Mime\Email;
21
 
22
class Mailer implements MailerContract, MailQueueContract
23
{
24
    use Macroable;
25
 
26
    /**
27
     * The name that is configured for the mailer.
28
     *
29
     * @var string
30
     */
31
    protected $name;
32
 
33
    /**
34
     * The view factory instance.
35
     *
36
     * @var \Illuminate\Contracts\View\Factory
37
     */
38
    protected $views;
39
 
40
    /**
41
     * The Symfony Transport instance.
42
     *
43
     * @var \Symfony\Component\Mailer\Transport\TransportInterface
44
     */
45
    protected $transport;
46
 
47
    /**
48
     * The event dispatcher instance.
49
     *
50
     * @var \Illuminate\Contracts\Events\Dispatcher|null
51
     */
52
    protected $events;
53
 
54
    /**
55
     * The global from address and name.
56
     *
57
     * @var array
58
     */
59
    protected $from;
60
 
61
    /**
62
     * The global reply-to address and name.
63
     *
64
     * @var array
65
     */
66
    protected $replyTo;
67
 
68
    /**
69
     * The global return path address.
70
     *
71
     * @var array
72
     */
73
    protected $returnPath;
74
 
75
    /**
76
     * The global to address and name.
77
     *
78
     * @var array
79
     */
80
    protected $to;
81
 
82
    /**
83
     * The queue factory implementation.
84
     *
85
     * @var \Illuminate\Contracts\Queue\Factory
86
     */
87
    protected $queue;
88
 
89
    /**
90
     * Create a new Mailer instance.
91
     *
92
     * @param  string  $name
93
     * @param  \Illuminate\Contracts\View\Factory  $views
94
     * @param  \Symfony\Component\Mailer\Transport\TransportInterface  $transport
95
     * @param  \Illuminate\Contracts\Events\Dispatcher|null  $events
96
     * @return void
97
     */
98
    public function __construct(string $name, Factory $views, TransportInterface $transport, Dispatcher $events = null)
99
    {
100
        $this->name = $name;
101
        $this->views = $views;
102
        $this->events = $events;
103
        $this->transport = $transport;
104
    }
105
 
106
    /**
107
     * Set the global from address and name.
108
     *
109
     * @param  string  $address
110
     * @param  string|null  $name
111
     * @return void
112
     */
113
    public function alwaysFrom($address, $name = null)
114
    {
115
        $this->from = compact('address', 'name');
116
    }
117
 
118
    /**
119
     * Set the global reply-to address and name.
120
     *
121
     * @param  string  $address
122
     * @param  string|null  $name
123
     * @return void
124
     */
125
    public function alwaysReplyTo($address, $name = null)
126
    {
127
        $this->replyTo = compact('address', 'name');
128
    }
129
 
130
    /**
131
     * Set the global return path address.
132
     *
133
     * @param  string  $address
134
     * @return void
135
     */
136
    public function alwaysReturnPath($address)
137
    {
138
        $this->returnPath = compact('address');
139
    }
140
 
141
    /**
142
     * Set the global to address and name.
143
     *
144
     * @param  string  $address
145
     * @param  string|null  $name
146
     * @return void
147
     */
148
    public function alwaysTo($address, $name = null)
149
    {
150
        $this->to = compact('address', 'name');
151
    }
152
 
153
    /**
154
     * Begin the process of mailing a mailable class instance.
155
     *
156
     * @param  mixed  $users
157
     * @return \Illuminate\Mail\PendingMail
158
     */
159
    public function to($users)
160
    {
161
        return (new PendingMail($this))->to($users);
162
    }
163
 
164
    /**
165
     * Begin the process of mailing a mailable class instance.
166
     *
167
     * @param  mixed  $users
168
     * @return \Illuminate\Mail\PendingMail
169
     */
170
    public function cc($users)
171
    {
172
        return (new PendingMail($this))->cc($users);
173
    }
174
 
175
    /**
176
     * Begin the process of mailing a mailable class instance.
177
     *
178
     * @param  mixed  $users
179
     * @return \Illuminate\Mail\PendingMail
180
     */
181
    public function bcc($users)
182
    {
183
        return (new PendingMail($this))->bcc($users);
184
    }
185
 
186
    /**
187
     * Send a new message with only an HTML part.
188
     *
189
     * @param  string  $html
190
     * @param  mixed  $callback
191
     * @return \Illuminate\Mail\SentMessage|null
192
     */
193
    public function html($html, $callback)
194
    {
195
        return $this->send(['html' => new HtmlString($html)], [], $callback);
196
    }
197
 
198
    /**
199
     * Send a new message with only a raw text part.
200
     *
201
     * @param  string  $text
202
     * @param  mixed  $callback
203
     * @return \Illuminate\Mail\SentMessage|null
204
     */
205
    public function raw($text, $callback)
206
    {
207
        return $this->send(['raw' => $text], [], $callback);
208
    }
209
 
210
    /**
211
     * Send a new message with only a plain part.
212
     *
213
     * @param  string  $view
214
     * @param  array  $data
215
     * @param  mixed  $callback
216
     * @return \Illuminate\Mail\SentMessage|null
217
     */
218
    public function plain($view, array $data, $callback)
219
    {
220
        return $this->send(['text' => $view], $data, $callback);
221
    }
222
 
223
    /**
224
     * Render the given message as a view.
225
     *
226
     * @param  string|array  $view
227
     * @param  array  $data
228
     * @return string
229
     */
230
    public function render($view, array $data = [])
231
    {
232
        // First we need to parse the view, which could either be a string or an array
233
        // containing both an HTML and plain text versions of the view which should
234
        // be used when sending an e-mail. We will extract both of them out here.
235
        [$view, $plain, $raw] = $this->parseView($view);
236
 
237
        $data['message'] = $this->createMessage();
238
 
239
        return $this->renderView($view ?: $plain, $data);
240
    }
241
 
242
    /**
243
     * Send a new message using a view.
244
     *
245
     * @param  \Illuminate\Contracts\Mail\Mailable|string|array  $view
246
     * @param  array  $data
247
     * @param  \Closure|string|null  $callback
248
     * @return \Illuminate\Mail\SentMessage|null
249
     */
250
    public function send($view, array $data = [], $callback = null)
251
    {
252
        if ($view instanceof MailableContract) {
253
            return $this->sendMailable($view);
254
        }
255
 
256
        // First we need to parse the view, which could either be a string or an array
257
        // containing both an HTML and plain text versions of the view which should
258
        // be used when sending an e-mail. We will extract both of them out here.
259
        [$view, $plain, $raw] = $this->parseView($view);
260
 
261
        $data['message'] = $message = $this->createMessage();
262
 
263
        // Once we have retrieved the view content for the e-mail we will set the body
264
        // of this message using the HTML type, which will provide a simple wrapper
265
        // to creating view based emails that are able to receive arrays of data.
266
        if (! is_null($callback)) {
267
            $callback($message);
268
        }
269
 
270
        $this->addContent($message, $view, $plain, $raw, $data);
271
 
272
        // If a global "to" address has been set, we will set that address on the mail
273
        // message. This is primarily useful during local development in which each
274
        // message should be delivered into a single mail address for inspection.
275
        if (isset($this->to['address'])) {
276
            $this->setGlobalToAndRemoveCcAndBcc($message);
277
        }
278
 
279
        // Next we will determine if the message should be sent. We give the developer
280
        // one final chance to stop this message and then we will send it to all of
281
        // its recipients. We will then fire the sent event for the sent message.
282
        $symfonyMessage = $message->getSymfonyMessage();
283
 
284
        if ($this->shouldSendMessage($symfonyMessage, $data)) {
285
            $symfonySentMessage = $this->sendSymfonyMessage($symfonyMessage);
286
 
287
            if ($symfonySentMessage) {
288
                $sentMessage = new SentMessage($symfonySentMessage);
289
 
290
                $this->dispatchSentEvent($sentMessage, $data);
291
 
292
                return $sentMessage;
293
            }
294
        }
295
    }
296
 
297
    /**
298
     * Send the given mailable.
299
     *
300
     * @param  \Illuminate\Contracts\Mail\Mailable  $mailable
301
     * @return \Illuminate\Mail\SentMessage|null
302
     */
303
    protected function sendMailable(MailableContract $mailable)
304
    {
305
        return $mailable instanceof ShouldQueue
306
                        ? $mailable->mailer($this->name)->queue($this->queue)
307
                        : $mailable->mailer($this->name)->send($this);
308
    }
309
 
310
    /**
311
     * Parse the given view name or array.
312
     *
313
     * @param  string|array  $view
314
     * @return array
315
     *
316
     * @throws \InvalidArgumentException
317
     */
318
    protected function parseView($view)
319
    {
320
        if (is_string($view)) {
321
            return [$view, null, null];
322
        }
323
 
324
        // If the given view is an array with numeric keys, we will just assume that
325
        // both a "pretty" and "plain" view were provided, so we will return this
326
        // array as is, since it should contain both views with numerical keys.
327
        if (is_array($view) && isset($view[0])) {
328
            return [$view[0], $view[1], null];
329
        }
330
 
331
        // If this view is an array but doesn't contain numeric keys, we will assume
332
        // the views are being explicitly specified and will extract them via the
333
        // named keys instead, allowing the developers to use one or the other.
334
        if (is_array($view)) {
335
            return [
336
                $view['html'] ?? null,
337
                $view['text'] ?? null,
338
                $view['raw'] ?? null,
339
            ];
340
        }
341
 
342
        throw new InvalidArgumentException('Invalid view.');
343
    }
344
 
345
    /**
346
     * Add the content to a given message.
347
     *
348
     * @param  \Illuminate\Mail\Message  $message
349
     * @param  string  $view
350
     * @param  string  $plain
351
     * @param  string  $raw
352
     * @param  array  $data
353
     * @return void
354
     */
355
    protected function addContent($message, $view, $plain, $raw, $data)
356
    {
357
        if (isset($view)) {
358
            $message->html($this->renderView($view, $data) ?: ' ');
359
        }
360
 
361
        if (isset($plain)) {
362
            $message->text($this->renderView($plain, $data) ?: ' ');
363
        }
364
 
365
        if (isset($raw)) {
366
            $message->text($raw);
367
        }
368
    }
369
 
370
    /**
371
     * Render the given view.
372
     *
373
     * @param  string  $view
374
     * @param  array  $data
375
     * @return string
376
     */
377
    protected function renderView($view, $data)
378
    {
379
        return $view instanceof Htmlable
380
                        ? $view->toHtml()
381
                        : $this->views->make($view, $data)->render();
382
    }
383
 
384
    /**
385
     * Set the global "to" address on the given message.
386
     *
387
     * @param  \Illuminate\Mail\Message  $message
388
     * @return void
389
     */
390
    protected function setGlobalToAndRemoveCcAndBcc($message)
391
    {
392
        $message->forgetTo();
393
 
394
        $message->to($this->to['address'], $this->to['name'], true);
395
 
396
        $message->forgetCc();
397
        $message->forgetBcc();
398
    }
399
 
400
    /**
401
     * Queue a new e-mail message for sending.
402
     *
403
     * @param  \Illuminate\Contracts\Mail\Mailable|string|array  $view
404
     * @param  string|null  $queue
405
     * @return mixed
406
     *
407
     * @throws \InvalidArgumentException
408
     */
409
    public function queue($view, $queue = null)
410
    {
411
        if (! $view instanceof MailableContract) {
412
            throw new InvalidArgumentException('Only mailables may be queued.');
413
        }
414
 
415
        if (is_string($queue)) {
416
            $view->onQueue($queue);
417
        }
418
 
419
        return $view->mailer($this->name)->queue($this->queue);
420
    }
421
 
422
    /**
423
     * Queue a new e-mail message for sending on the given queue.
424
     *
425
     * @param  string  $queue
426
     * @param  \Illuminate\Contracts\Mail\Mailable  $view
427
     * @return mixed
428
     */
429
    public function onQueue($queue, $view)
430
    {
431
        return $this->queue($view, $queue);
432
    }
433
 
434
    /**
435
     * Queue a new e-mail message for sending on the given queue.
436
     *
437
     * This method didn't match rest of framework's "onQueue" phrasing. Added "onQueue".
438
     *
439
     * @param  string  $queue
440
     * @param  \Illuminate\Contracts\Mail\Mailable  $view
441
     * @return mixed
442
     */
443
    public function queueOn($queue, $view)
444
    {
445
        return $this->onQueue($queue, $view);
446
    }
447
 
448
    /**
449
     * Queue a new e-mail message for sending after (n) seconds.
450
     *
451
     * @param  \DateTimeInterface|\DateInterval|int  $delay
452
     * @param  \Illuminate\Contracts\Mail\Mailable  $view
453
     * @param  string|null  $queue
454
     * @return mixed
455
     *
456
     * @throws \InvalidArgumentException
457
     */
458
    public function later($delay, $view, $queue = null)
459
    {
460
        if (! $view instanceof MailableContract) {
461
            throw new InvalidArgumentException('Only mailables may be queued.');
462
        }
463
 
464
        return $view->mailer($this->name)->later(
465
            $delay, is_null($queue) ? $this->queue : $queue
466
        );
467
    }
468
 
469
    /**
470
     * Queue a new e-mail message for sending after (n) seconds on the given queue.
471
     *
472
     * @param  string  $queue
473
     * @param  \DateTimeInterface|\DateInterval|int  $delay
474
     * @param  \Illuminate\Contracts\Mail\Mailable  $view
475
     * @return mixed
476
     */
477
    public function laterOn($queue, $delay, $view)
478
    {
479
        return $this->later($delay, $view, $queue);
480
    }
481
 
482
    /**
483
     * Create a new message instance.
484
     *
485
     * @return \Illuminate\Mail\Message
486
     */
487
    protected function createMessage()
488
    {
489
        $message = new Message(new Email());
490
 
491
        // If a global from address has been specified we will set it on every message
492
        // instance so the developer does not have to repeat themselves every time
493
        // they create a new message. We'll just go ahead and push this address.
494
        if (! empty($this->from['address'])) {
495
            $message->from($this->from['address'], $this->from['name']);
496
        }
497
 
498
        // When a global reply address was specified we will set this on every message
499
        // instance so the developer does not have to repeat themselves every time
500
        // they create a new message. We will just go ahead and push this address.
501
        if (! empty($this->replyTo['address'])) {
502
            $message->replyTo($this->replyTo['address'], $this->replyTo['name']);
503
        }
504
 
505
        if (! empty($this->returnPath['address'])) {
506
            $message->returnPath($this->returnPath['address']);
507
        }
508
 
509
        return $message;
510
    }
511
 
512
    /**
513
     * Send a Symfony Email instance.
514
     *
515
     * @param  \Symfony\Component\Mime\Email  $message
516
     * @return \Symfony\Component\Mailer\SentMessage|null
517
     */
518
    protected function sendSymfonyMessage(Email $message)
519
    {
520
        try {
521
            return $this->transport->send($message, Envelope::create($message));
522
        } finally {
523
            //
524
        }
525
    }
526
 
527
    /**
528
     * Determines if the email can be sent.
529
     *
530
     * @param  \Symfony\Component\Mime\Email  $message
531
     * @param  array  $data
532
     * @return bool
533
     */
534
    protected function shouldSendMessage($message, $data = [])
535
    {
536
        if (! $this->events) {
537
            return true;
538
        }
539
 
540
        return $this->events->until(
541
            new MessageSending($message, $data)
542
        ) !== false;
543
    }
544
 
545
    /**
546
     * Dispatch the message sent event.
547
     *
548
     * @param  \Illuminate\Mail\SentMessage  $message
549
     * @param  array  $data
550
     * @return void
551
     */
552
    protected function dispatchSentEvent($message, $data = [])
553
    {
554
        if ($this->events) {
555
            $this->events->dispatch(
556
                new MessageSent($message, $data)
557
            );
558
        }
559
    }
560
 
561
    /**
562
     * Get the Symfony Transport instance.
563
     *
564
     * @return \Symfony\Component\Mailer\Transport\TransportInterface
565
     */
566
    public function getSymfonyTransport()
567
    {
568
        return $this->transport;
569
    }
570
 
571
    /**
572
     * Get the view factory instance.
573
     *
574
     * @return \Illuminate\Contracts\View\Factory
575
     */
576
    public function getViewFactory()
577
    {
578
        return $this->views;
579
    }
580
 
581
    /**
582
     * Set the Symfony Transport instance.
583
     *
584
     * @param  \Symfony\Component\Mailer\Transport\TransportInterface  $transport
585
     * @return void
586
     */
587
    public function setSymfonyTransport(TransportInterface $transport)
588
    {
589
        $this->transport = $transport;
590
    }
591
 
592
    /**
593
     * Set the queue manager instance.
594
     *
595
     * @param  \Illuminate\Contracts\Queue\Factory  $queue
596
     * @return $this
597
     */
598
    public function setQueue(QueueContract $queue)
599
    {
600
        $this->queue = $queue;
601
 
602
        return $this;
603
    }
604
}