Subversion-Projekte lars-tiefland.laravel_shop

Revision

Revision 148 | 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 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
 
621 lars 256
        $data['mailer'] = $this->name;
257
 
148 lars 258
        // First we need to parse the view, which could either be a string or an array
259
        // containing both an HTML and plain text versions of the view which should
260
        // be used when sending an e-mail. We will extract both of them out here.
261
        [$view, $plain, $raw] = $this->parseView($view);
262
 
263
        $data['message'] = $message = $this->createMessage();
264
 
265
        // Once we have retrieved the view content for the e-mail we will set the body
266
        // of this message using the HTML type, which will provide a simple wrapper
267
        // to creating view based emails that are able to receive arrays of data.
268
        if (! is_null($callback)) {
269
            $callback($message);
270
        }
271
 
272
        $this->addContent($message, $view, $plain, $raw, $data);
273
 
274
        // If a global "to" address has been set, we will set that address on the mail
275
        // message. This is primarily useful during local development in which each
276
        // message should be delivered into a single mail address for inspection.
277
        if (isset($this->to['address'])) {
278
            $this->setGlobalToAndRemoveCcAndBcc($message);
279
        }
280
 
281
        // Next we will determine if the message should be sent. We give the developer
282
        // one final chance to stop this message and then we will send it to all of
283
        // its recipients. We will then fire the sent event for the sent message.
284
        $symfonyMessage = $message->getSymfonyMessage();
285
 
286
        if ($this->shouldSendMessage($symfonyMessage, $data)) {
287
            $symfonySentMessage = $this->sendSymfonyMessage($symfonyMessage);
288
 
289
            if ($symfonySentMessage) {
290
                $sentMessage = new SentMessage($symfonySentMessage);
291
 
292
                $this->dispatchSentEvent($sentMessage, $data);
293
 
294
                return $sentMessage;
295
            }
296
        }
297
    }
298
 
299
    /**
300
     * Send the given mailable.
301
     *
302
     * @param  \Illuminate\Contracts\Mail\Mailable  $mailable
303
     * @return \Illuminate\Mail\SentMessage|null
304
     */
305
    protected function sendMailable(MailableContract $mailable)
306
    {
307
        return $mailable instanceof ShouldQueue
308
                        ? $mailable->mailer($this->name)->queue($this->queue)
309
                        : $mailable->mailer($this->name)->send($this);
310
    }
311
 
312
    /**
313
     * Parse the given view name or array.
314
     *
315
     * @param  string|array  $view
316
     * @return array
317
     *
318
     * @throws \InvalidArgumentException
319
     */
320
    protected function parseView($view)
321
    {
322
        if (is_string($view)) {
323
            return [$view, null, null];
324
        }
325
 
326
        // If the given view is an array with numeric keys, we will just assume that
327
        // both a "pretty" and "plain" view were provided, so we will return this
328
        // array as is, since it should contain both views with numerical keys.
329
        if (is_array($view) && isset($view[0])) {
330
            return [$view[0], $view[1], null];
331
        }
332
 
333
        // If this view is an array but doesn't contain numeric keys, we will assume
334
        // the views are being explicitly specified and will extract them via the
335
        // named keys instead, allowing the developers to use one or the other.
336
        if (is_array($view)) {
337
            return [
338
                $view['html'] ?? null,
339
                $view['text'] ?? null,
340
                $view['raw'] ?? null,
341
            ];
342
        }
343
 
344
        throw new InvalidArgumentException('Invalid view.');
345
    }
346
 
347
    /**
348
     * Add the content to a given message.
349
     *
350
     * @param  \Illuminate\Mail\Message  $message
351
     * @param  string  $view
352
     * @param  string  $plain
353
     * @param  string  $raw
354
     * @param  array  $data
355
     * @return void
356
     */
357
    protected function addContent($message, $view, $plain, $raw, $data)
358
    {
359
        if (isset($view)) {
360
            $message->html($this->renderView($view, $data) ?: ' ');
361
        }
362
 
363
        if (isset($plain)) {
364
            $message->text($this->renderView($plain, $data) ?: ' ');
365
        }
366
 
367
        if (isset($raw)) {
368
            $message->text($raw);
369
        }
370
    }
371
 
372
    /**
373
     * Render the given view.
374
     *
375
     * @param  string  $view
376
     * @param  array  $data
377
     * @return string
378
     */
379
    protected function renderView($view, $data)
380
    {
381
        return $view instanceof Htmlable
382
                        ? $view->toHtml()
383
                        : $this->views->make($view, $data)->render();
384
    }
385
 
386
    /**
387
     * Set the global "to" address on the given message.
388
     *
389
     * @param  \Illuminate\Mail\Message  $message
390
     * @return void
391
     */
392
    protected function setGlobalToAndRemoveCcAndBcc($message)
393
    {
394
        $message->forgetTo();
395
 
396
        $message->to($this->to['address'], $this->to['name'], true);
397
 
398
        $message->forgetCc();
399
        $message->forgetBcc();
400
    }
401
 
402
    /**
403
     * Queue a new e-mail message for sending.
404
     *
405
     * @param  \Illuminate\Contracts\Mail\Mailable|string|array  $view
406
     * @param  string|null  $queue
407
     * @return mixed
408
     *
409
     * @throws \InvalidArgumentException
410
     */
411
    public function queue($view, $queue = null)
412
    {
413
        if (! $view instanceof MailableContract) {
414
            throw new InvalidArgumentException('Only mailables may be queued.');
415
        }
416
 
417
        if (is_string($queue)) {
418
            $view->onQueue($queue);
419
        }
420
 
421
        return $view->mailer($this->name)->queue($this->queue);
422
    }
