Passed
Push — master ( a6bb4f...a4381e )
by Malte
03:46
created

Message::fetchStructure()   D

Complexity

Conditions 18
Paths 16

Size

Total Lines 75
Code Lines 41

Duplication

Lines 0
Ratio 0 %

Importance

Changes 12
Bugs 1 Features 1
Metric Value
cc 18
eloc 41
c 12
b 1
f 1
nc 16
nop 2
dl 0
loc 75
rs 4.8666

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/*
3
* File:     Message.php
4
* Category: -
5
* Author:   M. Goldenbaum
6
* Created:  19.01.17 22:21
7
* Updated:  -
8
*
9
* Description:
10
*  -
11
*/
12
13
namespace Webklex\IMAP;
14
15
use Carbon\Carbon;
16
use Webklex\IMAP\Exceptions\InvalidMessageDateException;
17
use Webklex\IMAP\Exceptions\MaskNotFoundException;
18
use Webklex\IMAP\Exceptions\MethodNotFoundException;
19
use Webklex\IMAP\Support\AttachmentCollection;
20
use Webklex\IMAP\Support\FlagCollection;
21
use Webklex\IMAP\Support\Masks\MessageMask;
22
23
/**
24
 * Class Message
25
 *
26
 * @package Webklex\IMAP
27
 *
28
 * @property integer msglist
29
 * @property integer uid
30
 * @property integer msgn
31
 * @property integer priority
32
 * @property string subject
33
 * @property string message_id
34
 * @property string message_no
35
 * @property string references
36
 * @property carbon date
37
 * @property array from
38
 * @property array to
39
 * @property array cc
40
 * @property array bcc
41
 * @property array reply_to
42
 * @property array in_reply_to
43
 * @property array sender
44
 *
45
 * @method integer getMsglist()
46
 * @method integer setMsglist(integer $msglist)
47
 * @method integer getUid()
48
 * @method integer setUid(integer $uid)
49
 * @method integer getMsgn()
50
 * @method integer setMsgn(integer $msgn)
51
 * @method integer getPriority()
52
 * @method integer setPriority(integer $priority)
53
 * @method string getSubject()
54
 * @method string setSubject(string $subject)
55
 * @method string getMessageId()
56
 * @method string setMessageId(string $message_id)
57
 * @method string getMessageNo()
58
 * @method string setMessageNo(string $message_no)
59
 * @method string getReferences()
60
 * @method string setReferences(string $references)
61
 * @method carbon getDate()
62
 * @method carbon setDate(carbon $date)
63
 * @method array getFrom()
64
 * @method array setFrom(array $from)
65
 * @method array getTo()
66
 * @method array setTo(array $to)
67
 * @method array getCc()
68
 * @method array setCc(array $cc)
69
 * @method array getBcc()
70
 * @method array setBcc(array $bcc)
71
 * @method array getReplyTo()
72
 * @method array setReplyTo(array $reply_to)
73
 * @method array getInReplyTo()
74
 * @method array setInReplyTo(array $in_reply_to)
75
 * @method array getSender()
76
 * @method array setSender(array $sender)
77
 */
