Completed
Push — master ( cd9168...92912a )
by Malte
02:14
created

Message::make()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 36
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 25
c 1
b 0
f 0
dl 0
loc 36
rs 9.52
cc 3
nc 4
nop 8

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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\PHPIMAP;
14
15
use Carbon\Carbon;
16
use Webklex\PHPIMAP\Exceptions\InvalidMessageDateException;
17
use Webklex\PHPIMAP\Exceptions\MaskNotFoundException;
18
use Webklex\PHPIMAP\Exceptions\MessageContentFetchingException;
19
use Webklex\PHPIMAP\Exceptions\MessageFlagException;
20
use Webklex\PHPIMAP\Exceptions\MessageHeaderFetchingException;
21
use Webklex\PHPIMAP\Exceptions\MethodNotFoundException;
22
use Webklex\PHPIMAP\Support\AttachmentCollection;
23
use Webklex\PHPIMAP\Support\FlagCollection;
24
use Webklex\PHPIMAP\Support\Masks\MessageMask;
25
use Illuminate\Support\Str;
26
use Webklex\PHPIMAP\Support\MessageCollection;
27
use Webklex\PHPIMAP\Traits\HasEvents;
28
29
/**
30
 * Class Message
31
 *
32
 * @package Webklex\PHPIMAP
33
 *
34
 * @property integer msglist
35
 * @property integer uid
36
 * @property integer msgn
37
 * @property string subject
38
 * @property string message_id
39
 * @property string message_no
40
 * @property string references
41
 * @property carbon date
42
 * @property array from
43
 * @property array to
44
 * @property array cc
45
 * @property array bcc
46
 * @property array reply_to
47
 * @property array in_reply_to
48
 * @property array sender
49
 *
50
 * @method integer getMsglist()
51
 * @method integer setMsglist(integer $msglist)
52
 * @method integer getUid()
53
 * @method integer getMsgn()
54
 * @method integer getPriority()
55
 * @method integer setPriority(integer $priority)
56
 * @method string getSubject()
57
 * @method string setSubject(string $subject)
58
 * @method string getMessageId()
59
 * @method string setMessageId(string $message_id)
60
 * @method string getMessageNo()
61
 * @method string setMessageNo(string $message_no)
62
 * @method string getReferences()
63
 * @method string setReferences(string $references)
64
 * @method carbon getDate()
65
 * @method carbon setDate(carbon $date)
66
 * @method array getFrom()
67
 * @method array setFrom(array $from)
68
 * @method array getTo()
69
 * @method array setTo(array $to)
70
 * @method array getCc()
71
 * @method array setCc(array $cc)
72
 * @method array getBcc()
73
 * @method array setBcc(array $bcc)
74
 * @method array getReplyTo()
75
 * @method array setReplyTo(array $reply_to)
76
 * @method array getInReplyTo()
77
 * @method array setInReplyTo(array $in_reply_to)
78
 * @method array getSender()
79
 * @method array setSender(array $sender)
80
 */