423
 
424
    /**
425
     * Queue a new e-mail message for sending on the given queue.
426
     *
427
     * @param  string  $queue
428
     * @param  \Illuminate\Contracts\Mail\Mailable  $view
429
     * @return mixed
430
     */
431
    public function onQueue($queue, $view)
432
    {
433
        return $this->queue($view, $queue);
434
    }
435
 
436
    /**
437
     * Queue a new e-mail message for sending on the given queue.
438
     *
439
     * This method didn't match rest of framework's "onQueue" phrasing. Added "onQueue".
440
     *
441
     * @param  string  $queue
442
     * @param  \Illuminate\Contracts\Mail\Mailable  $view
443
     * @return mixed
444
     */
445
    public function queueOn($queue, $view)
446
    {
447
        return $this->onQueue($queue, $view);
448
    }
449
 
450
    /**
451
     * Queue a new e-mail message for sending after (n) seconds.
452
     *
453
     * @param  \DateTimeInterface|\DateInterval|int  $delay
454
     * @param  \Illuminate\Contracts\Mail\Mailable  $view
455
     * @param  string|null  $queue
456
     * @return mixed
457
     *
458
     * @throws \InvalidArgumentException
459
     */
460
    public function later($delay, $view, $queue = null)
461
    {
462
        if (! $view instanceof MailableContract) {
463
            throw new InvalidArgumentException('Only mailables may be queued.');
464
        }
465
 
466
        return $view->mailer($this->name)->later(
467
            $delay, is_null($queue) ? $this->queue : $queue
468
        );
469
    }
470
 
471
    /**
472
     * Queue a new e-mail message for sending after (n) seconds on the given queue.
473
     *
474
     * @param  string  $queue
475
     * @param  \DateTimeInterface|\DateInterval|int  $delay
476
     * @param  \Illuminate\Contracts\Mail\Mailable  $view
477
     * @return mixed
478
     */
479
    public function laterOn($queue, $delay, $view)
480
    {
481
        return $this->later($delay, $view, $queue);
482
    }
483
 
484
    /**
485
     * Create a new message instance.
486
     *
487
     * @return \Illuminate\Mail\Message
488
     */
489
    protected function createMessage()
490
    {
491
        $message = new Message(new Email());
492
 
493
        // If a global from address has been specified we will set it on every message
494
        // instance so the developer does not have to repeat themselves every time
495
        // they create a new message. We'll just go ahead and push this address.
496
        if (! empty($this->from['address'])) {
497
            $message->from($this->from['address'], $this->from['name']);
498
        }
499
 
500
        // When a global reply address was specified we will set this on every message
501
        // instance so the developer does not have to repeat themselves every time
502
        // they create a new message. We will just go ahead and push this address.
503
        if (! empty($this->replyTo['address'])) {
504
            $message->replyTo($this->replyTo['address'], $this->replyTo['name']);
505
        }
506
 
507
        if (! empty($this->returnPath['address'])) {
508
            $message->returnPath($this->returnPath['address']);
509
        }
510
 
511
        return $message;
512
    }
513
 
514
    /**
515
     * Send a Symfony Email instance.
516
     *
517
     * @param  \Symfony\Component\Mime\Email  $message
518
     * @return \Symfony\Component\Mailer\SentMessage|null
519
     */
520
    protected function sendSymfonyMessage(Email $message)
521
    {
522
        try {
523
            return $this->transport->send($message, Envelope::create($message));
524
        } finally {
525
            //
526
        }
527
    }
528
 
529
    /**
530
     * Determines if the email can be sent.
531
     *
532
     * @param  \Symfony\Component\Mime\Email  $message
533
     * @param  array  $data
534
     * @return bool
535
     */
536
    protected function shouldSendMessage($message, $data = [])
537
    {
538
        if (! $this->events) {
539
            return true;
540
        }
541
 
542
        return $this->events->until(
543
            new MessageSending($message, $data)
544
        ) !== false;
545
    }
546
 
547
    /**
548
     * Dispatch the message sent event.
549
     *
550
     * @param  \Illuminate\Mail\SentMessage  $message
551
     * @param  array  $data
552
     * @return void
553
     */
554
    protected function dispatchSentEvent($message, $data = [])
555
    {
556
        if ($this->events) {
557
            $this->events->dispatch(
558
                new MessageSent($message, $data)
559
            );
560
        }
561
    }
562
 
563
    /**
564
     * Get the Symfony Transport instance.
565
     *
566
     * @return \Symfony\Component\Mailer\Transport\TransportInterface
567
     */
568
    public function getSymfonyTransport()
569
    {
570
        return $this->transport;
571
    }
572
 
573
    /**
574
     * Get the view factory instance.
575
     *
576
     * @return \Illuminate\Contracts\View\Factory
577
     */
578
    public function getViewFactory()
579
    {
580
        return $this->views;
581
    }
582
 
583
    /**
584
     * Set the Symfony Transport instance.
585
     *
586
     * @param  \Symfony\Component\Mailer\Transport\TransportInterface  $transport
587
     * @return void
588
     */
589
    public function setSymfonyTransport(TransportInterface $transport)
590
    {
591
        $this->transport = $transport;
592
    }
593
 
594
    /**
595
     * Set the queue manager instance.
596
     *
597
     * @param  \Illuminate\Contracts\Queue\Factory  $queue
598
     * @return $this
599
     */
600
    public function setQueue(QueueContract $queue)
601
    {
602
        $this->queue = $queue;
603
 
604
        return $this;
605
    }
606
}