78
class Message {
79
80
    /**
81
     * Client instance
82
     *
83
     * @var Client
84
     */
85
    private $client = Client::class;
86
87
    /**
88
     * Default mask
89
     * @var string $mask
90
     */
91
    protected $mask = MessageMask::class;
92
93
    /** @var array $config */
94
    protected $config = [];
95
96
    /** @var array $attributes */
97
    protected $attributes = [
98
        'message_id' => '',
99
        'message_no' => null,
100
        'subject' => '',
101
        'references' => null,
102
        'date' => null,
103
        'from' => [],
104
        'to' => [],
105
        'cc' => [],
106
        'bcc' => [],
107
        'reply_to' => [],
108
        'in_reply_to' => '',
109
        'sender' => [],
110
        'priority' => 0,
111
    ];
112
113
    /**
114
     * The message folder path
115
     *
116
     * @var string $folder_path
117
     */
118
    protected $folder_path;
119
120
    /**
121
     * Fetch body options
122
     *
123
     * @var integer
124
     */
125
    public $fetch_options = null;
126
127
    /**
128
     * Fetch body options
129
     *
130
     * @var bool
131
     */
132
    public $fetch_body = null;
133
134
    /**
135
     * Fetch attachments options
136
     *
137
     * @var bool
138
     */
139
    public $fetch_attachment = null;
140
141
    /**
142
     * Fetch flags options
143
     *
144
     * @var bool
145
     */
146
    public $fetch_flags = null;
147
148
    /**
149
     * @var string $header
150
     */
151
    public $header = null;
152
153
    /**
154
     * @var null|object $header_info
155
     */
156
    public $header_info = null;
157
158
    /** @var null|string $raw_body */
159
    public $raw_body = null;
160
161
    /** @var null $structure */
162
    protected $structure = null;
163
164
    /**
165
     * Message body components
166
     *
167
     * @var array   $bodies
168
     * @var AttachmentCollection|array $attachments
169
     * @var FlagCollection|array       $flags
170
     */
171
    public $bodies = [];
172
    public $attachments = [];
173
    public $flags = [];
174
175
    /**
176
     * A list of all available and supported flags
177
     *
178
     * @var array $available_flags
179
     */
180
    private $available_flags = ['recent', 'flagged', 'answered', 'deleted', 'seen', 'draft'];
181
182
    /**
183
     * Message constructor.
184
     *
185
     * @param integer       $uid
186
     * @param integer|null  $msglist
187
     * @param Client        $client
188
     * @param integer|null  $fetch_options
189
     * @param boolean       $fetch_body
190
     * @param boolean       $fetch_attachment
191
     * @param boolean       $fetch_flags
192
     *
193
     * @throws Exceptions\ConnectionFailedException
194
     * @throws InvalidMessageDateException
195
     */
196
    public function __construct($uid, $msglist, Client $client, $fetch_options = null, $fetch_body = false, $fetch_attachment = false, $fetch_flags = false) {
197
198
        $default_mask = $client->getDefaultMessageMask();
199
        if($default_mask != null) {
200
            $this->mask = $default_mask;
201
        }
202
203
        $this->folder_path = $client->getFolderPath();
0 ignored issues
show
Documentation Bug introduced by
It seems like $client->getFolderPath() of type Webklex\IMAP\Folder is incompatible with the declared type string of property $folder_path.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
204
205
        $this->config = config('imap.options');
206
207
        $this->setFetchOption($fetch_options);
208
        $this->setFetchBodyOption($fetch_body);
209
        $this->setFetchAttachmentOption($fetch_attachment);
210
        $this->setFetchFlagsOption($fetch_flags);
211
212
        $this->attachments = AttachmentCollection::make([]);
213
        $this->flags = FlagCollection::make([]);
214
215
        $this->msglist = $msglist;
216
        $this->client = $client;
217
218
        $this->uid =  ($this->fetch_options == IMAP::FT_UID) ? $uid : $uid;
219
        $this->msgn = ($this->fetch_options == IMAP::FT_UID) ? imap_msgno($this->client->getConnection(), $uid) : $uid;
0 ignored issues
show
Bug introduced by
It seems like $this->client->getConnection() can also be of type true; however, parameter $imap_stream of imap_msgno() does only seem to accept resource, 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

219
        $this->msgn = ($this->fetch_options == IMAP::FT_UID) ? imap_msgno(/** @scrutinizer ignore-type */ $this->client->getConnection(), $uid) : $uid;
Loading history...
220
221
        $this->parseHeader();
222
223
        if ($this->getFetchFlagsOption() === true) {
224
            $this->parseFlags();
225
        }
226
227
        if ($this->getFetchBodyOption() === true) {
228
            $this->parseBody();
229
        }
230
    }
231
232
    /**
233
     * Call dynamic attribute setter and getter methods
234
     * @param string $method
235
     * @param array $arguments
236
     *
237
     * @return mixed
238
     * @throws MethodNotFoundException
239
     */
240
    public function __call($method, $arguments) {
241
        if(strtolower(substr($method, 0, 3)) === 'get') {
242
            $name = snake_case(substr($method, 3));
0 ignored issues
show
Deprecated Code introduced by
The function snake_case() has been deprecated: Str::snake() should be used directly instead. Will be removed in Laravel 5.9. ( Ignorable by Annotation )

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

242
            $name = /** @scrutinizer ignore-deprecated */ snake_case(substr($method, 3));

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
243
244
            if(in_array($name, array_keys($this->attributes))) {
245
                return $this->attributes[$name];
246
            }
247
248
        }elseif (strtolower(substr($method, 0, 3)) === 'set') {
249
            $name = snake_case(substr($method, 3));
0 ignored issues
show
Deprecated Code introduced by
The function snake_case() has been deprecated: Str::snake() should be used directly instead. Will be removed in Laravel 5.9. ( Ignorable by Annotation )

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

249
            $name = /** @scrutinizer ignore-deprecated */ snake_case(substr($method, 3));

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
250
251
            if(in_array($name, array_keys($this->attributes))) {
252
                $this->attributes[$name] = array_pop($arguments);
253
254
                return $this->attributes[$name];
255
            }
256
257
        }
258
259
        throw new MethodNotFoundException("Method ".self::class.'::'.$method.'() is not supported');
260
    }
261
262
    /**
263
     * @param $name
264
     * @param $value
265
     *
266
     * @return mixed
267
     */
268
    public function __set($name, $value) {
269
        $this->attributes[$name] = $value;
270
271
        return $this->attributes[$name];
272
    }
273
274
    /**
275
     * @param $name
276
     *
277
     * @return mixed|null
278
     */
279
    public function __get($name) {
280
        if(isset($this->attributes[$name])) {
281
            return $this->attributes[$name];
282
        }
283
284
        return null;
285
    }
286
287
    /**
288
     * Copy the current Messages to a mailbox
289
     *
290
     * @param $mailbox
291
     * @param int $options
292
     *
293
     * @return bool
294
     * @throws Exceptions\ConnectionFailedException
295
     */
296
    public function copy($mailbox, $options = 0) {
297
        $this->client->openFolder($this->folder_path);
298
        return imap_mail_copy($this->client->getConnection(), $this->uid, $mailbox, IMAP::CP_UID);
0 ignored issues
show
Bug introduced by
It seems like $this->client->getConnection() can also be of type true; however, parameter $imap_stream of imap_mail_copy() does only seem to accept resource, 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

298
        return imap_mail_copy(/** @scrutinizer ignore-type */ $this->client->getConnection(), $this->uid, $mailbox, IMAP::CP_UID);
Loading history...
299
    }
300
301
    /**
302
     * Move the current Messages to a mailbox
303
     *
304
     * @param $mailbox
305
     * @param int $options
306
     *
307
     * @return bool
308
     * @throws Exceptions\ConnectionFailedException
309
     */
310
    public function move($mailbox, $options = 0) {
311
        $this->client->openFolder($this->folder_path);
312
        return imap_mail_move($this->client->getConnection(), $this->uid, $mailbox, IMAP::CP_UID);
0 ignored issues
show
Bug introduced by
It seems like $this->client->getConnection() can also be of type true; however, parameter $imap_stream of imap_mail_move() does only seem to accept resource, 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

312
        return imap_mail_move(/** @scrutinizer ignore-type */ $this->client->getConnection(), $this->uid, $mailbox, IMAP::CP_UID);
Loading history...
313
    }
314
315
    /**
316
     * Check if the Message has a text body
317
     *
318
     * @return bool
319
     */
320
    public function hasTextBody() {
321
        return isset($this->bodies['text']);
322
    }
323
324
    /**
325
     * Get the Message text body
326
     *
327
     * @return mixed
328
     */
329
    public function getTextBody() {
330
        if (!isset($this->bodies['text'])) {
331
            return false;
332
        }
333
334
        return $this->bodies['text']->content;
335
    }
336
337
    /**
338
     * Check if the Message has a html body
339
     *
340
     * @return bool
341
     */
342
    public function hasHTMLBody() {
343
        return isset($this->bodies['html']);
344
    }
345
346
    /**
347
     * Get the Message html body
348
     * If $replaceImages is callable it should expect string $body as first parameter, $oAttachment as second and return
349
     * the resulting $body.
350
     *
351
     * @var bool|callable $replaceImages
352
     *
353
     * @return string|null
354
     *
355
     * @deprecated 1.4.0:2.0.0 No longer needed. Use AttachmentMask::getImageSrc() instead
356
     */
357
    public function getHTMLBody($replaceImages = false) {
358
        if (!isset($this->bodies['html'])) {
359
            return null;
360
        }
361
362
        $body = $this->bodies['html']->content;
363
        if ($replaceImages !== false) {
364
            $this->attachments->each(function($oAttachment) use(&$body, $replaceImages) {
365
                /** @var Attachment $oAttachment */
366
                if(is_callable($replaceImages)) {
367
                    $body = $replaceImages($body, $oAttachment);
368
                }elseif(is_string($replaceImages)) {
369
                    call_user_func($replaceImages, [$body, $oAttachment]);
370
                }else{
371
                    if ($oAttachment->id && $oAttachment->getImgSrc() != null) {
0 ignored issues
show
Deprecated Code introduced by
The function Webklex\IMAP\Attachment::getImgSrc() has been deprecated: 1.4.0:2.0.0 No longer needed. Use AttachmentMask::getImageSrc() instead ( Ignorable by Annotation )

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

371
                    if ($oAttachment->id && /** @scrutinizer ignore-deprecated */ $oAttachment->getImgSrc() != null) {

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
372
                        $body = str_replace('cid:'.$oAttachment->id, $oAttachment->getImgSrc(), $body);
0 ignored issues
show
Deprecated Code introduced by
The function Webklex\IMAP\Attachment::getImgSrc() has been deprecated: 1.4.0:2.0.0 No longer needed. Use AttachmentMask::getImageSrc() instead ( Ignorable by Annotation )

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

372
                        $body = str_replace('cid:'.$oAttachment->id, /** @scrutinizer ignore-deprecated */ $oAttachment->getImgSrc(), $body);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
373
                    }
374
                }
375
            });
376
        }
377
378
        return $body;
379
    }
380
381
    /**
382
     * Parse all defined headers
383
     *
384
     * @return void
385
     * @throws Exceptions\ConnectionFailedException
386
     * @throws InvalidMessageDateException
387
     */
388
    private function parseHeader() {
389
        $this->client->openFolder($this->folder_path);
390
        $this->header = $header = imap_fetchheader($this->client->getConnection(), $this->uid, IMAP::FT_UID);
0 ignored issues
show
Bug introduced by
It seems like $this->client->getConnection() can also be of type true; however, parameter $imap_stream of imap_fetchheader() does only seem to accept resource, 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

390
        $this->header = $header = imap_fetchheader(/** @scrutinizer ignore-type */ $this->client->getConnection(), $this->uid, IMAP::FT_UID);
Loading history...
391
392
        $this->priority = $this->extractPriority($this->header);
393
394
        if ($this->header) {
395
            $header = imap_rfc822_parse_headers($this->header);
396
        }
397
398
        if (property_exists($header, 'subject')) {
399
            if($this->config['decoder']['message']['subject'] === 'utf-8') {
400
                $this->subject = imap_utf8($header->subject);
401
            }else{
402
                $this->subject = mb_decode_mimeheader($header->subject);
403
            }
404
        }
405
406
        foreach(['from', 'to', 'cc', 'bcc', 'reply_to', 'sender'] as $part){
407
            $this->extractHeaderAddressPart($header, $part);
0 ignored issues
show
Bug introduced by
It seems like $header can also be of type string; however, parameter $header of Webklex\IMAP\Message::extractHeaderAddressPart() does only seem to accept object, 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

407
            $this->extractHeaderAddressPart(/** @scrutinizer ignore-type */ $header, $part);
Loading history...
408
        }
409
410
        if (property_exists($header, 'references')) {
411
            $this->references = $header->references;
412
        }
413
        if (property_exists($header, 'in_reply_to')) {
414
            $this->in_reply_to = str_replace(['<', '>'], '', $header->in_reply_to);
415
        }
416
        if (property_exists($header, 'message_id')) {
417
            $this->message_id = str_replace(['<', '>'], '', $header->message_id);
418
        }
419
        if (property_exists($header, 'Msgno')) {
420
            $messageNo = (int) trim($header->Msgno);
421
            $this->message_no = ($this->fetch_options == IMAP::FT_UID) ? $messageNo : imap_msgno($this->client->getConnection(), $messageNo);
0 ignored issues
show
Bug introduced by
It seems like $this->client->getConnection() can also be of type true; however, parameter $imap_stream of imap_msgno() does only seem to accept resource, 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

421
            $this->message_no = ($this->fetch_options == IMAP::FT_UID) ? $messageNo : imap_msgno(/** @scrutinizer ignore-type */ $this->client->getConnection(), $messageNo);
Loading history...
422
        } else {
423
            $this->message_no = imap_msgno($this->client->getConnection(), $this->getUid());
424
        }
425
426
        $this->date = $this->parseDate($header);
0 ignored issues
show
Bug introduced by
It seems like $header can also be of type string; however, parameter $header of Webklex\IMAP\Message::parseDate() does only seem to accept object, 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

426
        $this->date = $this->parseDate(/** @scrutinizer ignore-type */ $header);
Loading history...
427
    }
428
429
    /**
430
     * Try to extract the priority from a given raw header string
431
     * @param string $header
432
     *
433
     * @return int|null
434
     */
435
    private function extractPriority($header) {
436
        if(preg_match('/x\-priority\:.*([0-9]{1,2})/i', $header, $priority)){
437
            $priority = isset($priority[1]) ? (int) $priority[1] : 0;
438
            switch($priority){
439
                case IMAP::MESSAGE_PRIORITY_HIGHEST;
440
                    $priority = IMAP::MESSAGE_PRIORITY_HIGHEST;
441
                    break;
442
                case IMAP::MESSAGE_PRIORITY_HIGH;
443
                    $priority = IMAP::MESSAGE_PRIORITY_HIGH;
444
                    break;
445
                case IMAP::MESSAGE_PRIORITY_NORMAL;
446
                    $priority = IMAP::MESSAGE_PRIORITY_NORMAL;
447
                    break;
448
                case IMAP::MESSAGE_PRIORITY_LOW;
449
                    $priority = IMAP::MESSAGE_PRIORITY_LOW;
450
                    break;
451
                case IMAP::MESSAGE_PRIORITY_LOWEST;
452
                    $priority = IMAP::MESSAGE_PRIORITY_LOWEST;
453
                    break;
454
                default:
455
                    $priority = IMAP::MESSAGE_PRIORITY_UNKNOWN;
456
                    break;
457
            }
458
        }
459
460
        return $priority;
461
    }
462
463
    /**
464
     * Exception handling for invalid dates
465
     *
466
     * Currently known invalid formats:
467
     * ^ Datetime                                   ^ Problem                           ^ Cause
468
     * | Mon, 20 Nov 2017 20:31:31 +0800 (GMT+8:00) | Double timezone specification     | A Windows feature
469
     * | Thu, 8 Nov 2018 08:54:58 -0200 (-02)       |
470
     * |                                            | and invalid timezone (max 6 char) |
471
     * | 04 Jan 2018 10:12:47 UT                    | Missing letter "C"                | Unknown
472
     * | Thu, 31 May 2018 18:15:00 +0800 (added by) | Non-standard details added by the | Unknown
473
     * |                                            | mail server                       |
474
     * | Sat, 31 Aug 2013 20:08:23 +0580            | Invalid timezone                  | PHPMailer bug https://sourceforge.net/p/phpmailer/mailman/message/6132703/
475
     *
476
     * Please report any new invalid timestamps to [#45](https://github.com/Webklex/laravel-imap/issues/45)
477
     *
478
     * @param object $header
479
     *
480
     * @return Carbon|null
481
     * @throws InvalidMessageDateException
482
     */
483
    private function parseDate($header) {
484
        $parsed_date = null;
485
486
        if (property_exists($header, 'date')) {
487
            $date = $header->date;
488
489
            if(preg_match('/\+0580/', $date)) {
490
                $date = str_replace('+0580', '+0530', $date);
491
            }
492
493
            $date = trim(rtrim($date));
494
            try {
495
                $parsed_date = Carbon::parse($date);
496
            } catch (\Exception $e) {
497
                switch (true) {
498
                    case preg_match('/([0-9]{1,2}\ [A-Z]{2,3}\ [0-9]{4}\ [0-9]{1,2}\:[0-9]{1,2}\:[0-9]{1,2}\ UT)+$/i', $date) > 0:
499
                    case preg_match('/([A-Z]{2,3}\,\ [0-9]{1,2}\ [A-Z]{2,3}\ [0-9]{4}\ [0-9]{1,2}\:[0-9]{1,2}\:[0-9]{1,2}\ UT)+$/i', $date) > 0:
500
                        $date .= 'C';
501
                        break;
502
                    case preg_match('/([A-Z]{2,3}[\,|\ \,]\ [0-9]{1,2}\ [A-Z]{2,3}\ [0-9]{4}\ [0-9]{1,2}\:[0-9]{1,2}\:[0-9]{1,2}.*)+$/i', $date) > 0:
503
                    case preg_match('/([A-Z]{2,3}\,\ [0-9]{1,2}\ [A-Z]{2,3}\ [0-9]{4}\ [0-9]{1,2}\:[0-9]{1,2}\:[0-9]{1,2}\ [\-|\+][0-9]{4}\ \(.*)\)+$/i', $date) > 0:
504
                    case preg_match('/([A-Z]{2,3}\, \ [0-9]{1,2}\ [A-Z]{2,3}\ [0-9]{4}\ [0-9]{1,2}\:[0-9]{1,2}\:[0-9]{1,2}\ [\-|\+][0-9]{4}\ \(.*)\)+$/i', $date) > 0:
505
                    case preg_match('/([0-9]{1,2}\ [A-Z]{2,3}\ [0-9]{2,4}\ [0-9]{2}\:[0-9]{2}\:[0-9]{2}\ [A-Z]{2}\ \-[0-9]{2}\:[0-9]{2}\ \([A-Z]{2,3}\ \-[0-9]{2}:[0-9]{2}\))+$/i', $date) > 0:
506
                        $array = explode('(', $date);
507
                        $array = array_reverse($array);
508
                        $date = trim(array_pop($array));
509
                        break;
510
                }
511
                try{
512
                    $parsed_date = Carbon::parse($date);
513
                } catch (\Exception $_e) {
514
                    throw new InvalidMessageDateException("Invalid message date. ID:".$this->getMessageId(), 1000, $e);
515
                }
516
            }
517
        }
518
519
        return $parsed_date;
520
    }
521
522
    /**
523
     * Parse additional flags
524
     *
525
     * @return void
526
     * @throws Exceptions\ConnectionFailedException
527
     */
528
    private function parseFlags() {
529
        $this->flags = FlagCollection::make([]);
530
531
        $this->client->openFolder($this->folder_path);
532
        $flags = imap_fetch_overview($this->client->getConnection(), $this->uid, IMAP::FT_UID);
0 ignored issues
show
Bug introduced by
It seems like $this->client->getConnection() can also be of type true; however, parameter $imap_stream of imap_fetch_overview() does only seem to accept resource, 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

532
        $flags = imap_fetch_overview(/** @scrutinizer ignore-type */ $this->client->getConnection(), $this->uid, IMAP::FT_UID);
Loading history...
533
        if (is_array($flags) && isset($flags[0])) {
534
            foreach($this->available_flags as $flag) {
535
                $this->parseFlag($flags, $flag);
536
            }
537
        }
538
    }
539
540
    /**
541
     * Extract a possible flag information from a given array
542
     * @param array $flags
543
     * @param string $flag
544
     */
545
    private function parseFlag($flags, $flag) {
546
        $flag = strtolower($flag);
547
548
        if (property_exists($flags[0], strtoupper($flag))) {
549
            $this->flags->put($flag, $flags[0]->{strtoupper($flag)});
550
        } elseif (property_exists($flags[0], ucfirst($flag))) {
551
            $this->flags->put($flag, $flags[0]->{ucfirst($flag)});
552
        } elseif (property_exists($flags[0], $flag)) {
553
            $this->flags->put($flag, $flags[0]->$flag);
554
        }
555
    }
556
557
    /**
558
     * Get the current Message header info
559
     *
560
     * @return object
561
     * @throws Exceptions\ConnectionFailedException
562
     */
563
    public function getHeaderInfo() {
564
        if ($this->header_info == null) {
565
            $this->client->openFolder($this->folder_path);
566
            $this->header_info = imap_headerinfo($this->client->getConnection(), $this->getMessageNo());
0 ignored issues
show
Bug introduced by
It seems like $this->client->getConnection() can also be of type true; however, parameter $stream_id of imap_headerinfo() does only seem to accept resource, 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

566
            $this->header_info = imap_headerinfo(/** @scrutinizer ignore-type */ $this->client->getConnection(), $this->getMessageNo());
Loading history...
Bug introduced by
$this->getMessageNo() of type string is incompatible with the type integer expected by parameter $msg_no of imap_headerinfo(). ( Ignorable by Annotation )

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

566
            $this->header_info = imap_headerinfo($this->client->getConnection(), /** @scrutinizer ignore-type */ $this->getMessageNo());
Loading history...
567
        }
568
569
        return $this->header_info;
570
    }
571
572
    /**
573
     * Extract a given part as address array from a given header
574
     * @param object $header
575
     * @param string $part
576
     */
577
    private function extractHeaderAddressPart($header, $part) {
578
        if (property_exists($header, $part)) {
579
            $this->$part = $this->parseAddresses($header->$part);
580
        }
581
    }
582
583
    /**
584
     * Parse Addresses
585
     * @param $list
586
     *
587
     * @return array
588
     */
589
    private function parseAddresses($list) {
590
        $addresses = [];
591
592
        foreach ($list as $item) {
593
            $address = (object) $item;
594
595
            if (!property_exists($address, 'mailbox')) {
596
                $address->mailbox = false;
597
            }
598
            if (!property_exists($address, 'host')) {
599
                $address->host = false;
600
            }
601
            if (!property_exists($address, 'personal')) {
602
                $address->personal = false;
603
            }
604
605
            $personalParts = imap_mime_header_decode($address->personal);
606
607
            $address->personal = '';
608
            foreach ($personalParts as $p) {
609
                $address->personal .= $p->text;
610
            }
611
612
            $address->mail = ($address->mailbox && $address->host) ? $address->mailbox.'@'.$address->host : false;
613
            $address->full = ($address->personal) ? $address->personal.' <'.$address->mail.'>' : $address->mail;
0 ignored issues
show
Bug introduced by
Are you sure $address->mail of type false|string can be used in concatenation? ( Ignorable by Annotation )

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

613
            $address->full = ($address->personal) ? $address->personal.' <'./** @scrutinizer ignore-type */ $address->mail.'>' : $address->mail;
Loading history...
614
615
            $addresses[] = $address;
616
        }
617
618
        return $addresses;
619
    }
620
621
    /**
622
     * Parse the Message body
623
     *
624
     * @return $this
625
     * @throws Exceptions\ConnectionFailedException
626
     */
627
    public function parseBody() {
628
        $this->client->openFolder($this->folder_path);
629
        $this->structure = imap_fetchstructure($this->client->getConnection(), $this->uid, IMAP::FT_UID);
0 ignored issues
show
Bug introduced by
It seems like $this->client->getConnection() can also be of type true; however, parameter $imap_stream of imap_fetchstructure() does only seem to accept resource, 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

629
        $this->structure = imap_fetchstructure(/** @scrutinizer ignore-type */ $this->client->getConnection(), $this->uid, IMAP::FT_UID);
Loading history...
Documentation Bug introduced by
It seems like imap_fetchstructure($thi...klex\IMAP\IMAP::FT_UID) of type object is incompatible with the declared type null of property $structure.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
630
631
        if(property_exists($this->structure, 'parts')){
632
            $parts = $this->structure->parts;
633
634
            foreach ($parts as $part)  {
635
                foreach ($part->parameters as $parameter)  {
636
                    if($parameter->attribute == "charset")  {
637
                        $encoding = $parameter->value;
638
639
                        $encoding = preg_replace('/Content-Transfer-Encoding/', '', $encoding);
640
                        $encoding = preg_replace('/iso-8859-8-i/', 'iso-8859-8', $encoding);
641
642
                        $parameter->value = $encoding;
643
                    }
644
                }
645
            }
646
        }
647
648
        $this->fetchStructure($this->structure);
649
650
        return $this;
651
    }
652
653
    /**
654
     * Fetch the Message structure
655
     *
656
     * @param $structure
657
     * @param mixed $partNumber
658
     *
659
     * @throws Exceptions\ConnectionFailedException
660
     */
661
    private function fetchStructure($structure, $partNumber = null) {
662
        $this->client->openFolder($this->folder_path);
663
664
        if ($structure->type == IMAP::MESSAGE_TYPE_TEXT &&
665
            ($structure->ifdisposition == 0 ||
666
                ($structure->ifdisposition == 1 && !isset($structure->parts) && $partNumber != null)
667
            )
668
        ) {
669
            if ($structure->subtype == "PLAIN") {
670
                if (!$partNumber) {
671
                    $partNumber = 1;
672
                }
673
674
                $encoding = $this->getEncoding($structure);
675
676
                $content = imap_fetchbody($this->client->getConnection(), $this->uid, $partNumber, $this->fetch_options | IMAP::FT_UID);
0 ignored issues
show
Bug introduced by
It seems like $this->client->getConnection() can also be of type true; however, parameter $imap_stream of imap_fetchbody() does only seem to accept resource, 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

676
                $content = imap_fetchbody(/** @scrutinizer ignore-type */ $this->client->getConnection(), $this->uid, $partNumber, $this->fetch_options | IMAP::FT_UID);
Loading history...
677
                $content = $this->decodeString($content, $structure->encoding);
678
679
                // We don't need to do convertEncoding() if charset is ASCII (us-ascii):
680
                //     ASCII is a subset of UTF-8, so all ASCII files are already UTF-8 encoded
681
                //     https://stackoverflow.com/a/11303410
682
                //
683
                // us-ascii is the same as ASCII:
684
                //     ASCII is the traditional name for the encoding system; the Internet Assigned Numbers Authority (IANA)
685
                //     prefers the updated name US-ASCII, which clarifies that this system was developed in the US and
686
                //     based on the typographical symbols predominantly in use there.
687
                //     https://en.wikipedia.org/wiki/ASCII
688
                //
689
                // convertEncoding() function basically means convertToUtf8(), so when we convert ASCII string into UTF-8 it gets broken.
690
                if ($encoding != 'us-ascii') {
691
                    $content = $this->convertEncoding($content, $encoding);
692
                }
693
694
                $body = new \stdClass;
695
                $body->type = "text";
696
                $body->content = $content;
697
698
                $this->bodies['text'] = $body;
699
700
                $this->fetchAttachment($structure, $partNumber);
701
702
            } elseif ($structure->subtype == "HTML") {
703
                if (!$partNumber) {
704
                    $partNumber = 1;
705
                }
706
707
                $encoding = $this->getEncoding($structure);
708
709
                $content = imap_fetchbody($this->client->getConnection(), $this->uid, $partNumber, $this->fetch_options | IMAP::FT_UID);
710
                $content = $this->decodeString($content, $structure->encoding);
711
                if ($encoding != 'us-ascii') {
712
                    $content = $this->convertEncoding($content, $encoding);
713
                }
714
715
                $body = new \stdClass;
716
                $body->type = "html";
717
                $body->content = $content;
718
719
                $this->bodies['html'] = $body;
720
            } elseif ($structure->disposition == 'attachment') {
721
                if ($this->getFetchAttachmentOption() === true) {
722
                    $this->fetchAttachment($structure, $partNumber);
723
                }
724
            }
725
        } elseif ($structure->type == IMAP::MESSAGE_TYPE_MULTIPART) {
726
            foreach ($structure->parts as $index => $subStruct) {
727
                $prefix = "";
728
                if ($partNumber) {
729
                    $prefix = $partNumber.".";
730
                }
731
                $this->fetchStructure($subStruct, $prefix.($index + 1));
732
            }
733
        } else {
734
            if ($this->getFetchAttachmentOption() === true) {
735
                $this->fetchAttachment($structure, $partNumber);
736
            }
737
        }
738
    }
739
740
    /**
741
     * Fetch the Message attachment
742
     *
743
     * @param object $structure
744
     * @param mixed  $partNumber
745
     *
746
     * @throws Exceptions\ConnectionFailedException
747
     */
748
    protected function fetchAttachment($structure, $partNumber) {
749
750
        $oAttachment = new Attachment($this, $structure, $partNumber);
751
752
        if ($oAttachment->getName() !== null) {
0 ignored issues
show
introduced by
The condition $oAttachment->getName() !== null is always true.
Loading history...
753
            if ($oAttachment->getId() !== null) {
0 ignored issues
show
introduced by
The condition $oAttachment->getId() !== null is always true.
Loading history...
754
                $this->attachments->put($oAttachment->getId(), $oAttachment);
755
            } else {
756
                $this->attachments->push($oAttachment);
757
            }
758
        }
759
    }
760
761
    /**
762
     * Fail proof setter for $fetch_option
763
     *
764
     * @param $option
765
     *
766
     * @return $this
767
     */
768
    public function setFetchOption($option) {
769
        if (is_long($option) === true) {
770
            $this->fetch_options = $option;
771
        } elseif (is_null($option) === true) {
772
            $config = config('imap.options.fetch', IMAP::FT_UID);
773
            $this->fetch_options = is_long($config) ? $config : 1;
774
        }
775
776
        return $this;
777
    }
778
779
    /**
780
     * Fail proof setter for $fetch_body
781
     *
782
     * @param $option
783
     *
784
     * @return $this
785
     */
786
    public function setFetchBodyOption($option) {
787
        if (is_bool($option)) {
788
            $this->fetch_body = $option;
789
        } elseif (is_null($option)) {
790
            $config = config('imap.options.fetch_body', true);
791
            $this->fetch_body = is_bool($config) ? $config : true;
792
        }
793
794
        return $this;
795
    }
796
797
    /**
798
     * Fail proof setter for $fetch_attachment
799
     *
800
     * @param $option
801
     *
802
     * @return $this
803
     */
804
    public function setFetchAttachmentOption($option) {
805
        if (is_bool($option)) {
806
            $this->fetch_attachment = $option;
807
        } elseif (is_null($option)) {
808
            $config = config('imap.options.fetch_attachment', true);
809
            $this->fetch_attachment = is_bool($config) ? $config : true;
810
        }
811
812
        return $this;
813
    }
814
815
    /**
816
     * Fail proof setter for $fetch_flags
817
     *
818
     * @param $option
819
     *
820
     * @return $this
821
     */
822
    public function setFetchFlagsOption($option) {
823
        if (is_bool($option)) {
824
            $this->fetch_flags = $option;
825
        } elseif (is_null($option)) {
826
            $config = config('imap.options.fetch_flags', true);
827
            $this->fetch_flags = is_bool($config) ? $config : true;
828
        }
829
830
        return $this;
831
    }
832
833
    /**
834
     * Decode a given string
835
     *
836
     * @param $string
837
     * @param $encoding
838
     *
839
     * @return string
840
     */
841
    public function decodeString($string, $encoding) {
842
        switch ($encoding) {
843
            case IMAP::MESSAGE_ENC_7BIT:
844
                return $string;
845
            case IMAP::MESSAGE_ENC_8BIT:
846
                return quoted_printable_decode(imap_8bit($string));
847
            case IMAP::MESSAGE_ENC_BINARY:
848
                return imap_binary($string);
849
            case IMAP::MESSAGE_ENC_BASE64:
850
                return imap_base64($string);
851
            case IMAP::MESSAGE_ENC_QUOTED_PRINTABLE:
852
                return quoted_printable_decode($string);
853
            case IMAP::MESSAGE_ENC_OTHER:
854
                return $string;
855
            default:
856
                return $string;
857
        }
858
    }
859
860
    /**
861
     * Convert the encoding
862
     *
863
     * @param $str
864
     * @param string $from
865
     * @param string $to
866
     *
867
     * @return mixed|string
868
     */
869
    public function convertEncoding($str, $from = "ISO-8859-2", $to = "UTF-8") {
870
871
        $from = EncodingAliases::get($from);
872
        $to = EncodingAliases::get($to);
873
        
874
        if ($from === $to) {
875
            return $str;
876
        }
877
878
        // We don't need to do convertEncoding() if charset is ASCII (us-ascii):
879
        //     ASCII is a subset of UTF-8, so all ASCII files are already UTF-8 encoded
880
        //     https://stackoverflow.com/a/11303410
881
        //
882
        // us-ascii is the same as ASCII:
883
        //     ASCII is the traditional name for the encoding system; the Internet Assigned Numbers Authority (IANA)
884
        //     prefers the updated name US-ASCII, which clarifies that this system was developed in the US and
885
        //     based on the typographical symbols predominantly in use there.
886
        //     https://en.wikipedia.org/wiki/ASCII
887
        //
888
        // convertEncoding() function basically means convertToUtf8(), so when we convert ASCII string into UTF-8 it gets broken.
889
        if (strtolower($from) == 'us-ascii' && $to == 'UTF-8') {
890
            return $str;
891
        }
892
893
        if (function_exists('iconv') && $from != 'UTF-7' && $to != 'UTF-7') {
894
            return @iconv($from, $to.'//IGNORE', $str);
895
        } else {
896
            if (!$from) {
897
                return mb_convert_encoding($str, $to);
898
            }
899
            return mb_convert_encoding($str, $to, $from);
900
        }
901
    }
902
903
    /**
904
     * Get the encoding of a given abject
905
     *
906
     * @param object|string $structure
907
     *
908
     * @return string
909
     */
910
    public function getEncoding($structure) {
911
        if (property_exists($structure, 'parameters')) {
912
            foreach ($structure->parameters as $parameter) {
913
                if (strtolower($parameter->attribute) == "charset") {
914
                    return EncodingAliases::get($parameter->value);
915
                }
916
            }
917
        }elseif (is_string($structure) === true){
918
            return mb_detect_encoding($structure);
919
        }
920
921
        return 'UTF-8';
922
    }
923
924
    /**
925
     * Find the folder containing this message.
926
     * @param null|Folder $folder where to start searching from (top-level inbox by default)
927
     *
928
     * @return mixed|null|Folder
929
     * @throws Exceptions\ConnectionFailedException
930
     * @throws Exceptions\MailboxFetchingException
931
     * @throws InvalidMessageDateException
932
     * @throws MaskNotFoundException
933
     */
934
    public function getContainingFolder(Folder $folder = null) {
935
        $folder = $folder ?: $this->client->getFolders()->first();
936
        $this->client->checkConnection();
937
938
        // Try finding the message by uid in the current folder
939
        $client = new Client;
940
        $client->openFolder($folder->path);
941
        $uidMatches = imap_fetch_overview($client->getConnection(), $this->uid, IMAP::FT_UID);
0 ignored issues
show
Bug introduced by
It seems like $client->getConnection() can also be of type true; however, parameter $imap_stream of imap_fetch_overview() does only seem to accept resource, 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

941
        $uidMatches = imap_fetch_overview(/** @scrutinizer ignore-type */ $client->getConnection(), $this->uid, IMAP::FT_UID);
Loading history...
942
        $uidMatch = count($uidMatches)
943
            ? new Message($uidMatches[0]->uid, $uidMatches[0]->msgno, $client)
944
            : null;
945
        $client->disconnect();
946
947
        // imap_fetch_overview() on a parent folder will return the matching message
948
        // even when the message is in a child folder so we need to recursively
949
        // search the children
950
        foreach ($folder->children as $child) {
951
            $childFolder = $this->getContainingFolder($child);
952
953
            if ($childFolder) {
954
                return $childFolder;
955
            }
956
        }
957
958
        // before returning the parent
959
        if ($this->is($uidMatch)) {
960
            return $folder;
961
        }
962
963
        // or signalling that the message was not found in any folder
964
        return null;
965
    }
966
967
    public function getFolder(){
968
        return $this->client->getFolder($this->folder_path);
969
    }
970
971
    /**
972
     * Move the Message into an other Folder
973
     * @param string $mailbox
974
     * @param bool $expunge
975
     * @param bool $create_folder
976
     *
977
     * @return null|Message
978
     * @throws Exceptions\ConnectionFailedException
979
     * @throws InvalidMessageDateException
980
     */
981
    public function moveToFolder($mailbox = 'INBOX', $expunge = false, $create_folder = true) {
982
983
        if($create_folder) $this->client->createFolder($mailbox, true);
984
985
        $target_folder = $this->client->getFolder($mailbox);
986
        $target_status = $target_folder->getStatus(IMAP::SA_ALL);
987
988
        $this->client->openFolder($this->folder_path);
989
        $status = imap_mail_move($this->client->getConnection(), $this->uid, $mailbox, IMAP::CP_UID);
0 ignored issues
show
Bug introduced by
It seems like $this->client->getConnection() can also be of type true; however, parameter $imap_stream of imap_mail_move() does only seem to accept resource, 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

989
        $status = imap_mail_move(/** @scrutinizer ignore-type */ $this->client->getConnection(), $this->uid, $mailbox, IMAP::CP_UID);
Loading history...
990
991
        if($status === true){
992
            if($expunge) $this->client->expunge();
993
            $this->client->openFolder($target_folder->path);
994
995
            return $target_folder->getMessage($target_status->uidnext, null, $this->fetch_options, $this->fetch_body, $this->fetch_attachment, $this->fetch_flags);
996
        }
997
998
        return null;
999
    }
1000
1001
    /**
1002
     * Delete the current Message
1003
     * @param bool $expunge
1004
     *
1005
     * @return bool
1006
     * @throws Exceptions\ConnectionFailedException
1007
     */
1008
    public function delete($expunge = true) {
1009
        $this->client->openFolder($this->folder_path);
1010
1011
        $status = imap_delete($this->client->getConnection(), $this->uid, IMAP::FT_UID);
0 ignored issues
show
Bug introduced by
It seems like $this->client->getConnection() can also be of type true; however, parameter $imap_stream of imap_delete() does only seem to accept resource, 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

1011
        $status = imap_delete(/** @scrutinizer ignore-type */ $this->client->getConnection(), $this->uid, IMAP::FT_UID);
Loading history...
1012
        if($expunge) $this->client->expunge();
1013
1014
        return $status;
1015
    }
1016
1017
    /**
1018
     * Restore a deleted Message
1019
     * @param boolean $expunge
1020
     *
1021
     * @return bool
1022
     * @throws Exceptions\ConnectionFailedException
1023
     */
1024
    public function restore($expunge = true) {
1025
        $this->client->openFolder($this->folder_path);
1026
1027
        $status = imap_undelete($this->client->getConnection(), $this->uid, IMAP::FT_UID);
0 ignored issues
show
Bug introduced by
It seems like $this->client->getConnection() can also be of type true; however, parameter $imap_stream of imap_undelete() does only seem to accept resource, 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

1027
        $status = imap_undelete(/** @scrutinizer ignore-type */ $this->client->getConnection(), $this->uid, IMAP::FT_UID);
Loading history...
1028
        if($expunge) $this->client->expunge();
1029
1030
        return $status;
1031
    }
1032
1033
    /**
1034
     * Get all message attachments.
1035
     *
1036
     * @return AttachmentCollection
1037
     */
1038
    public function getAttachments() {
1039
        return $this->attachments;
1040
    }
1041
1042
    /**
1043
     * Checks if there are any attachments present
1044
     *
1045
     * @return boolean
1046
     */
1047
    public function hasAttachments() {
1048
        return $this->attachments->isEmpty() === false;
1049
    }
1050
1051
    /**
1052
     * Set a given flag
1053
     * @param string|array $flag
1054
     *
1055
     * @return bool
1056
     * @throws Exceptions\ConnectionFailedException
1057
     */
1058
    public function setFlag($flag) {
1059
        $this->client->openFolder($this->folder_path);
1060
1061
        $flag = "\\".trim(is_array($flag) ? implode(" \\", $flag) : $flag);
1062
        $status = imap_setflag_full($this->client->getConnection(), $this->getUid(), $flag, SE_UID);
0 ignored issues
show
Bug introduced by
It seems like $this->client->getConnection() can also be of type true; however, parameter $imap_stream of imap_setflag_full() does only seem to accept resource, 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

1062
        $status = imap_setflag_full(/** @scrutinizer ignore-type */ $this->client->getConnection(), $this->getUid(), $flag, SE_UID);
Loading history...
1063
        $this->parseFlags();
1064
1065
        return $status;
1066
    }
1067
1068
    /**
1069
     * Unset a given flag
1070
     * @param string|array $flag
1071
     *
1072
     * @return bool
1073
     * @throws Exceptions\ConnectionFailedException
1074
     */
1075
    public function unsetFlag($flag) {
1076
        $this->client->openFolder($this->folder_path);
1077
1078
        $flag = "\\".trim(is_array($flag) ? implode(" \\", $flag) : $flag);
1079
        $status = imap_clearflag_full($this->client->getConnection(), $this->getUid(), $flag, SE_UID);
0 ignored issues
show
Bug introduced by
It seems like $this->client->getConnection() can also be of type true; however, parameter $imap_stream of imap_clearflag_full() does only seem to accept resource, 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

1079
        $status = imap_clearflag_full(/** @scrutinizer ignore-type */ $this->client->getConnection(), $this->getUid(), $flag, SE_UID);
Loading history...
1080
        $this->parseFlags();
1081
1082
        return $status;
1083
    }
1084
1085
    /**
1086
     * @return null|object|string
1087
     * @throws Exceptions\ConnectionFailedException
1088
     */
1089
    public function getRawBody() {
1090
        if ($this->raw_body === null) {
1091
            $this->client->openFolder($this->folder_path);
1092
1093
            $this->raw_body = imap_fetchbody($this->client->getConnection(), $this->getUid(), '', $this->fetch_options | IMAP::FT_UID);
0 ignored issues
show
Bug introduced by
It seems like $this->client->getConnection() can also be of type true; however, parameter $imap_stream of imap_fetchbody() does only seem to accept resource, 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

1093
            $this->raw_body = imap_fetchbody(/** @scrutinizer ignore-type */ $this->client->getConnection(), $this->getUid(), '', $this->fetch_options | IMAP::FT_UID);
Loading history...
1094
        }
1095
1096
        return $this->raw_body;
1097
    }
1098
1099
    /**
1100
     * @return string
1101
     */
1102
    public function getHeader() {
1103
        return $this->header;
1104
    }
1105
1106
    /**
1107
     * @return Client
1108
     */
1109
    public function getClient() {
1110
        return $this->client;
1111
    }
1112
1113
    /**
1114
     * @return integer
1115
     */
1116
    public function getFetchOptions() {
1117
        return $this->fetch_options;
1118
    }
1119
1120
    /**
1121
     * @return boolean
1122
     */
1123
    public function getFetchBodyOption() {
1124
        return $this->fetch_body;
1125
    }
1126
1127
    /**
1128
     * @return boolean
1129
     */
1130
    public function getFetchAttachmentOption() {
1131
        return $this->fetch_attachment;
1132
    }
1133
    
1134
    /**
1135
     * @return boolean
1136
     */
1137
    public function getFetchFlagsOption() {
1138
        return $this->fetch_flags;
1139
    }
1140
1141
    /**
1142
     * @return mixed
1143
     */
1144
    public function getBodies() {
1145
        return $this->bodies;
1146
    }
1147
    
1148
    /**
1149
     * @return FlagCollection
1150
     */
1151
    public function getFlags() {
1152
        return $this->flags;
1153
    }
1154
1155
    /**
1156
     * @return object|null
1157
     */
1158
    public function getStructure(){
1159
        return $this->structure;
1160
    }
1161
1162
    /**
1163
     * Does this message match another one?
1164
     *
1165
     * A match means same uid, message id, subject and date/time.
1166
     *
1167
     * @param  null|Message $message
1168
     * @return boolean
1169
     */
1170
    public function is(Message $message = null) {
1171
        if (is_null($message)) {
1172
            return false;
1173
        }
1174
1175
        return $this->uid == $message->uid
1176
            && $this->message_id == $message->message_id
1177
            && $this->subject == $message->subject
1178
            && $this->date->eq($message->date);
1179
    }
1180
1181
    /**
1182
     * @return array
1183
     */
1184
    public function getAttributes(){
1185
        return $this->attributes;
1186
    }
1187
1188
    /**
1189
     * @param $mask
1190
     * @return $this
1191
     */
1192
    public function setMask($mask){
1193
        if(class_exists($mask)){
1194
            $this->mask = $mask;
1195
        }
1196
1197
        return $this;
1198
    }
1199
1200
    /**
1201
     * @return string
1202
     */
1203
    public function getMask(){
1204
        return $this->mask;
1205
    }
1206
1207
    /**
1208
     * Get a masked instance by providing a mask name
1209
     * @param string|null $mask
1210
     *
1211
     * @return mixed
1212
     * @throws MaskNotFoundException
1213
     */
1214
    public function mask($mask = null){
1215
        $mask = $mask !== null ? $mask : $this->mask;
1216
        if(class_exists($mask)){
1217
            return new $mask($this);
1218
        }
1219
1220
        throw new MaskNotFoundException("Unknown mask provided: ".$mask);
1221
    }
1222
}
1223