Completed
Push — master ( e798ee...0f9365 )
by Malte
03:48
created

Message::parseDate()   C

Complexity

Conditions 12
Paths 35

Size

Total Lines 38
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 12
eloc 28
c 2
b 0
f 0
nc 35
nop 1
dl 0
loc 38
rs 6.9666

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

220
        $this->msgn = ($this->fetch_options == IMAP::FT_UID) ? imap_msgno(/** @scrutinizer ignore-type */ $this->client->getConnection(), $uid) : $uid;
Loading history...
221
222
        $this->parseHeader();
223
224
        if ($this->getFetchFlagsOption() === true) {
225
            $this->parseFlags();
226
        }
227
228
        if ($this->getFetchBodyOption() === true) {
229
            $this->parseBody();
230
        }
231
    }
232
233
    /**
234
     * Call dynamic attribute setter and getter methods
235
     * @param string $method
236
     * @param array $arguments
237
     *
238
     * @return mixed
239
     * @throws MethodNotFoundException
240
     */
241
    public function __call($method, $arguments) {
242
        if(strtolower(substr($method, 0, 3)) === 'get') {
243
            $name = Str::snake(substr($method, 3));
244
245
            if(in_array($name, array_keys($this->attributes))) {
246
                return $this->attributes[$name];
247
            }
248
249
        }elseif (strtolower(substr($method, 0, 3)) === 'set') {
250
            $name = Str::snake(substr($method, 3));
251
252
            if(in_array($name, array_keys($this->attributes))) {
253
                $this->attributes[$name] = array_pop($arguments);
254
255
                return $this->attributes[$name];
256
            }
257
258
        }
259
260
        throw new MethodNotFoundException("Method ".self::class.'::'.$method.'() is not supported');
261
    }
262
263
    /**
264
     * @param $name
265
     * @param $value
266
     *
267
     * @return mixed
268
     */
269
    public function __set($name, $value) {
270
        $this->attributes[$name] = $value;
271
272
        return $this->attributes[$name];
273
    }
274
275
    /**
276
     * @param $name
277
     *
278
     * @return mixed|null
279
     */
280
    public function __get($name) {
281
        if(isset($this->attributes[$name])) {
282
            return $this->attributes[$name];
283
        }
284
285
        return null;
286
    }
287
288
    /**
289
     * Copy the current Messages to a mailbox
290
     *
291
     * @param $mailbox
292
     * @param int $options
293
     *
294
     * @return bool
295
     * @throws Exceptions\ConnectionFailedException
296
     */
297
    public function copy($mailbox, $options = 0) {
298
        $this->client->openFolder($this->folder_path);
299
        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

299
        return imap_mail_copy(/** @scrutinizer ignore-type */ $this->client->getConnection(), $this->uid, $mailbox, IMAP::CP_UID);
Loading history...
300
    }
301
302
    /**
303
     * Move the current Messages to a mailbox
304
     *
305
     * @param $mailbox
306
     * @param int $options
307
     *
308
     * @return bool
309
     * @throws Exceptions\ConnectionFailedException
310
     */
311
    public function move($mailbox, $options = 0) {
312
        $this->client->openFolder($this->folder_path);
313
        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

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

372
                    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...
373
                        $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

373
                        $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...
374
                    }
375
                }
376
            });
377
        }
378
379
        return $body;
380
    }
381
382
    /**
383
     * Parse all defined headers
384
     *
385
     * @return void
386
     * @throws Exceptions\ConnectionFailedException
387
     * @throws InvalidMessageDateException
388
     */
