Passed
Pull Request — master (#258)
by
unknown
03:34
created

Mail::getBcc()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
cc 1
eloc 2
c 2
b 1
f 0
nc 1
nop 0
dl 0
loc 5
rs 10
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 Google_Service_Gmail_MessagePart;
13
use Illuminate\Support\Collection;
14
use Illuminate\Support\Str;
15
16
/**
17
 * Class SingleMessage
18
 *
19
 * @package Dacastro4\LaravelGmail\services
20
 */
21
class Mail extends GmailConnection
22
{
23
24
	use HasDecodableBody,
0 ignored issues
show
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...
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...
25
		Modifiable,
26
		HasParts,
27
		Replyable {
28
		Replyable::__construct as private __rConstruct;
29
		Modifiable::__construct as private __mConstruct;
30
	}
31
32
	/**
33
	 * @var
34
	 */
35
	public $id;
36
37
	/**
38
	 * @var
39
	 */
40
	public $userId;
41
42
	/**
43
	 * @var
44
	 */
45
	public $internalDate;
46
47
	/**
48
	 * @var
49
	 */
50
	public $labels;
51
52
	/**
53
	 * @var
54
	 */
55
	public $size;
56
57
	/**
58
	 * @var
59
	 */
60
	public $threadId;
61
62
	/**
63
	 * @var
64
	 */
65
	public $historyId;
66
67
	/**
68
	 * @var \Google_Service_Gmail_MessagePart
69
	 */
70
	public $payload;
71
72
	public $parts;
73
74
	/**
75
	 * @var
76
	 */
77
	public $snippet;
78
79
	/**
80
	 * @var Google_Service_Gmail
81
	 */
82
	public $service;
83
84
	/**
85
	 * SingleMessage constructor.
86
	 *
87
	 * @param \Google_Service_Gmail_Message $message
88
	 * @param bool $preload
89
	 * @param  int 	$userId
90
	 */
91
	public function __construct(\Google_Service_Gmail_Message $message = null, $preload = false, $userId = null)
92
	{
93
		$this->service = new Google_Service_Gmail($this);
94
95
		$this->__rConstruct();
96
		$this->__mConstruct();
97
		parent::__construct(config(), $userId);
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

97
		parent::/** @scrutinizer ignore-call */ 
98
          __construct(config(), $userId);

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...
98
99
		if (!is_null($message)) {
100
			if ($preload) {
101
				$message = $this->service->users_messages->get('me', $message->getId());
102
			}
103
104
			$this->setUserId($userId);
105
106
			$this->setMessage($message);
107
108
			if ($preload) {
109
				$this->setMetadata();
110
			}
111
		}
112
	}
113
114
	/**
115
	 * Set user Id
116
	 *
117
	 * @param int $userId
118
	 */
119
	protected function setUserId($userId)
120
	{
121
		$this->userId = $userId;
122
	}
123
124
	/**
125
	 * Sets data from mail
126
	 *
127
	 * @param \Google_Service_Gmail_Message $message
128
	 */
129
	protected function setMessage(\Google_Service_Gmail_Message $message)
130
	{
131
		$this->id = $message->getId();
132
		$this->internalDate = $message->getInternalDate();
133
		$this->labels = $message->getLabelIds();
134
		$this->size = $message->getSizeEstimate();
135
		$this->threadId = $message->getThreadId();
136
		$this->historyId = $message->getHistoryId();
137
		$this->payload = $message->getPayload();
138
		$this->snippet = $message->getSnippet();
139
		if ($this->payload) {
140
			$this->parts = collect($this->payload->getParts());
141
		}
142
	}
143
144
	/**
145
	 * Sets the metadata from Mail when preloaded
146
	 */
147
	protected function setMetadata()
148
	{
149
		$this->to = $this->getTo();
150
		$from = $this->getFrom();
151
		$this->from = isset($from['email']) ? $from['email'] : null;
152
		$this->nameFrom = isset($from['email']) ? $from['email'] : null;
153
154
		$this->subject = $this->getSubject();
155
	}
156
157
	/**
158
	 * Return a UNIX version of the date
159
	 *
160
	 * @return int UNIX date
161
	 */
162
	public function getInternalDate()
163
	{
164
		return $this->internalDate;
165
	}
166
167
	/**
168
	 * Returns the labels of the email
169
	 * Example: INBOX, STARRED, UNREAD
170
	 *
171
	 * @return array
172
	 */
173
	public function getLabels()
174
	{
175
		return $this->labels;
176
	}
177
178
	/**
179
	 * Returns approximate size of the email
180
	 *
181
	 * @return mixed
182
	 */
183
	public function getSize()
184
	{
185
		return $this->size;
186
	}
187
188
	/**
189
	 * Returns thread ID of the email
190
	 *
191
	 * @return string
192
	 */
193
	public function getThreadId()
194
	{
195
		return $this->threadId;
196
	}
197
198
	/**
199
	 * Returns history ID of the email
200
	 *
201
	 * @return string
202
	 */
203
	public function getHistoryId()
204
	{
205
		return $this->historyId;
206
	}
207
208
	/**
209
	 * Returns all the headers of the email
210
	 *
211
	 * @return Collection
212
	 */
213
	public function getHeaders()
214
	{
215
		return $this->buildHeaders($this->payload->getHeaders());
216
	}
217
218
	/**
219
	 * Returns the subject of the email
220
	 *
221
	 * @return string
222
	 */
223
	public function getSubject()
224
	{
225
		return $this->getHeader('Subject');
226
	}
227
228
	/**
229
	 * Returns the subject of the email
230
	 *
231
	 * @return array|string
232
	 */
233
	public function getReplyTo()
234
	{
235
		$replyTo = $this->getHeader('Reply-To');
236
237
		return $this->getFrom($replyTo ? $replyTo : $this->getHeader('From'));
238
	}
239
240
	/**
241
	 * Returns the Snippet from the email
242
	 *
243
	 * @return string
244
	 */
245
	public function getSnippet()
246
	{
247
248
249
		return $this->snippet;
250
	}
251
252
	/**
253
	 * Returns array of name and email of each recipient
254
	 *
255
	 * @param string|null $email
256
	 * @return array
257
	 */
258
	public function getFrom($email = null)
259
	{
260
		$from = $email ? $email : $this->getHeader('From');
261
262
		preg_match('/<(.*)>/', $from, $matches);
0 ignored issues
show
Bug introduced by
It seems like $from can also be of type null; however, parameter $subject of preg_match() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

262
		preg_match('/<(.*)>/', /** @scrutinizer ignore-type */ $from, $matches);
Loading history...
263
264
		$name = preg_replace('/ <(.*)>/', '', $from);
265
266
		return [
267
			'name'  => $name,
268
			'email' => isset($matches[1]) ? $matches[1] : null,
269
		];
270
	}
271
272
	/**
273
	 * Returns email of sender
274
	 *
275
	 * @return string|null
276
	 */
277
	public function getFromEmail()
278
	{
279
		$from = $this->getHeader('From');
280
281
		if (filter_var($from, FILTER_VALIDATE_EMAIL)) {
282
			return $from;
283
		}
284
285
		preg_match('/<(.*)>/', $from, $matches);
0 ignored issues
show
Bug introduced by
It seems like $from can also be of type null; however, parameter $subject of preg_match() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

285
		preg_match('/<(.*)>/', /** @scrutinizer ignore-type */ $from, $matches);
Loading history...
286
287
		return isset($matches[1]) ? $matches[1] : null;
288
	}
289
290
	/**
291
	 * Returns name of the sender
292
	 *
293
	 * @return string|null
294
	 */
295
	public function getFromName()
296
	{
297
		$from = $this->getHeader('From');
298
299
		$name = preg_replace('/ <(.*)>/', '', $from);
300
301
		return $name;
302
	}
303
304
	/**
305
	 * Returns array list of recipients
306
	 *
307
	 * @return array
308
	 */
309
	public function getTo()
310
	{
311
		$allTo = $this->getHeader('To');
312
313
		return $this->formatEmailList($allTo);
314
	}
315
316
	/**
317
	 * Returns array list of cc recipients
318
	 *
319
	 * @return array
320
	 */
321
	public function getCc()
322
	{
323
		$allCc = $this->getHeader('Cc');
324
325
		return $this->formatEmailList($allCc);
326
	}
327
328
	/**
329
	 * Returns array list of bcc recipients
330
	 *
331
	 * @return array
332
	 */
333
	public function getBcc()
334
	{
335
		$allBcc = $this->getHeader('Bcc');
336
337
		return $this->formatEmailList($allBcc);
338
	}
339
340
	/**
341
	 * Returns an array of emails from an string in RFC 822 format
342
	 *
343
	 * @param string $emails email list in RFC 822 format
344
	 *
345
	 * @return array
346
	 */
347
	public function formatEmailList($emails)
348
	{
349
		$all = [];
350
		$explodedEmails = explode(',', $emails);
351
352
		foreach ($explodedEmails as $email) {
353
354
			$item = [];
355
356
			preg_match('/<(.*)>/', $email, $matches);
357
358
			$item['email'] = str_replace(' ', '', isset($matches[1]) ? $matches[1] : $email);
359
360
			$name = preg_replace('/ <(.*)>/', '', $email);
361
362
			if (Str::startsWith($name, ' ')) {
363
				$name = substr($name, 1);
364
			}
365
366
			$item['name'] = str_replace("\"", '', $name ?: null);
367
368
			$all[] = $item;
369
		}
370
371
		return $all;
372
	}
373
374
	/**
375
	 * Returns the original date that the email was sent
376
	 *
377
	 * @return Carbon
378
	 */
379
	public function getDate()
380
	{
381
		return Carbon::parse($this->getHeader('Date'));
382
	}
383
384
	/**
385
	 * Returns email of the original recipient
386
	 *
387
	 * @return string
388
	 */
389
	public function getDeliveredTo()
390
	{
391
		return $this->getHeader('Delivered-To');
392
	}
393
394
	/**
395
	 * Base64 version of the body
396
	 *
397
	 * @return string
398
	 */
399
	public function getRawPlainTextBody()
400
	{
401
		return $this->getPlainTextBody(true);
402
	}
403
404
	/**
405
	 * @param bool $raw
406
	 *
407
	 * @return string
408
	 */
409
	public function getPlainTextBody($raw = false)
410
	{
411
		$content = $this->getBody();
412
413
		return $raw ? $content : $this->getDecodedBody($content);
414
	}
415
416
	/**
417
	 * Returns a specific body part from an email
418
	 *
419
	 * @param string $type
420
	 *
421
	 * @return null|string
422
	 * @throws \Exception
423
	 */
424
	public function getBody($type = 'text/plain')
425
	{
426
		$parts = $this->getAllParts($this->parts);
427
		try {
428
			if (!$parts->isEmpty()) {
429
				foreach ($parts as $part) {
430
					if ($part->mimeType == $type) {
431
						return $part->body->data;
432
						//if there are no parts in payload, try to get data from body->data
433
					} elseif ($this->payload->body->data) {
434
						return $this->payload->body->data;
435
					}
436
				}
437
			} else {
438
				return $this->payload->body->data;
439
			}
440
		} catch (\Exception $exception) {
441
			throw new \Exception("Preload or load the single message before getting the body.");
442
		}
443
444
		return null;
445
	}
446
447
	/**
448
	 * True if message has at least one attachment.
449
	 *
450
	 * @return boolean
451
	 */
452
	public function hasAttachments()
453
	{
454
		$parts = $this->getAllParts($this->parts);
455
		$has = false;
456
457
		/** @var Google_Service_Gmail_MessagePart $part */
458
		foreach ($parts as $part) {
459
			if (!empty($part->body->attachmentId) && $part->getFilename() != null && strlen($part->getFilename()) > 0) {
460
				$has = true;
461
				break;
462
			}
463
		}
464
465
		return $has;
466
	}
467
468
	/**
469
	 * Number of attachments of the message.
470
	 *
471
	 * @return int
472
	 */
473
	public function countAttachments()
474
	{
475
		$numberOfAttachments = 0;
476
		$parts = $this->getAllParts($this->parts);
477
478
		foreach ($parts as $part) {
479
			if (!empty($part->body->attachmentId)) {
480
				$numberOfAttachments++;
481
			}
482
		}
483
484
		return $numberOfAttachments;
485
	}
486
487
	/**
488
	 * Decodes the body from gmail to make it readable
489
	 *
490
	 * @param $content
491
	 * @return bool|string
492
	 */
493
	public function getDecodedBody($content)
494
	{
495
		$content = str_replace('_', '/', str_replace('-', '+', $content));
496
497
		return base64_decode($content);
498
	}
499
500
	/**
501
	 * @return string base64 version of the body
502
	 */
503
	public function getRawHtmlBody()
504
	{
505
		return $this->getHtmlBody(true);
506
	}
507
508
	/**
509
	 * Gets the HTML body
510
	 *
511
	 * @param bool $raw
512
	 *
513
	 * @return string
514
	 */
515
	public function getHtmlBody($raw = false)
516
	{
517
		$content = $this->getBody('text/html');
518
519
		return $raw ? $content : $this->getDecodedBody($content);
520
	}
521
522
	/**
523
	 * Get a collection of attachments with full information
524
	 *
525
	 * @return Collection
526
	 * @throws \Exception
527
	 */
528
	public function getAttachmentsWithData()
529
	{
530
		return $this->getAttachments(true);
531
	}
532
533
	/**
534
	 * Returns a collection of attachments
535
	 *
536
	 * @param bool $preload Preload only the attachment's 'data'.
537
	 * But does not load the other attachment info like filename, mimetype, etc..
538
	 *
539
	 * @return Collection
540
	 * @throws \Exception
541
	 */
542
	public function getAttachments($preload = false)
0 ignored issues
show
Unused Code introduced by
The parameter $preload is not used and could be removed. ( Ignorable by Annotation )

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

542
	public function getAttachments(/** @scrutinizer ignore-unused */ $preload = false)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
543
	{
544
		$attachments = new Collection();
545
		$parts = $this->getAllParts($this->parts);
546
547
		foreach ($parts as $part) {
548
			if (!empty($part->body->attachmentId)) {
549
				$attachment = (new Attachment($part->body->attachmentId, $part, $this->userId));
550
				// if ($preload) {
551
				// 	$attachment = $attachment->getData();
552
				// }
553
				$attachments->push($attachment);
554
			}
555
		}
556
557
		return $attachments;
558
	}
559
560
	/**
561
	 * Returns ID of the email
562
	 *
563
	 * @return string
564
	 */
565
	public function getId()
566
	{
567
		return $this->id;
568
	}
569
570
	/**
571
	 * Gets the user email from the config file
572
	 *
573
	 * @return mixed|null
574
	 */
575
	public function getUser()
576
	{
577
		return $this->config('email');
578
	}
579
580
	/**
581
	 * Get's the gmail information from the Mail
582
	 *
583
	 * @return Mail
584
	 */
585
	public function load()
586
	{
587
		$message = $this->service->users_messages->get('me', $this->getId());
588
589
		return new self($message);
590
	}
591
592
	/**
593
	 * Sets the access token in case we wanna use a different token
594
	 *
595
	 * @param string $token
596
	 *
597
	 * @return Mail
598
	 */
599
	public function using($token)
600
	{
601
		$this->setToken($token);
602
603
		return $this;
604
	}
605
606
	/**
607
	 * checks if message has at least one part without iterating through all parts
608
	 *
609
	 * @return bool
610
	 */
611
	public function hasParts()
612
	{
613
		return !!$this->iterateParts($this->parts, $returnOnFirstFound = true);
614
	}
615
616
	/**
617
	 * Gets all the headers from an email and returns a collections
618
	 *
619
	 * @param $emailHeaders
620
	 * @return Collection
621
	 */
622
	private function buildHeaders($emailHeaders)
623
	{
624
		$headers = [];
625
626
		foreach ($emailHeaders as $header) {
627
			/** @var \Google_Service_Gmail_MessagePartHeader $header */
628
629
			$head = new \stdClass();
630
631
			$head->key = $header->getName();
632
			$head->value = $header->getValue();
633
634
			$headers[] = $head;
635
		}
636
637
		return collect($headers);
638
	}
639
}
640