81
class Message {
82
    use HasEvents;
83
84
    /**
85
     * Client instance
86
     *
87
     * @var Client
88
     */
89
    private $client = Client::class;
90
91
    /**
92
     * Default mask
93
     *
94
     * @var string $mask
95
     */
96
    protected $mask = MessageMask::class;
97
98
    /**
99
     * Used config
100
     *
101
     * @var array $config
102
     */
103
    protected $config = [];
104
105
    /**
106
     * Attribute holder
107
     *
108
     * @var array $attributes
109
     */
110
    protected $attributes = [
111
        'message_no' => null,
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
     * @var integer
130
     */
131
    protected $sequence = IMAP::NIL;
132
133
    /**
134
     * Fetch body options
135
     *
136
     * @var bool
137
     */
138
    public $fetch_body = null;
139
140
    /**
141
     * Fetch flags options
142
     *
143
     * @var bool
144
     */
145
    public $fetch_flags = null;
146
147
    /**
148
     * @var Header $header
149
     */
150
    public $header = null;
151
152
    /**
153
     * Raw message body
154
     *
155
     * @var null|string $raw_body
156
     */
157
    public $raw_body = null;
158
159
    /**
160
     * Message structure
161
     *
162
     * @var Structure $structure
163
     */
164
    protected $structure = null;
165
166
    /**
167
     * Message body components
168
     *
169
     * @var array   $bodies
170
     * @var AttachmentCollection|array $attachments
171
     * @var FlagCollection|array       $flags
172
     */
173
    public $bodies = [];
174
    public $attachments = [];
175
    public $flags = [];
176
177
    /**
178
     * A list of all available and supported flags
179
     *
180
     * @var array $available_flags
181
     */
182
    private $available_flags = null;
183
184
    /**
185
     * Message constructor.
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_flags
192
     * @param integer $sequence
193
     *
194
     * @throws Exceptions\ConnectionFailedException
195
     * @throws InvalidMessageDateException
196
     * @throws Exceptions\RuntimeException
197
     * @throws MessageHeaderFetchingException
198
     * @throws MessageContentFetchingException
199
     * @throws Exceptions\EventNotFoundException
200
     * @throws MessageFlagException
201
     */
202
    public function __construct($uid, $msglist, Client $client, $fetch_options = null, $fetch_body = false, $fetch_flags = false, $sequence = null) {
203
204
        $default_mask = $client->getDefaultMessageMask();
205
        if($default_mask != null) {
206
            $this->mask = $default_mask;
207
        }
208
        $this->events["message"] = $client->getDefaultEvents("message");
209
        $this->events["flag"] = $client->getDefaultEvents("flag");
210
211
        $this->folder_path = $client->getFolderPath();
0 ignored issues
show
Documentation Bug introduced by
It seems like $client->getFolderPath() of type Webklex\PHPIMAP\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...
212
213
        $this->config = ClientManager::get('options');
214
        $this->available_flags = ClientManager::get('flags');
215
216
        $this->setSequence($sequence);
217
        $this->setFetchOption($fetch_options);
218
        $this->setFetchBodyOption($fetch_body);
219
        $this->setFetchFlagsOption($fetch_flags);
220
221
        $this->attachments = AttachmentCollection::make([]);
222
        $this->flags = FlagCollection::make([]);
223
224
        $this->client = $client;
225
        $this->client->openFolder($this->folder_path);
0 ignored issues
show
Bug introduced by
$this->folder_path of type Webklex\PHPIMAP\Folder is incompatible with the type string expected by parameter $folder of Webklex\PHPIMAP\Client::openFolder(). ( Ignorable by Annotation )

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

225
        $this->client->openFolder(/** @scrutinizer ignore-type */ $this->folder_path);
Loading history...
226
227
        if ($this->sequence === IMAP::ST_UID) {
228
            $this->uid = $uid;
229
            $this->msgn = $this->client->getConnection()->getMessageNumber($this->uid);
0 ignored issues
show
Bug introduced by
The method getMessageNumber() does not exist on Webklex\PHPIMAP\Connection\Protocols\Protocol. Since it exists in all sub-types, consider adding an abstract or default implementation to Webklex\PHPIMAP\Connection\Protocols\Protocol. ( Ignorable by Annotation )

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

229
            $this->msgn = $this->client->getConnection()->/** @scrutinizer ignore-call */ getMessageNumber($this->uid);
Loading history...
230
        }else{
231
            $this->msgn = $uid;
232
            $this->uid = $this->client->getConnection()->getUid($this->msgn);
0 ignored issues
show
Bug introduced by
The method getUid() does not exist on Webklex\PHPIMAP\Connection\Protocols\Protocol. Since it exists in all sub-types, consider adding an abstract or default implementation to Webklex\PHPIMAP\Connection\Protocols\Protocol. ( Ignorable by Annotation )

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

232
            $this->uid = $this->client->getConnection()->/** @scrutinizer ignore-call */ getUid($this->msgn);
Loading history...
233
        }
234
        $this->msglist = $msglist;
235
236
        if ($this->fetch_options == IMAP::FT_PEEK) {
237
            $this->parseFlags();
238
        }
239
240
        $this->parseHeader();
241
242
        if ($this->getFetchBodyOption() === true) {
243
            $this->parseBody();
244
        }
245
246
        if ($this->getFetchFlagsOption() === true && $this->fetch_options !== IMAP::FT_PEEK) {
247
            $this->parseFlags();
248
        }
249
    }
250
251
    /**
252
     * Create a new instance without fetching the message header and providing them raw instead
253
     * @param int $uid
254
     * @param int|null $msglist
255
     * @param Client $client
256
     * @param string $raw_header
257
     * @param string $raw_body
258
     * @param string $raw_flags
259
     * @param null $fetch_options
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $fetch_options is correct as it would always require null to be passed?
Loading history...
260
     * @param null $sequence
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $sequence is correct as it would always require null to be passed?
Loading history...
261
     *
262
     * @return Message
263
     * @throws Exceptions\ConnectionFailedException
264
     * @throws Exceptions\EventNotFoundException
265
     * @throws InvalidMessageDateException
266
     * @throws MessageContentFetchingException
267
     * @throws \ReflectionException
268
     * @throws MessageFlagException
269
     * @throws Exceptions\RuntimeException
270
     */
271
    public static function make($uid, $msglist, Client $client, $raw_header, $raw_body, $raw_flags, $fetch_options = null, $sequence = null){
272
        $reflection = new \ReflectionClass(self::class);
273
        /** @var self $instance */
274
        $instance = $reflection->newInstanceWithoutConstructor();
275
276
        $default_mask = $client->getDefaultMessageMask();
277
        if($default_mask != null) {
278
            $instance->setMask($default_mask);
279
        }
280
        $instance->setEvents([
281
            "message" => $client->getDefaultEvents("message"),
282
            "flag" => $client->getDefaultEvents("flag"),
283
        ]);
284
        $instance->setFolderPath($client->getFolderPath());
285
        $instance->setConfig(ClientManager::get('options'));
286
        $instance->setAvailableFlags(ClientManager::get('flags'));
287
        $instance->setSequence($sequence);
288
        $instance->setFetchOption($fetch_options);
289
290
        $instance->setAttachments(AttachmentCollection::make([]));
291
292
        $instance->setClient($client);
293
294
        if ($instance->getSequence() === IMAP::ST_UID) {
295
            $instance->setUid($uid);
296
            $instance->setMsglist($msglist);
297
        }else{
298
            $instance->setMsgn($uid, $msglist);
0 ignored issues
show
Bug introduced by
It seems like $msglist can also be of type integer; however, parameter $msglist of Webklex\PHPIMAP\Message::setMsgn() does only seem to accept null, 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
            $instance->setMsgn($uid, /** @scrutinizer ignore-type */ $msglist);
Loading history...
299
        }
300
301
        $instance->parseRawHeader($raw_header);
302
        $instance->parseRawFlags($raw_flags);
303
        $instance->parseRawBody($raw_body);
304
        $instance->peek();
305
306
        return $instance;
307
    }
308
309
    /**
310
     * Call dynamic attribute setter and getter methods
311
     * @param string $method
312
     * @param array $arguments
313
     *
314
     * @return mixed
315
     * @throws MethodNotFoundException
316
     */
317
    public function __call($method, $arguments) {
318
        if(strtolower(substr($method, 0, 3)) === 'get') {
319
            $name = Str::snake(substr($method, 3));
320
            return $this->get($name);
321
        }elseif (strtolower(substr($method, 0, 3)) === 'set') {
322
            $name = Str::snake(substr($method, 3));
323
324
            if(in_array($name, array_keys($this->attributes))) {
325
                return $this->__set($name, array_pop($arguments));
326
            }
327
328
        }
329
330
        throw new MethodNotFoundException("Method ".self::class.'::'.$method.'() is not supported');
331
    }
332
333
    /**
334
     * Magic setter
335
     * @param $name
336
     * @param $value
337
     *
338
     * @return mixed
339
     */
340
    public function __set($name, $value) {
341
        $this->attributes[$name] = $value;
342
343
        return $this->attributes[$name];
344
    }
345
346
    /**
347
     * Magic getter
348
     * @param $name
349
     *
350
     * @return mixed|null
351
     */
352
    public function __get($name) {
353
        return $this->get($name);
354
    }
355
356
    /**
357
     * Get an available message or message header attribute
358
     * @param $name
359
     *
360
     * @return mixed|null
361
     */
362
    public function get($name) {
363
        if(isset($this->attributes[$name])) {
364
            return $this->attributes[$name];
365
        }
366
367
        return $this->header->get($name);
368
    }
369
370
    /**
371
     * Check if the Message has a text body
372
     *
373
     * @return bool
374
     */
375
    public function hasTextBody() {
376
        return isset($this->bodies['text']);
377
    }
378
379
    /**
380
     * Get the Message text body
381
     *
382
     * @return mixed
383
     */
384
    public function getTextBody() {
385
        if (!isset($this->bodies['text'])) {
386
            return null;
387
        }
388
389
        return $this->bodies['text'];
390
    }
391
392
    /**
393
     * Check if the Message has a html body
394
     *
395
     * @return bool
396
     */
397
    public function hasHTMLBody() {
398
        return isset($this->bodies['html']);
399
    }
400
401
    /**
402
     * Get the Message html body
403
     *
404
     * @return string|null
405
     */
406
    public function getHTMLBody() {
407
        if (!isset($this->bodies['html'])) {
408
            return null;
409
        }
410
411
        return $this->bodies['html'];
412
    }
413
414
    /**
415
     * Parse all defined headers
416
     *
417
     * @throws Exceptions\ConnectionFailedException
418
     * @throws Exceptions\RuntimeException
419
     * @throws InvalidMessageDateException
420
     * @throws MessageHeaderFetchingException
421
     */
422
    private function parseHeader() {
423
        $sequence_id = $this->getSequenceId();
424
        $headers = $this->client->getConnection()->headers([$sequence_id], "RFC822", $this->sequence === IMAP::ST_UID);
0 ignored issues
show
Bug introduced by
The method headers() does not exist on Webklex\PHPIMAP\Connection\Protocols\Protocol. Since it exists in all sub-types, consider adding an abstract or default implementation to Webklex\PHPIMAP\Connection\Protocols\Protocol. ( Ignorable by Annotation )

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

424
        $headers = $this->client->getConnection()->/** @scrutinizer ignore-call */ headers([$sequence_id], "RFC822", $this->sequence === IMAP::ST_UID);
Loading history...
425
        if (!isset($headers[$sequence_id])) {
426
            throw new MessageHeaderFetchingException("no headers found", 0);
427
        }
428
429
        $this->parseRawHeader($headers[$sequence_id]);
430
    }
431
432
    /**
433
     * @param string $raw_header
434
     *
435
     * @throws InvalidMessageDateException
436
     */
437
    public function parseRawHeader($raw_header){
438
        $this->header = new Header($raw_header);
439
    }
440
441
    /**
442
     * Parse additional raw flags
443
     * @param $raw_flags
444
     */
445
    public function parseRawFlags($raw_flags) {
446
        $this->flags = FlagCollection::make([]);
447
448
        foreach($raw_flags as $flag) {
449
            if (strpos($flag, "\\") === 0){
450
                $flag = substr($flag, 1);
451
            }
452
            $flag_key = strtolower($flag);
453
            if (in_array($flag_key, $this->available_flags) || $this->available_flags === null) {
454
                $this->flags->put($flag_key, $flag);
455
            }
456
        }
457
    }
458
459
    /**
460
     * Parse additional flags
461
     *
462
     * @return void
463
     * @throws Exceptions\ConnectionFailedException
464
     * @throws MessageFlagException
465
     */
466
    private function parseFlags() {
467
        $this->client->openFolder($this->folder_path);
468
        $this->flags = FlagCollection::make([]);
469
470
        $sequence_id = $this->getSequenceId();
471
        try {
472
            $flags = $this->client->getConnection()->flags([$sequence_id], $this->sequence === IMAP::ST_UID);
0 ignored issues
show
Bug introduced by
The method flags() does not exist on Webklex\PHPIMAP\Connection\Protocols\Protocol. Since it exists in all sub-types, consider adding an abstract or default implementation to Webklex\PHPIMAP\Connection\Protocols\Protocol. ( Ignorable by Annotation )

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

472
            $flags = $this->client->getConnection()->/** @scrutinizer ignore-call */ flags([$sequence_id], $this->sequence === IMAP::ST_UID);
Loading history...
473
        } catch (Exceptions\RuntimeException $e) {
474
            throw new MessageFlagException("flag could not be fetched", 0, $e);
475
        }
476
477
        if (isset($flags[$sequence_id])) {
478
            $this->parseRawFlags($flags[$sequence_id]);
479
        }
480
    }
481
482
    /**
483
     * Parse the Message body
484
     *
485
     * @return $this
486
     * @throws Exceptions\ConnectionFailedException
487
     * @throws Exceptions\MessageContentFetchingException
488
     * @throws InvalidMessageDateException
489
     * @throws Exceptions\EventNotFoundException
490
     * @throws MessageFlagException
491
     */
492
    public function parseBody() {
493
        $this->client->openFolder($this->folder_path);
494
495
        $sequence_id = $this->getSequenceId();
496
        try {
497
            $contents = $this->client->getConnection()->content([$sequence_id], "RFC822", $this->sequence === IMAP::ST_UID);
0 ignored issues
show
Bug introduced by
The method content() does not exist on Webklex\PHPIMAP\Connection\Protocols\Protocol. Since it exists in all sub-types, consider adding an abstract or default implementation to Webklex\PHPIMAP\Connection\Protocols\Protocol. ( Ignorable by Annotation )

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

497
            $contents = $this->client->getConnection()->/** @scrutinizer ignore-call */ content([$sequence_id], "RFC822", $this->sequence === IMAP::ST_UID);
Loading history...
498
        } catch (Exceptions\RuntimeException $e) {
499
            throw new MessageContentFetchingException("failed to fetch content", 0);
500
        }
501
        if (!isset($contents[$sequence_id])) {
502
            throw new MessageContentFetchingException("no content found", 0);
503
        }
504
        $content = $contents[$sequence_id];
505
506
        $body = $this->parseRawBody($content);
507
        $this->peek();
508
509
        return $body;
510
    }
511
512
    /**
513
     * Handle auto "Seen" flag handling
514
     *
515
     * @throws Exceptions\ConnectionFailedException
516
     * @throws Exceptions\EventNotFoundException
517
     * @throws MessageFlagException
518
     */
519
    public function peek(){
520
        if ($this->fetch_options == IMAP::FT_PEEK) {
521
            if ($this->getFlags()->get("seen") == null) {
522
                $this->unsetFlag("Seen");
523
            }
524
        }elseif ($this->getFlags()->get("seen") != null) {
525
            $this->setFlag("Seen");
526
        }
527
    }
528
529
    /**
530
     * Parse a given message body
531
     * @param string $raw_body
532
     *
533
     * @return $this
534
     * @throws Exceptions\ConnectionFailedException
535
     * @throws InvalidMessageDateException
536
     * @throws MessageContentFetchingException
537
     */
538
    public function parseRawBody($raw_body) {
539
        $this->structure = new Structure($raw_body, $this->header);
540
        $this->fetchStructure($this->structure);
541
542
        return $this;
543
    }
544
545
    /**
546
     * Fetch the Message structure
547
     * @param $structure
548
     *
549
     * @throws Exceptions\ConnectionFailedException
550
     */
551
    private function fetchStructure($structure) {
552
        $this->client->openFolder($this->folder_path);
553
554
        foreach ($structure->parts as $part) {
555
            $this->fetchPart($part);
556
        }
557
    }
558
559
    /**
560
     * Fetch a given part
561
     * @param Part $part
562
     */
563
    private function fetchPart(Part $part) {
564
        if ($part->isAttachment()) {
565
            $this->fetchAttachment($part);
566
        }else{
567
            $encoding = $this->getEncoding($part);
568
569
            $content = $this->decodeString($part->content, $part->encoding);
570
571
            // We don't need to do convertEncoding() if charset is ASCII (us-ascii):
572
            //     ASCII is a subset of UTF-8, so all ASCII files are already UTF-8 encoded
573
            //     https://stackoverflow.com/a/11303410
574
            //
575
            // us-ascii is the same as ASCII:
576
            //     ASCII is the traditional name for the encoding system; the Internet Assigned Numbers Authority (IANA)
577
            //     prefers the updated name US-ASCII, which clarifies that this system was developed in the US and
578
            //     based on the typographical symbols predominantly in use there.
579
            //     https://en.wikipedia.org/wiki/ASCII
580
            //
581
            // convertEncoding() function basically means convertToUtf8(), so when we convert ASCII string into UTF-8 it gets broken.
582
            if ($encoding != 'us-ascii') {
583
                $content = $this->convertEncoding($content, $encoding);
584
            }
585
586
            $subtype = strtolower($part->subtype);
587
            $subtype = $subtype == "plain" || $subtype == "" ? "text" : $subtype;
588
589
            $this->bodies[$subtype] = $content;
590
        }
591
    }
592
593
    /**
594
     * Fetch the Message attachment
595
     * @param Part $part
596
     */
597
    protected function fetchAttachment($part) {
598
        $oAttachment = new Attachment($this, $part);
599
600
        if ($oAttachment->getName() !== null && $oAttachment->getSize() > 0) {
601
            if ($oAttachment->getId() !== null) {
0 ignored issues
show
introduced by
The condition $oAttachment->getId() !== null is always true.
Loading history...
602
                $this->attachments->put($oAttachment->getId(), $oAttachment);
603
            } else {
604
                $this->attachments->push($oAttachment);
605
            }
606
        }
607
    }
608
609
    /**
610
     * Fail proof setter for $fetch_option
611
     * @param $option
612
     *
613
     * @return $this
614
     */
615
    public function setFetchOption($option) {
616
        if (is_long($option) === true) {
617
            $this->fetch_options = $option;
618
        } elseif (is_null($option) === true) {
619
            $config = ClientManager::get('options.fetch', IMAP::FT_UID);
620
            $this->fetch_options = is_long($config) ? $config : 1;
621
        }
622
623
        return $this;
624
    }
625
626
    /**
627
     * Set the sequence type
628
     * @param int $sequence
629
     *
630
     * @return $this
631
     */
632
    public function setSequence($sequence) {
633
        if (is_long($sequence)) {
0 ignored issues
show
introduced by
The condition is_long($sequence) is always true.
Loading history...
634
            $this->sequence = $sequence;
635
        } elseif (is_null($sequence)) {
636
            $config = ClientManager::get('options.sequence', IMAP::ST_MSGN);
637
            $this->sequence = is_long($config) ? $config : IMAP::ST_MSGN;
638
        }
639
640
        return $this;
641
    }
642
643
    /**
644
     * Fail proof setter for $fetch_body
645
     * @param $option
646
     *
647
     * @return $this
648
     */
649
    public function setFetchBodyOption($option) {
650
        if (is_bool($option)) {
651
            $this->fetch_body = $option;
652
        } elseif (is_null($option)) {
653
            $config = ClientManager::get('options.fetch_body', true);
654
            $this->fetch_body = is_bool($config) ? $config : true;
655
        }
656
657
        return $this;
658
    }
659
660
    /**
661
     * Fail proof setter for $fetch_flags
662
     * @param $option
663
     *
664
     * @return $this
665
     */
666
    public function setFetchFlagsOption($option) {
667
        if (is_bool($option)) {
668
            $this->fetch_flags = $option;
669
        } elseif (is_null($option)) {
670
            $config = ClientManager::get('options.fetch_flags', true);
671
            $this->fetch_flags = is_bool($config) ? $config : true;
672
        }
673
674
        return $this;
675
    }
676
677
    /**
678
     * Decode a given string
679
     * @param $string
680
     * @param $encoding
681
     *
682
     * @return string
683
     */
684
    public function decodeString($string, $encoding) {
685
        switch ($encoding) {
686
            case IMAP::MESSAGE_ENC_BINARY:
687
                if (extension_loaded('imap')) {
688
                    return base64_decode(\imap_binary($string));
689
                }
690
                return base64_decode($string);
691
            case IMAP::MESSAGE_ENC_BASE64:
692
                return base64_decode($string);
693
            case IMAP::MESSAGE_ENC_8BIT:
694
            case IMAP::MESSAGE_ENC_QUOTED_PRINTABLE:
695
                return quoted_printable_decode($string);
696
            case IMAP::MESSAGE_ENC_7BIT:
697
            case IMAP::MESSAGE_ENC_OTHER:
698
            default:
699
                return $string;
700
        }
701
    }
702
703
    /**
704
     * Convert the encoding
705
     * @param $str
706
     * @param string $from
707
     * @param string $to
708
     *
709
     * @return mixed|string
710
     */
711
    public function convertEncoding($str, $from = "ISO-8859-2", $to = "UTF-8") {
712
713
        $from = EncodingAliases::get($from);
714
        $to = EncodingAliases::get($to);
715
716
        if ($from === $to) {
717
            return $str;
718
        }
719
720
        // We don't need to do convertEncoding() if charset is ASCII (us-ascii):
721
        //     ASCII is a subset of UTF-8, so all ASCII files are already UTF-8 encoded
722
        //     https://stackoverflow.com/a/11303410
723
        //
724
        // us-ascii is the same as ASCII:
725
        //     ASCII is the traditional name for the encoding system; the Internet Assigned Numbers Authority (IANA)
726
        //     prefers the updated name US-ASCII, which clarifies that this system was developed in the US and
727
        //     based on the typographical symbols predominantly in use there.
728
        //     https://en.wikipedia.org/wiki/ASCII
729
        //
730
        // convertEncoding() function basically means convertToUtf8(), so when we convert ASCII string into UTF-8 it gets broken.
731
        if (strtolower($from) == 'us-ascii' && $to == 'UTF-8') {
732
            return $str;
733
        }
734
735
        if (function_exists('iconv') && $from != 'UTF-7' && $to != 'UTF-7') {
736
            return @iconv($from, $to.'//IGNORE', $str);
737
        } else {
738
            if (!$from) {
739
                return mb_convert_encoding($str, $to);
740
            }
741
            return mb_convert_encoding($str, $to, $from);
742
        }
743
    }
744
745
    /**
746
     * Get the encoding of a given abject
747
     * @param object|string $structure
748
     *
749
     * @return string
750
     */
751
    public function getEncoding($structure) {
752
        if (property_exists($structure, 'parameters')) {
753
            foreach ($structure->parameters as $parameter) {
754
                if (strtolower($parameter->attribute) == "charset") {
755
                    return EncodingAliases::get($parameter->value);
756
                }
757
            }
758
        }elseif (property_exists($structure, 'charset')){
759
            return EncodingAliases::get($structure->charset);
760
        }elseif (is_string($structure) === true){
761
            return mb_detect_encoding($structure);
762
        }
763
764
        return 'UTF-8';
765
    }
766
767
    /**
768
     * Get the messages folder
769
     *
770
     * @return mixed
771
     * @throws Exceptions\ConnectionFailedException
772
     * @throws Exceptions\FolderFetchingException
773
     */
774
    public function getFolder(){
775
        return $this->client->getFolder($this->folder_path);
776
    }
777
778
    /**
779
     * Create a message thread based on the current message
780
     * @param Folder|null $sent_folder
781
     * @param MessageCollection|null $thread
782
     * @param Folder|null $folder
783
     *
784
     * @return MessageCollection|null
785
     * @throws Exceptions\ConnectionFailedException
786
     * @throws Exceptions\FolderFetchingException
787
     * @throws Exceptions\GetMessagesFailedException
788
     */
789
    public function thread($sent_folder = null, &$thread = null, $folder = null){
790
        $thread = $thread ? $thread : MessageCollection::make([]);
791
        $folder = $folder ? $folder :  $this->getFolder();
792
        $sent_folder = $sent_folder ? $sent_folder : $this->client->getFolder(ClientManager::get("options.common_folders.sent", "INBOX/Sent"));
793
794
        /** @var Message $message */
795
        foreach($thread as $message) {
796
            if ($message->message_id == $this->message_id) {
797
                return $thread;
798
            }
799
        }
800
        $thread->push($this);
801
802
        $this->fetchThreadByInReplyTo($thread, $this->message_id, $folder, $folder, $sent_folder);
803
        $this->fetchThreadByInReplyTo($thread, $this->message_id, $sent_folder, $folder, $sent_folder);
804
805
        if (is_array($this->in_reply_to)) {
0 ignored issues
show
introduced by
The condition is_array($this->in_reply_to) is always true.
Loading history...
806
            foreach($this->in_reply_to as $in_reply_to) {
807
                $this->fetchThreadByMessageId($thread, $in_reply_to, $folder, $folder, $sent_folder);
808
                $this->fetchThreadByMessageId($thread, $in_reply_to, $sent_folder, $folder, $sent_folder);
809
            }
810
        }
811
812
        return $thread;
813
    }
814
815
    /**
816
     * Fetch a partial thread by message id
817
     * @param MessageCollection $thread
818
     * @param string $in_reply_to
819
     * @param Folder $primary_folder
820
     * @param Folder $secondary_folder
821
     * @param Folder $sent_folder
822
     *
823
     * @throws Exceptions\ConnectionFailedException
824
     * @throws Exceptions\GetMessagesFailedException
825
     */
826
    protected function fetchThreadByInReplyTo(&$thread, $in_reply_to, $primary_folder, $secondary_folder, $sent_folder){
827
        $primary_folder->query()->inReplyTo($in_reply_to)
828
        ->setFetchBody($this->getFetchBodyOption())
829
        ->leaveUnread()->get()->each(function($message) use(&$thread, $secondary_folder, $sent_folder){
830
            /** @var Message $message */
831
            $message->thread($sent_folder, $thread, $secondary_folder);
832
        });
833
    }
834
835
    /**
836
     * Fetch a partial thread by message id
837
     * @param MessageCollection $thread
838
     * @param string $message_id
839
     * @param Folder $primary_folder
840
     * @param Folder $secondary_folder
841
     * @param Folder $sent_folder
842
     *
843
     * @throws Exceptions\ConnectionFailedException
844
     * @throws Exceptions\GetMessagesFailedException
845
     */
846
    protected function fetchThreadByMessageId(&$thread, $message_id, $primary_folder, $secondary_folder, $sent_folder){
847
        $primary_folder->query()->messageId($message_id)
848
        ->setFetchBody($this->getFetchBodyOption())
849
        ->leaveUnread()->get()->each(function($message) use(&$thread, $secondary_folder, $sent_folder){
850
            /** @var Message $message */
851
            $message->thread($sent_folder, $thread, $secondary_folder);
852
        });
853
    }
854
855
    /**
856
     * Copy the current Messages to a mailbox
857
     * @param string $folder_path
858
     * @param boolean $expunge
859
     *
860
     * @return null|Message
861
     * @throws Exceptions\ConnectionFailedException
862
     * @throws Exceptions\FolderFetchingException
863
     * @throws Exceptions\RuntimeException
864
     * @throws InvalidMessageDateException
865
     * @throws MessageContentFetchingException
866
     * @throws MessageHeaderFetchingException
867
     * @throws Exceptions\EventNotFoundException
868
     * @throws MessageFlagException
869
     */
870
    public function copy($folder_path, $expunge = false) {
871
        $this->client->openFolder($folder_path);
872
        $status = $this->client->getConnection()->examineFolder($folder_path);
0 ignored issues
show
Bug introduced by
The method examineFolder() does not exist on Webklex\PHPIMAP\Connection\Protocols\Protocol. Since it exists in all sub-types, consider adding an abstract or default implementation to Webklex\PHPIMAP\Connection\Protocols\Protocol. ( Ignorable by Annotation )

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

872
        $status = $this->client->getConnection()->/** @scrutinizer ignore-call */ examineFolder($folder_path);
Loading history...
873
874
        if (isset($status["uidnext"])) {
875
            $next_uid = $status["uidnext"];
876
877
            /** @var Folder $folder */
878
            $folder = $this->client->getFolder($folder_path);
879
880
            $this->client->openFolder($this->folder_path);
881
            if ($this->client->getConnection()->copyMessage($folder->path, $this->getSequenceId(), null, $this->sequence === IMAP::ST_UID) == true) {
0 ignored issues
show
Bug introduced by
The method copyMessage() does not exist on Webklex\PHPIMAP\Connection\Protocols\Protocol. Since it exists in all sub-types, consider adding an abstract or default implementation to Webklex\PHPIMAP\Connection\Protocols\Protocol. ( Ignorable by Annotation )

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

881
            if ($this->client->getConnection()->/** @scrutinizer ignore-call */ copyMessage($folder->path, $this->getSequenceId(), null, $this->sequence === IMAP::ST_UID) == true) {
Loading history...
882
                return $this->fetchNewMail($folder, $next_uid, "copied", $expunge);
883
            }
884
        }
885
886
        return null;
887
    }
888
889
    /**
890
     * Move the current Messages to a mailbox
891
     * @param string $folder_path
892
     * @param boolean $expunge
893
     *
894
     * @return Message|null
895
     * @throws Exceptions\ConnectionFailedException
896
     * @throws Exceptions\FolderFetchingException
897
     * @throws Exceptions\RuntimeException
898
     * @throws InvalidMessageDateException
899
     * @throws MessageContentFetchingException
900
     * @throws MessageHeaderFetchingException
901
     * @throws Exceptions\EventNotFoundException
902
     * @throws MessageFlagException
903
     */
904
    public function move($folder_path, $expunge = false) {
905
        $this->client->openFolder($folder_path);
906
        $status = $this->client->getConnection()->examineFolder($folder_path);
907
908
        if (isset($status["uidnext"])) {
909
            $next_uid = $status["uidnext"];
910
911
            /** @var Folder $folder */
912
            $folder = $this->client->getFolder($folder_path);
913
914
            $this->client->openFolder($this->folder_path);
915
            if ($this->client->getConnection()->moveMessage($folder->path, $this->getSequenceId(), null, $this->sequence === IMAP::ST_UID) == true) {
0 ignored issues
show
Bug introduced by
The method moveMessage() does not exist on Webklex\PHPIMAP\Connection\Protocols\Protocol. Since it exists in all sub-types, consider adding an abstract or default implementation to Webklex\PHPIMAP\Connection\Protocols\Protocol. ( Ignorable by Annotation )

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

915
            if ($this->client->getConnection()->/** @scrutinizer ignore-call */ moveMessage($folder->path, $this->getSequenceId(), null, $this->sequence === IMAP::ST_UID) == true) {
Loading history...
916
                return $this->fetchNewMail($folder, $next_uid, "moved", $expunge);
917
            }
918
        }
919
920
        return null;
921
    }
922
923
    /**
924
     * Fetch a new message and fire a given event
925
     * @param Folder $folder
926
     * @param int $next_uid
927
     * @param string $event
928
     * @param boolean $expunge
929
     *
930
     * @return mixed
931
     * @throws Exceptions\ConnectionFailedException
932
     * @throws Exceptions\EventNotFoundException
933
     * @throws Exceptions\RuntimeException
934
     * @throws InvalidMessageDateException
935
     * @throws MessageContentFetchingException
936
     * @throws MessageFlagException
937
     * @throws MessageHeaderFetchingException
938
     */
939
    protected function fetchNewMail($folder, $next_uid, $event, $expunge){
940
        if($expunge) $this->client->expunge();
941
942
        $this->client->openFolder($folder->path);
943
944
        if ($this->sequence === IMAP::ST_UID) {
945
            $sequence_id = $next_uid;
946
        }else{
947
            $sequence_id = $this->client->getConnection()->getMessageNumber($next_uid);
948
        }
949
950
        $message = $folder->query()->getMessage($sequence_id, null, $this->sequence);
951
        $event = $this->getEvent("message", $event);
952
        $event::dispatch($this, $message);
953
954
        return $message;
955
    }
956
957
    /**
958
     * Delete the current Message
959
     * @param bool $expunge
960
     *
961
     * @return bool
962
     * @throws Exceptions\ConnectionFailedException
963
     * @throws Exceptions\EventNotFoundException
964
     * @throws MessageFlagException
965
     */
966
    public function delete($expunge = true) {
967
        $status = $this->setFlag("Deleted");
968
        if($expunge) $this->client->expunge();
969
970
        $event = $this->getEvent("message", "deleted");
971
        $event::dispatch($this);
972
973
        return $status;
974
    }
975
976
    /**
977
     * Restore a deleted Message
978
     * @param boolean $expunge
979
     *
980
     * @return bool
981
     * @throws Exceptions\ConnectionFailedException
982
     * @throws Exceptions\EventNotFoundException
983
     * @throws MessageFlagException
984
     */
985
    public function restore($expunge = true) {
986
        $status = $this->unsetFlag("Deleted");
987
        if($expunge) $this->client->expunge();
988
989
        $event = $this->getEvent("message", "restored");
990
        $event::dispatch($this);
991
992
        return $status;
993
    }
994
995
    /**
996
     * Set a given flag
997
     * @param string|array $flag
998
     *
999
     * @return bool
1000
     * @throws Exceptions\ConnectionFailedException
1001
     * @throws MessageFlagException
1002
     * @throws Exceptions\EventNotFoundException
1003
     */
1004
    public function setFlag($flag) {
1005
        $this->client->openFolder($this->folder_path);
1006
        $flag = "\\".trim(is_array($flag) ? implode(" \\", $flag) : $flag);
1007
        $sequence_id = $this->getSequenceId();
1008
        try {
1009
            $status = $this->client->getConnection()->store([$flag], $sequence_id, $sequence_id, "+", true, $this->sequence === IMAP::ST_UID);
0 ignored issues
show
Bug introduced by
The method store() does not exist on Webklex\PHPIMAP\Connection\Protocols\Protocol. Since it exists in all sub-types, consider adding an abstract or default implementation to Webklex\PHPIMAP\Connection\Protocols\Protocol. ( Ignorable by Annotation )

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

1009
            $status = $this->client->getConnection()->/** @scrutinizer ignore-call */ store([$flag], $sequence_id, $sequence_id, "+", true, $this->sequence === IMAP::ST_UID);
Loading history...
1010
        } catch (Exceptions\RuntimeException $e) {
1011
            throw new MessageFlagException("flag could not be set", 0, $e);
1012
        }
1013
        $this->parseFlags();
1014
1015
        $event = $this->getEvent("flag", "new");
1016
        $event::dispatch($this, $flag);
1017
1018
        return $status;
1019
    }
1020
1021
    /**
1022
     * Unset a given flag
1023
     * @param string|array $flag
1024
     *
1025
     * @return bool
1026
     * @throws Exceptions\ConnectionFailedException
1027
     * @throws Exceptions\EventNotFoundException
1028
     * @throws MessageFlagException
1029
     */
1030
    public function unsetFlag($flag) {
1031
        $this->client->openFolder($this->folder_path);
1032
1033
        $flag = "\\".trim(is_array($flag) ? implode(" \\", $flag) : $flag);
1034
        $sequence_id = $this->getSequenceId();
1035
        try {
1036
            $status = $this->client->getConnection()->store([$flag], $sequence_id, $sequence_id, "-", true, $this->sequence === IMAP::ST_UID);
1037
        } catch (Exceptions\RuntimeException $e) {
1038
            throw new MessageFlagException("flag could not be removed", 0, $e);
1039
        }
1040
        $this->parseFlags();
1041
1042
        $event = $this->getEvent("flag", "deleted");
1043
        $event::dispatch($this, $flag);
1044
1045
        return $status;
1046
    }
1047
1048
    /**
1049
     * Set a given flag
1050
     * @param string|array $flag
1051
     *
1052
     * @return bool
1053
     * @throws Exceptions\ConnectionFailedException
1054
     * @throws MessageFlagException
1055
     * @throws Exceptions\EventNotFoundException
1056
     */
1057
    public function addFlag($flag) {
1058
        return $this->setFlag($flag);
1059
    }
1060
1061
    /**
1062
     * Unset a given flag
1063
     * @param string|array $flag
1064
     *
1065
     * @return bool
1066
     * @throws Exceptions\ConnectionFailedException
1067
     * @throws Exceptions\EventNotFoundException
1068
     * @throws MessageFlagException
1069
     */
1070
    public function removeFlag($flag) {
1071
        return $this->unsetFlag($flag);
1072
    }
1073
1074
    /**
1075
     * Get all message attachments.
1076
     *
1077
     * @return AttachmentCollection
1078
     */
1079
    public function getAttachments() {
1080
        return $this->attachments;
1081
    }
1082
1083
    /**
1084
     * Get all message attachments.
1085
     *
1086
     * @return AttachmentCollection
1087
     */
1088
    public function attachments(){
1089
        return $this->getAttachments();
1090
    }
1091
1092
    /**
1093
     * Checks if there are any attachments present
1094
     *
1095
     * @return boolean
1096
     */
1097
    public function hasAttachments() {
1098
        return $this->attachments->isEmpty() === false;
1099
    }
1100
1101
    /**
1102
     * Get the raw body
1103
     *
1104
     * @return string
1105
     * @throws Exceptions\ConnectionFailedException
1106
     */
1107
    public function getRawBody() {
1108
        if ($this->raw_body === null) {
1109
            $this->client->openFolder($this->folder_path);
1110
1111
            $this->raw_body = $this->structure->raw;
1112
        }
1113
1114
        return $this->raw_body;
1115
    }
1116
1117
    /**
1118
     * Get the message header
1119
     *
1120
     * @return Header
1121
     */
1122
    public function getHeader() {
1123
        return $this->header;
1124
    }
1125
1126
    /**
1127
     * Get the current client
1128
     *
1129
     * @return Client
1130
     */
1131
    public function getClient() {
1132
        return $this->client;
1133
    }
1134
1135
    /**
1136
     * Get the used fetch option
1137
     *
1138
     * @return integer
1139
     */
1140
    public function getFetchOptions() {
1141
        return $this->fetch_options;
1142
    }
1143
1144
    /**
1145
     * Get the used fetch body option
1146
     *
1147
     * @return boolean
1148
     */
1149
    public function getFetchBodyOption() {
1150
        return $this->fetch_body;
1151
    }
1152
1153
    /**
1154
     * Get the used fetch flags option
1155
     *
1156
     * @return boolean
1157
     */
1158
    public function getFetchFlagsOption() {
1159
        return $this->fetch_flags;
1160
    }
1161
1162
    /**
1163
     * Get all available bodies
1164
     *
1165
     * @return array
1166
     */
1167
    public function getBodies() {
1168
        return $this->bodies;
1169
    }
1170
1171
    /**
1172
     * Get all set flags
1173
     *
1174
     * @return FlagCollection
1175
     */
1176
    public function getFlags() {
1177
        return $this->flags;
1178
    }
1179
1180
    /**
1181
     * Get all set flags
1182
     *
1183
     * @return FlagCollection
1184
     */
1185
    public function flags(){
1186
        return $this->getFlags();
1187
    }
1188
1189
    /**
1190
     * Get the fetched structure
1191
     *
1192
     * @return Structure|null
1193
     */
1194
    public function getStructure(){
1195
        return $this->structure;
1196
    }
1197
1198
    /**
1199
     * Check if a message matches an other by comparing basic attributes
1200
     *
1201
     * @param  null|Message $message
1202
     * @return boolean
1203
     */
1204
    public function is(Message $message = null) {
1205
        if (is_null($message)) {
1206
            return false;
1207
        }
1208
1209
        return $this->uid == $message->uid
1210
            && $this->message_id == $message->message_id
1211
            && $this->subject == $message->subject
1212
            && $this->date->eq($message->date);
1213
    }
1214
1215
    /**
1216
     * Get all message attributes
1217
     *
1218
     * @return array
1219
     */
1220
    public function getAttributes(){
1221
        return array_merge($this->attributes, $this->header->getAttributes());
1222
    }
1223
1224
    /**
1225
     * Set the message mask
1226
     * @param $mask
1227
     *
1228
     * @return $this
1229
     */
1230
    public function setMask($mask){
1231
        if(class_exists($mask)){
1232
            $this->mask = $mask;
1233
        }
1234
1235
        return $this;
1236
    }
1237
1238
    /**
1239
     * Get the used message mask
1240
     *
1241
     * @return string
1242
     */
1243
    public function getMask(){
1244
        return $this->mask;
1245
    }
1246
1247
    /**
1248
     * Get a masked instance by providing a mask name
1249
     * @param string|null $mask
1250
     *
1251
     * @return mixed
1252
     * @throws MaskNotFoundException
1253
     */
1254
    public function mask($mask = null){
1255
        $mask = $mask !== null ? $mask : $this->mask;
1256
        if(class_exists($mask)){
1257
            return new $mask($this);
1258
        }
1259
1260
        throw new MaskNotFoundException("Unknown mask provided: ".$mask);
1261
    }
1262
1263
    /**
1264
     * Set the message path aka folder path
1265
     * @param $folder_path
1266
     *
1267
     * @return $this
1268
     */
1269
    public function setFolderPath($folder_path){
1270
        $this->folder_path = $folder_path;
1271
1272
        return $this;
1273
    }
1274
1275
    /**
1276
     * Set the config
1277
     * @param $config
1278
     *
1279
     * @return $this
1280
     */
1281
    public function setConfig($config){
1282
        $this->config = $config;
1283
1284
        return $this;
1285
    }
1286
1287
    /**
1288
     * Set the available flags
1289
     * @param $available_flags
1290
     *
1291
     * @return $this
1292
     */
1293
    public function setAvailableFlags($available_flags){
1294
        $this->available_flags = $available_flags;
1295
1296
        return $this;
1297
    }
1298
1299
    /**
1300
     * Set the attachment collection
1301
     * @param $attachments
1302
     *
1303
     * @return $this
1304
     */
1305
    public function setAttachments($attachments){
1306
        $this->attachments = $attachments;
1307
1308
        return $this;
1309
    }
1310
1311
    /**
1312
     * Set the flag collection
1313
     * @param $flags
1314
     *
1315
     * @return $this
1316
     */
1317
    public function setFlags($flags){
1318
        $this->flags = $flags;
1319
1320
        return $this;
1321
    }
1322
1323
    /**
1324
     * Set the client
1325
     * @param $client
1326
     *
1327
     * @throws Exceptions\ConnectionFailedException
1328
     * @return $this
1329
     */
1330
    public function setClient($client){
1331
        $this->client = $client;
1332
        $this->client->openFolder($this->folder_path);
1333
1334
        return $this;
1335
    }
1336
1337
    /**
1338
     * Set the message number
1339
     * @param int $uid
1340
     *
1341
     * @throws Exceptions\ConnectionFailedException
1342
     * @throws Exceptions\RuntimeException
1343
     * @return $this
1344
     */
1345
    public function setUid($uid){
1346
        $this->uid = $uid;
1347
        $this->msgn = $this->client->getConnection()->getMessageNumber($this->uid);
1348
        $this->msglist = null;
1349
1350
        return $this;
1351
    }
1352
1353
    /**
1354
     * Set the message number
1355
     * @param $msgn
1356
     * @param null $msglist
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $msglist is correct as it would always require null to be passed?
Loading history...
1357
     *
1358
     * @throws Exceptions\ConnectionFailedException
1359
     * @throws Exceptions\RuntimeException
1360
     * @return $this
1361
     */
1362
    public function setMsgn($msgn, $msglist = null){
1363
        $this->msgn = $msgn;
1364
        $this->msglist = $msglist;
1365
        $this->uid = $this->client->getConnection()->getUid($this->msgn);
1366
1367
        return $this;
1368
    }
1369
1370
    /**
1371
     * Get the current sequence type
1372
     *
1373
     * @return int
1374
     */
1375
    public function getSequence(){
1376
        return $this->sequence;
1377
    }
1378
1379
    /**
1380
     * Set the sequence type
1381
     *
1382
     * @return int
1383
     */
1384
    public function getSequenceId(){
1385
        return $this->sequence === IMAP::ST_UID ? $this->uid : $this->msgn;
1386
    }
1387
}
1388