Passed
Pull Request — master (#80)
by
unknown
01:42
created

Mail::load()   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 0
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\Modifiable;
9
use Dacastro4\LaravelGmail\Traits\Replyable;
10
use Google_Service_Gmail;
11
use Illuminate\Support\Collection;
12
13
/**
14
 * Class SingleMessage
15
 * @package Dacastro4\LaravelGmail\services
16
 */
17
class Mail extends GmailConnection
18
{
19
	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...
20
		Modifiable,
21
		Replyable {
22
		Replyable::__construct as private __rConstruct;
23
		Modifiable::__construct as private __mConstruct;
24
	}
25
26
	/**
27
	 * @var
28
	 */
29
	public $id;
30
31
	/**
32
	 * @var
33
	 */
34
	public $internalDate;
35
36
	/**
37
	 * @var
38
	 */
39
	public $labels;
40
41
	/**
42
	 * @var
43
	 */
44
	public $size;
45
46
	/**
47
	 * @var
48
	 */
49
	public $threadId;
50
51
	/**
52
	 * @var \Google_Service_Gmail_MessagePart
53
	 */
54
	public $payload;
55
56
	/**
57
	 * @var Google_Service_Gmail
58
	 */
59
	public $service;
60
61
	/**
62
	 * SingleMessage constructor.
63
	 *
64
	 * @param  \Google_Service_Gmail_Message  $message
65
	 * @param  bool  $preload
66
	 *
67
	 */
68
	public function __construct(\Google_Service_Gmail_Message $message = null, $preload = false)
69
	{
70
71
		$this->service = new Google_Service_Gmail($this);
72
73
		$this->__rConstruct();
74
		$this->__mConstruct();
75
		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

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