Passed
Pull Request — master (#87)
by Daniel
03:58
created

Mail::getThreatId()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
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
 *
17
 * @package Dacastro4\LaravelGmail\services
18
 */
19
class Mail extends GmailConnection
20
{
21
22
	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...
23
		Modifiable,
24
		HasParts,
25
		Replyable {
26
		Replyable::__construct as private __rConstruct;
27
		Modifiable::__construct as private __mConstruct;
28
	}
29
30
	/**
31
	 * @var
32
	 */
33
	public $id;
34
35
	/**
36
	 * @var
37
	 */
38
	public $internalDate;
39
40
	/**
41
	 * @var
42
	 */
43
	public $labels;
44
45
	/**
46
	 * @var
47
	 */
48
	public $size;
49
50
	/**
51
	 * @var
52
	 */
53
	public $threadId;
54
55
	/**
56
	 * @var \Google_Service_Gmail_MessagePart
57
	 */
58
	public $payload;
59
60
	public $collectedPayload;
61
62
	/**
63
	 * @var Google_Service_Gmail
64
	 */
65
	public $service;
66
67
	/**
68
	 * @var
69
	 */
70
	private $allParts;
0 ignored issues
show
introduced by
The private property $allParts is not used, and could be removed.
Loading history...
71
72
	/**
73
	 * SingleMessage constructor.
74
	 *
75
	 * @param  \Google_Service_Gmail_Message  $message
76
	 * @param  bool  $preload
77
	 */
78
	public function __construct(\Google_Service_Gmail_Message $message = null, $preload = false)
79
	{
80
81
		$this->service = new Google_Service_Gmail($this);
82
83
		$this->__rConstruct();
84
		$this->__mConstruct();
85
		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

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