Passed
Pull Request — master (#91)
by
unknown
02:29
created

Mail::using()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Dacastro4\LaravelGmail\Services\Message;
4
5
use Carbon\Carbon;
6
use Dacastro4\LaravelGmail\GmailConnection;
7
use Dacastro4\LaravelGmail\Traits\HasDecodableBody;
8
use Dacastro4\LaravelGmail\Traits\HasParts;
9
use Dacastro4\LaravelGmail\Traits\Modifiable;
10
use Dacastro4\LaravelGmail\Traits\Replyable;
11
use Google_Service_Gmail;
12
use Illuminate\Support\Collection;
13
14
/**
15
 * Class SingleMessage
16
 * @package Dacastro4\LaravelGmail\services
17
 */
18
class Mail extends GmailConnection
19
{
20
	use HasDecodableBody,
0 ignored issues
show
Bug introduced by
The trait Dacastro4\LaravelGmail\Traits\Modifiable requires the property $users_messages which is not provided by Dacastro4\LaravelGmail\Services\Message\Mail.
Loading history...
Bug introduced by
The trait Dacastro4\LaravelGmail\Traits\Replyable requires the property $users_messages which is not provided by Dacastro4\LaravelGmail\Services\Message\Mail.
Loading history...
21
		Modifiable,
22
        HasParts,
23
		Replyable {
24
		    Replyable::__construct as private __rConstruct;
25
		    Modifiable::__construct as private __mConstruct;
26
	    }
27
28
	/**
29
	 * @var
30
	 */
31
	public $id;
32
33
	/**
34
	 * @var
35
	 */
36
	public $internalDate;
37
38
	/**
39
	 * @var
40
	 */
41
	public $labels;
42
43
	/**
44
	 * @var
45
	 */
46
	public $size;
47
48
    /**
49
	 * @var
50
	 */
51
	public $threatId;
52
53
    /**
54
	 * @var \Google_Service_Gmail_MessagePart
55
	 */
56
	public $payload;
57
    /**
58
	 * @var Google_Service_Gmail
59
	 */
60
	public $service;
61
    /**
62
     * @var
63
     */
64
	private $allParts;
0 ignored issues
show
introduced by
The private property $allParts is not used, and could be removed.
Loading history...
65
66
	/**
67
	 * SingleMessage constructor.
68
	 *
69
	 * @param  \Google_Service_Gmail_Message  $message
70
	 * @param  bool  $preload
71
	 *
72
	 */
73
	public function __construct(\Google_Service_Gmail_Message $message = null, $preload = false)
74
	{
75
76
	    $this->service = new Google_Service_Gmail($this);
77
78
		$this->__rConstruct();
79
		$this->__mConstruct();
80
		parent::__construct(config());
0 ignored issues
show
Unused Code introduced by
The call to Dacastro4\LaravelGmail\T...difiable::__construct() has too many arguments starting with config(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

80
		parent::/** @scrutinizer ignore-call */ 
81
          __construct(config());

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
81
82
		if (!is_null($message)) {
83
			if ($preload) {
84
				$message = $this->service->users_messages->get('me', $message->getId());
85
			}
86
87
			$this->setMessage($message);
88
89
		}
90
	}
91
92
	protected function setMessage(\Google_Service_Gmail_Message $message)
93
	{
94
		$this->id = $message->getId();
95
		$this->internalDate = $message->getInternalDate();
96
		$this->labels = $message->getLabelIds();
97
		$this->size = $message->getSizeEstimate();
98
		$this->threatId = $message->getThreadId();
99
		$this->payload = $message->getPayload();
100
	}
101
102
	/**
103
	 * Return a UNIX version of the date
104
	 *
105
	 * @return int UNIX date
106
	 */
107
	public function getInternalDate()
108
	{
109
		return $this->internalDate;
110
	}
111
112
	/**
113
	 * Returns the labels of the email
114
	 * Example: INBOX, STARRED, UNREAD
115
	 *
116
	 * @return array
117
	 */
118
	public function getLabels()
119
	{
120
		return $this->labels;
121
	}
122
123
	/**
124
	 * Returns approximate size of the email
125
	 *
126
	 * @return mixed
127
	 */
128
	public function getSize()
129
	{
130
		return $this->size;
131
	}
132
133
	/**
134
	 * Returns threat ID of the email
135
	 *
136
	 * @return string
137
	 */
138
	public function getThreatId()
139
	{
140
		return $this->threatId;
141
	}
142
143
	/**
144
	 * Returns all the headers of the email
145
	 *
146
	 * @return Collection
147
	 */
148
	public function getHeaders()
149
	{
150
		return $this->buildHeaders($this->payload->getHeaders());
151
	}
152
153
	private function buildHeaders($emailHeaders)
154
	{
155
		$headers = [];
156
157
		foreach ($emailHeaders as $header) {
158
			/** @var \Google_Service_Gmail_MessagePartHeader $header */
159
160
			$head = new \stdClass();
161
162
			$head->key = $header->getName();
163
			$head->value = $header->getValue();
164
165
			$headers[] = $head;
166
		}
167
168
		return collect($headers);
169
170
	}
171
172
	/**
173
	 * Returns the subject of the email
174
	 *
175
	 * @return string
176
	 */
177
	public function getSubject()
178
	{
179
		return $this->getHeader('Subject');
180
	}
181
182
	/**
183
	 * Returns array of name and email of each recipient
184
	 *
185
	 * @return array
186
	 */
187
	public function getFrom()
188
	{
189
		$from = $this->getHeader('From');
190
191
		preg_match('/<(.*)>/', $from, $matches);
192
193
		$name = preg_replace('/ <(.*)>/', '', $from);
194
195
		return [
196
			'name' => $name,
197
			'email' => isset($matches[1]) ? $matches[1] : null,
198
		];
199
	}
200
201
	/**
202
	 * Returns email of sender
203
	 *
204
	 * @return string|null
205
	 */
206
	public function getFromEmail()
207
	{
208
		$from = $this->getHeader('From');
209
210
		preg_match('/<(.*)>/', $from, $matches);
211
212
		return isset($matches[1]) ? $matches[1] : null;
213
	}
214
215
	/**
216
	 * Returns name of the sender
217
	 *
218
	 * @return string|null
219
	 */
220
	public function getFromName()
221
	{
222
		$from = $this->getHeader('From');
223
224
		$name = preg_replace('/ <(.*)>/', '', $from);
225
226
		return $name;
227
	}
228
229
	/**
230
	 * Returns array list of recipients
231
	 *
232
	 * @return array
233
	 */
234
	public function getTo()
235
	{
236
		$allTo = $this->getHeader('To');
237
238
		return $this->formatEmailList($allTo);
239
	}
240
241
	/**
242
	 * Returns an array of emails from an string in RFC 822 format
243
	 *
244
	 * @param  string  $emails  email list in RFC 822 format
245
	 *
246
	 * @return array
247
	 */
248
	public function formatEmailList($emails)
249
	{
250
		$all = [];
251
		$explodedEmails = explode(',', $emails);
252
253
		foreach ($explodedEmails as $email) {
254
255
			$item = [];
256
257
			preg_match('/<(.*)>/', $email, $matches);
258
259
			$item['email'] = str_replace(' ', '', isset($matches[1]) ? $matches[1] : $email);
260
261
			$name = preg_replace('/ <(.*)>/', '', $email);
262
263
			if (starts_with($name, ' ')) {
264
				$name = substr($name, 1);
265
			}
266
267
			$item['name'] = str_replace("\"", '', $name ?: null);
268
269
			$all[] = $item;
270
271
		}
272
273
		return $all;
274
	}
275
276
	/**
277
	 * Returns the original date that the email was sent
278
	 *
279
	 * @return Carbon
280
	 */
281
	public function getDate()
282
	{
283
		return Carbon::parse($this->getHeader('Date'));
284
	}
285
286
	/**
287
	 * Returns email of the original recipient
288
	 *
289
	 * @return string
290
	 */
291
	public function getDeliveredTo()
292
	{
293
		return $this->getHeader('Delivered-To');
294
	}
295
296
	/**
297
	 * @return string base64 version of the body
298
	 */
299
	public function getRawPlainTextBody()
300
	{
301
		return $this->getPlainTextBody(true);
302
	}
303
304
	/**
305
	 * @param  bool  $raw
306
	 *
307
	 * @return string
308
	 */
309
	public function getPlainTextBody($raw = false)
310
	{
311
		$content = $this->getBody();
312
313
		return $raw ? $content : $this->getDecodedBody($content);
314
	}
315
316
	/**
317
	 * Returns a specific body part from an email
318
	 *
319
	 * @param  string  $type
320
	 *
321
	 * @return null|string
322
	 */
323
	public function getBody($type = 'text/plain')
324
	{
325
        $parts = $this->getAllParts(collect([$this->payload]));
326
        foreach ($parts as $part)
327
        {
328
            if ($part->mimeType == $type)
329
            {
330
                return $part->body->data;
331
            //if there are no parts in payload, try to get data from body->data
332
            }elseif ($this->payload->body->data)
333
            {
334
                return $this->payload->body->data;
335
            }
336
        }
337
        return null;
338
339
	}
340
341
	/**
342
	 * @return boolean. True if message has at least one attachment.
0 ignored issues
show
Documentation Bug introduced by
The doc comment boolean. at position 0 could not be parsed: Unknown type name 'boolean.' at position 0 in boolean..
Loading history...
343
	 */
344
	public function hasAttachments()
345
	{
346
        $parts = $this->getAllParts(collect([$this->payload]));
347
	    foreach ($parts as $part)
348
        {
349
            if(!empty($part->body->attachmentId))
350
            {
351
                return true;
352
            }
353
        }
354
        return false;
355
	}
356
357
    /**
358
     * @return Integer. Number of attachments of the message.
0 ignored issues
show
Documentation Bug introduced by
The doc comment Integer. at position 0 could not be parsed: Unknown type name 'Integer.' at position 0 in Integer..
Loading history...
359
     */
360
    public function countAttachments()
361
    {
362
        $numberOfAttachments = 0;
363
        $parts = $this->getAllParts(collect([$this->payload]));
364
        foreach ($parts as $part)
365
        {
366
            if(!empty($part->body->attachmentId))
367
            {
368
                $numberOfAttachments++;
369
            }
370
        }
371
        return $numberOfAttachments;
372
    }
373
374
375
	public function getDecodedBody($content)
376
	{
377
		$content = str_replace('_', '/', str_replace('-', '+', $content));
378
379
		return base64_decode($content);
380
	}
381
382
	/**
383
	 * @return string base64 version of the body
384
	 */
385
	public function getRawHtmlBody()
386
	{
387
		return $this->getHtmlBody(true);
388
	}
389
390
	/**
391
	 * @param  bool  $raw
392
	 *
393
	 * @return string
394
	 */
395
	public function getHtmlBody($raw = false)
396
	{
397
		$content = $this->getBody('text/html');
398
399
		return $raw ? $content : $this->getDecodedBody($content);
400
	}
401
402
	/**
403
	 * @return Collection
404
	 * @throws \Exception
405
	 */
406
	public function getAttachmentsWithData()
407
	{
408
		return $this->getAttachments(true);
409
	}
410
411
	/**
412
	 * Returns a collection of attachments
413
	 *
414
	 * @param  bool  $preload  Preload only the attachment's 'data'.
415
     * But does not load the other attachment info like filename, mimetype, etc..
416
     * Maybe would be better to push the data to the other info? So ot would all be together.
417
	 *
418
	 * @return Collection
419
	 * @throws \Exception
420
	 */
421
	public function getAttachments($preload = false)
422
	{
423
		$attachments = new Collection([]);
424
        $parts = $this->getAllParts(collect([$this->payload]));
425
		foreach ($parts as $part)
426
		{
427
            if(!empty($part->body->attachmentId))
428
            {
429
				$attachment = (new Attachment($part->body->attachmentId, $part));
430
				if ($preload) {
431
					$attachment = $attachment->getData();
432
				}
433
				$attachments->push(
434
					$attachment
435
				);
436
			}
437
438
		}
439
440
		return $attachments;
441
442
	}
443
444
	/**
445
	 * Returns ID of the email
446
	 *
447
	 * @return string
448
	 */
449
	public function getId()
450
	{
451
		return $this->id;
452
	}
453
454
455
	/* added by buckfuddey */
456
457
	/**
458
	 * Get's the gmail information from the Mail
459
	 *
460
	 * @return Mail
461
	 */
462
	public function load()
463
	{
464
		$message = $this->service->users_messages->get('me', $this->getId());
465
466
		return new self($message);
467
	}
468
469
	/**
470
	 * Sets the access token in case we wanna use a different token
471
	 *
472
	 * @param  string  $token
473
	 *
474
	 * @return Mail
475
	 */
476
	public function using($token)
477
	{
478
		$this->setToken($token);
479
480
		return $this;
481
	}
482
483
484
    /**
485
     * checks if message has at least one part without itarating through all parts
486
     *
487
     * @return bool
488
     */
489
    public function hasParts()
490
    {
491
        if($this->iterateParts(
492
            collect([$this->payload]), $returnOnFirstFound = true)
493
        ){
494
            return true;
495
        }else{
496
            return false;
497
        }
498
    }
499
500
    /**
501
     * checks if message has no parts withour iterating through all parts
502
     *
503
     * @return bool
504
     */
505
    public function hasNoParts()
506
    {
507
        if ($this->hasParts())
508
        {
509
            return false;
510
        }else{
511
            return true;
512
        }
513
    }
514
515
516
517
518
519
    //unused function? Could be removed?
520
    public function extractFromBody()
521
    {
522
523
        if ($this->hasNoParts()) {
524
            $type = $this->payload->getMimeType();
525
            $body = $this->payload->getBody();
526
            if ($type == 'text/html' || $type == 'text/plain') {
527
                $this->bodyArr[$type] = $this->getDecodedBody($body->getData());
0 ignored issues
show
Bug Best Practice introduced by
The property bodyArr does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
528
            }
529
            if ($body->getAttachmentId()) {
530
                $this->attachmentData[] = [
0 ignored issues
show
Bug Best Practice introduced by
The property attachmentData does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
531
                    'id' => $body->getAttachmentId(),
532
                    'mimeType' => $type,
533
                ];
534
            }
535
        } else {
536
            $parts = $this->payload->getParts();
537
            foreach ($parts as $part) {
538
                if (empty($part->getParts())) {
539
                    $type = $part->getMimeType();
540
                    $body = $part->getBody();
541
                    if ($type == 'text/html' || $type == 'text/plain') {
542
                        if (isset($this->messageBodyArr[$type])) {
543
                            $this->messageBodyArr[$type] .= $this->getDecodedBody($body->getData());
544
                        } else {
545
                            $this->messageBodyArr[$type] = $this->getDecodedBody($body->getData());
0 ignored issues
show
Bug Best Practice introduced by
The property messageBodyArr does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
546
                        }
547
                    }
548
549
                    if ($body->getAttachmentId()) {
550
                        $this->attachmentData[] = [
551
                            'id' => $body->getAttachmentId(),
552
                            'fileName' => $part->getFilename(),
553
                            'mimeType' => $type,
554
                        ];
555
                    }
556
                } else {
557
                    $subParts = $part->getParts();
558
                    $this->traverseData($subParts);
559
                }
560
            }
561
        }
562
    }
563
564
565
    //unused function? Could be removed?
566
    public function traverseData($parts)
567
    {
568
        foreach ($parts as $part) {
569
            if (empty($part->getParts())) {
570
                $type = $part->getMimeType();
571
                $body = $part->getBody();
572
                if ($type == 'text/html' || $type == 'text/plain') {
573
                    if (isset($this->messageBodyArr[$type])) {
574
                        $this->messageBodyArr[$type] .= $this->getDecodedBody($body->getData());
575
                    } else {
576
                        $this->messageBodyArr[$type] = $this->getDecodedBody($body->getData());
0 ignored issues
show
Bug Best Practice introduced by
The property messageBodyArr does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
577
                    }
578
                }
579
580
                if ($body->getAttachmentId()) {
581
                    $this->attachmentData[] = [
0 ignored issues
show
Bug Best Practice introduced by
The property attachmentData does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
582
                        'id' => $body->getAttachmentId(),
583
                        'fileName' => $part->getFilename(),
584
                        'mimeType' => $type,
585
                    ];
586
587
                }
588
            } else {
589
                $subParts = $part->getParts();
590
                $this->traverseData($subParts);
591
            }
592
        }
593
    }
594
}
595