389
    private function parseHeader() {
390
        $this->client->openFolder($this->folder_path);
391
        $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

391
        $this->header = $header = imap_fetchheader(/** @scrutinizer ignore-type */ $this->client->getConnection(), $this->uid, IMAP::FT_UID);
Loading history...
392
393
        $this->priority = $this->extractPriority($this->header);
394
395
        if ($this->header) {
396
            $header = imap_rfc822_parse_headers($this->header);
397
        }
398
399
        if (property_exists($header, 'subject')) {
400
            if($this->config['decoder']['message']['subject'] === 'utf-8') {
401
                $this->subject = imap_utf8($header->subject);
402
            }else{
403
                $this->subject = mb_decode_mimeheader($header->subject);
404
            }
405
        }
406
407
        foreach(['from', 'to', 'cc', 'bcc', 'reply_to', 'sender'] as $part){
408
            $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

408
            $this->extractHeaderAddressPart(/** @scrutinizer ignore-type */ $header, $part);
Loading history...
409
        }
410
411
        if (property_exists($header, 'references')) {
412
            $this->references = $header->references;
413
        }
414
        if (property_exists($header, 'in_reply_to')) {
415
            $this->in_reply_to = str_replace(['<', '>'], '', $header->in_reply_to);
416
        }
417
        if (property_exists($header, 'message_id')) {
418
            $this->message_id = str_replace(['<', '>'], '', $header->message_id);
419
        }
420
        if (property_exists($header, 'Msgno')) {
421
            $messageNo = (int) trim($header->Msgno);
422
            $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

422
            $this->message_no = ($this->fetch_options == IMAP::FT_UID) ? $messageNo : imap_msgno(/** @scrutinizer ignore-type */ $this->client->getConnection(), $messageNo);
Loading history...
423
        } else {
424
            $this->message_no = imap_msgno($this->client->getConnection(), $this->getUid());
425
        }
426
427
        $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

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

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

568
            $this->header_info = imap_headerinfo($this->client->getConnection(), /** @scrutinizer ignore-type */ $this->getMessageNo());
Loading history...
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

568
            $this->header_info = imap_headerinfo(/** @scrutinizer ignore-type */ $this->client->getConnection(), $this->getMessageNo());
Loading history...
569
        }
570
571
        return $this->header_info;
572
    }
573
574
    /**
575
     * Extract a given part as address array from a given header
576
     * @param object $header
577
     * @param string $part
578
     */
579
    private function extractHeaderAddressPart($header, $part) {
580
        if (property_exists($header, $part)) {
581
            $this->$part = $this->parseAddresses($header->$part);
582
        }
583
    }
584
585
    /**
586
     * Parse Addresses
587
     * @param $list
588
     *
589
     * @return array
590
     */
591
    private function parseAddresses($list) {
592
        $addresses = [];
593
594
        foreach ($list as $item) {
595
            $address = (object) $item;
596
597
            if (!property_exists($address, 'mailbox')) {
598
                $address->mailbox = false;
599
            }
600
            if (!property_exists($address, 'host')) {
601
                $address->host = false;
602
            }
603
            if (!property_exists($address, 'personal')) {
604
                $address->personal = false;
605
            } else {
606
                $personalParts = imap_mime_header_decode($address->personal);
607
608
                if(is_array($personalParts)) {
609
                    $address->personal = '';
610
                    foreach ($personalParts as $p) {
611
                        $address->personal .= $p->text;
612
                    }
613
                }
614
            }
615
616
            $address->mail = ($address->mailbox && $address->host) ? $address->mailbox.'@'.$address->host : false;
617
            $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

617
            $address->full = ($address->personal) ? $address->personal.' <'./** @scrutinizer ignore-type */ $address->mail.'>' : $address->mail;
Loading history...
618
619
            $addresses[] = $address;
620
        }
621
622
        return $addresses;
623
    }
624
625
    /**
626
     * Parse the Message body
627
     *
628
     * @return $this
629
     * @throws Exceptions\ConnectionFailedException
630
     */
631
    public function parseBody() {
632
        $this->client->openFolder($this->folder_path);
633
        $this->structure = imap_fetchstructure($this->client->getConnection(), $this->uid, IMAP::FT_UID);
0 ignored issues
show
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...
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

633
        $this->structure = imap_fetchstructure(/** @scrutinizer ignore-type */ $this->client->getConnection(), $this->uid, IMAP::FT_UID);
Loading history...
634
635
        if(property_exists($this->structure, 'parts')){
636
            $parts = $this->structure->parts;
637
638
            foreach ($parts as $part)  {
639
                foreach ($part->parameters as $parameter)  {
640
                    if($parameter->attribute == "charset")  {
641
                        $encoding = $parameter->value;
642
643
                        $encoding = preg_replace('/Content-Transfer-Encoding/', '', $encoding);
644
                        $encoding = preg_replace('/iso-8859-8-i/', 'iso-8859-8', $encoding);
645
646
                        $parameter->value = $encoding;
647
                    }
648
                }
649
            }
650
        }
651
652
        $this->fetchStructure($this->structure);
653
654
        return $this;
655
    }
656
657
    /**
658
     * Fetch the Message structure
659
     *
660
     * @param $structure
661
     * @param mixed $partNumber
662
     *
663
     * @throws Exceptions\ConnectionFailedException
664
     */
