Passed
Push — master ( 76311e...1fdee9 )
by Daniel
02:08
created

Mail::setMessage()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

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