665
    private function fetchStructure($structure, $partNumber = null) {
666
        $this->client->openFolder($this->folder_path);
667
668
        if ($structure->type == IMAP::MESSAGE_TYPE_TEXT &&
669
            ($structure->ifdisposition == 0 ||
670
                ($structure->ifdisposition == 1 && !isset($structure->parts) && $partNumber != null)
671
            )
672
        ) {
673
            if (strtolower($structure->subtype) == "plain" || strtolower($structure->subtype) == "csv") {
674
                if (!$partNumber) {
675
                    $partNumber = 1;
676
                }
677
678
                $encoding = $this->getEncoding($structure);
679
680
                $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

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

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

993
        $status = imap_mail_move(/** @scrutinizer ignore-type */ $this->client->getConnection(), $this->uid, $mailbox, IMAP::CP_UID);
Loading history...
994
995
        if($status === true){
996
            if($expunge) $this->client->expunge();
997
            $this->client->openFolder($target_folder->path);
998
999
            return $target_folder->getMessage($target_status->uidnext, null, $this->fetch_options, $this->fetch_body, $this->fetch_attachment, $this->fetch_flags);
1000
        }
1001
1002
        return null;
1003
    }
1004
1005
    /**
1006
     * Delete the current Message
1007
     * @param bool $expunge
1008
     *
1009
     * @return bool
1010
     * @throws Exceptions\ConnectionFailedException
1011
     */
1012
    public function delete($expunge = true) {
1013
        $this->client->openFolder($this->folder_path);
1014
1015
        $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

1015
        $status = imap_delete(/** @scrutinizer ignore-type */ $this->client->getConnection(), $this->uid, IMAP::FT_UID);
Loading history...
1016
        if($expunge) $this->client->expunge();
1017
1018
        return $status;
1019
    }
1020
1021
    /**
1022
     * Restore a deleted Message
1023
     * @param boolean $expunge
1024
     *
1025
     * @return bool
1026
     * @throws Exceptions\ConnectionFailedException
1027
     */
1028
    public function restore($expunge = true) {
1029
        $this->client->openFolder($this->folder_path);
1030
1031
        $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

1031
        $status = imap_undelete(/** @scrutinizer ignore-type */ $this->client->getConnection(), $this->uid, IMAP::FT_UID);
Loading history...
1032
        if($expunge) $this->client->expunge();
1033
1034
        return $status;
1035
    }
1036
1037
    /**
1038
     * Get all message attachments.
1039
     *
1040
     * @return AttachmentCollection
1041
     */
1042
    public function getAttachments() {
1043
        return $this->attachments;
1044
    }
1045
1046
    /**
1047
     * Checks if there are any attachments present
1048
     *
1049
     * @return boolean
1050
     */
1051
    public function hasAttachments() {
1052
        return $this->attachments->isEmpty() === false;
1053
    }
1054
1055
    /**
1056
     * Set a given flag
1057
     * @param string|array $flag
1058
     *
1059
     * @return bool
1060
     * @throws Exceptions\ConnectionFailedException
1061
     */
1062
    public function setFlag($flag) {
1063
        $this->client->openFolder($this->folder_path);
1064
1065
        $flag = "\\".trim(is_array($flag) ? implode(" \\", $flag) : $flag);
1066
        $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

1066
        $status = imap_setflag_full(/** @scrutinizer ignore-type */ $this->client->getConnection(), $this->getUid(), $flag, SE_UID);
Loading history...
1067
        $this->parseFlags();
1068
1069
        return $status;
1070
    }
1071
1072
    /**
1073
     * Unset a given flag
1074
     * @param string|array $flag
1075
     *
1076
     * @return bool
1077
     * @throws Exceptions\ConnectionFailedException
1078
     */
1079
    public function unsetFlag($flag) {
1080
        $this->client->openFolder($this->folder_path);
1081
1082
        $flag = "\\".trim(is_array($flag) ? implode(" \\", $flag) : $flag);
1083
        $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

1083
        $status = imap_clearflag_full(/** @scrutinizer ignore-type */ $this->client->getConnection(), $this->getUid(), $flag, SE_UID);
Loading history...
1084
        $this->parseFlags();
1085
1086
        return $status;
1087
    }
1088
1089
    /**
1090
     * @return null|object|string
1091
     * @throws Exceptions\ConnectionFailedException
1092
     */
1093
    public function getRawBody() {
1094
        if ($this->raw_body === null) {
1095
            $this->client->openFolder($this->folder_path);
1096
1097
            $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

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