Issues (1844)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  Header Injection
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

class/pear/Net/IMAP.php (62 issues)

1
<?php
2
//
3
// +----------------------------------------------------------------------+
4
// | PHP Version 4                                                        |
5
// +----------------------------------------------------------------------+
6
// | Copyright (c) 1997-2003 The PHP Group                                |
7
// +----------------------------------------------------------------------+
8
// | This source file is subject to version 2.02 of the PHP license,      |
9
// | that is bundled with this package in the file LICENSE, and is        |
10
// | available at through the world-wide-web at                           |
11
// | https://www.php.net/license/2_02.txt.                                 |
12
// | If you did not receive a copy of the PHP license and are unable to   |
13
// | obtain it through the world-wide-web, please send a note to          |
14
// | [email protected] so we can mail you a copy immediately.               |
15
// +----------------------------------------------------------------------+
16
// | Author: Damian Alejandro Fernandez Sosa <[email protected]>       |
17
// +----------------------------------------------------------------------+
18
19
require_once XHELP_PEAR_PATH . '/Net/IMAPProtocol.php';
20
21
/**
22
 * Provides an implementation of the IMAP protocol using PEAR's
23
 * Net_Socket:: class.
24
 *
25
 * @author  Damian Alejandro Fernandez Sosa <[email protected]>
26
 */
27
class Net_IMAP extends Net_IMAPProtocol
28
{
29
    /**
30
     * Constructor
31
     *
32
     * Instantiates a new Net_SMTP object, overriding any defaults
33
     * with parameters that are passed in.
34
     *
35
     * @param mixed $host
36
     * @param mixed $port
37
     */
38
    public function __construct($host = 'localhost', $port = 143)
39
    {
40
        Net_IMAPProtocol::__construct();
41
        $ret = $this->connect($host, $port);
0 ignored issues
show
The assignment to $ret is dead and can be removed.
Loading history...
42
    }
43
44
    /**
45
     * Attempt to connect to the IMAP server located at $host $port
46
     * @param string $host The IMAP server
47
     * @param string $port The IMAP port
48
     *
49
     *          It is only useful in a very few circunstances
50
     *          because the contructor already makes this job
51
     * @return \PEAR_Error|true success or
52
     *
53
     * @since  1.0
54
     */
55
    public function connect(string $host, string $port)
56
    {
57
        $ret = $this->cmdConnect($host, $port);
0 ignored issues
show
$port of type string is incompatible with the type integer expected by parameter $port of Net_IMAPProtocol::cmdConnect(). ( Ignorable by Annotation )

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

57
        $ret = $this->cmdConnect($host, /** @scrutinizer ignore-type */ $port);
Loading history...
58
        if (true === $ret) {
59
            return $ret;
60
        }
61
        if (empty($ret)) {
62
            return new PEAR_Error('Unexpected response on connection');
63
        }
64
        if (PEAR::isError($ret)) {
0 ignored issues
show
Bug Best Practice introduced by
The method PEAR::isError() is not static, but was called statically. ( Ignorable by Annotation )

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

64
        if (PEAR::/** @scrutinizer ignore-call */ isError($ret)) {
Loading history...
65
            return $ret;
66
        }
67
        if (isset($ret['RESPONSE']['CODE'])) {
68
            if ('OK' !== \mb_strtoupper($ret['RESPONSE']['CODE'])) {
69
                return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']);
70
            }
71
        }
72
73
        return $ret;
74
    }
75
76
    /**
77
     * Attempt to authenticate to the IMAP server.
78
     * @param string $user             The userid to authenticate as.
79
     * @param string $pass             The password to authenticate with.
80
     * @param string|bool   $useauthenticate  true: authenticate using
81
     *                                 the IMAP AUTHENTICATE command. false: authenticate using
82
     *                                 the IMAP AUTHENTICATE command. 'string': authenticate using
83
     *                                 the IMAP AUTHENTICATE command but using the authMethod in 'string'
84
     * @param bool   $selectMailbox    automaticaly select inbox on login (false does not)
85
     *
86
     * @return \PEAR_Error|true on success or PEAR_Error
87
     *
88
     * @since  1.0
89
     */
90
    public function login(string $user, string $pass, bool $useauthenticate = true, bool $selectMailbox = true)
91
    {
92
        if ($useauthenticate) {
93
            //$useauthenticate is a string if the user hardcodes an AUTHMethod
94
            // (the user calls $imap->login("user","password","CRAM-MD5"); for example!
95
96
            $method = is_string($useauthenticate) ? $useauthenticate : null;
0 ignored issues
show
The condition is_string($useauthenticate) is always false.
Loading history...
97
98
            //Try the selected Auth method
99
            if (PEAR::isError($ret = $this->cmdAuthenticate($user, $pass, $method))) {
0 ignored issues
show
Bug Best Practice introduced by
The method PEAR::isError() is not static, but was called statically. ( Ignorable by Annotation )

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

99
            if (PEAR::/** @scrutinizer ignore-call */ isError($ret = $this->cmdAuthenticate($user, $pass, $method))) {
Loading history...
100
                // Verify the methods that we have in common with the server
101
                if (is_array($this->_serverAuthMethods)) {
0 ignored issues
show
The condition is_array($this->_serverAuthMethods) is always false.
Loading history...
102
                    $commonMethods = array_intersect($this->supportedAuthMethods, $this->_serverAuthMethods);
103
                } else {
104
                    $this->_serverAuthMethods = null;
105
                }
106
                if (null === $this->_serverAuthMethods || 0 == count($commonMethods) || null === $this->supportedAuthMethods) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $commonMethods does not seem to be defined for all execution paths leading up to this point.
Loading history...
107
                    // The server does not have any auth method, so I try LOGIN
108
                    if (PEAR::isError($ret = $this->cmdLogin($user, $pass))) {
109
                        return $ret;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $ret returns the type array which is incompatible with the documented return type PEAR_Error|true.
Loading history...
110
                    }
111
                } else {
112
                    return $ret;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $ret also could return the type array which is incompatible with the documented return type PEAR_Error|true.
Loading history...
113
                }
114
            }
115
            if ('OK' !== \mb_strtoupper($ret['RESPONSE']['CODE'])) {
116
                return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']);
117
            }
118
        } else {
119
            //The user request "PLAIN"  auth, we use the login command
120
            if (PEAR::isError($ret = $this->cmdLogin($user, $pass))) {
121
                return $ret;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $ret returns the type array which is incompatible with the documented return type PEAR_Error|true.
Loading history...
122
            }
123
            if ('OK' !== \mb_strtoupper($ret['RESPONSE']['CODE'])) {
124
                return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']);
125
            }
126
        }
127
128
        if ($selectMailbox) {
129
            //Select INBOX
130
            if (PEAR::isError($ret = $this->cmdSelect($this->getCurrentMailbox()))) {
131
                return $ret;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $ret returns the type array which is incompatible with the documented return type PEAR_Error|true.
Loading history...
132
            }
133
        }
134
        if ('OK' !== \mb_strtoupper($ret['RESPONSE']['CODE'])) {
135
            return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']);
136
        }
137
138
        return true;
139
    }
140
141
    /**
142
     * Disconnect function. Sends the QUIT command
143
     * and closes the socket.
144
     *
145
     * @param false $expungeOnExit
146
     * @return bool|\PEAR_Error Success/Failure
147
     */
148
    public function disconnect(bool $expungeOnExit = false)
149
    {
150
        if ($expungeOnExit) {
151
            $ret = $this->cmdExpunge();
152
            if ('OK' !== \mb_strtoupper($ret['RESPONSE']['CODE'])) {
153
                $ret = $this->cmdLogout();
154
155
                return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']);
156
            }
157
        }
158
        $ret = $this->cmdLogout();
159
        if ('OK' !== \mb_strtoupper($ret['RESPONSE']['CODE'])) {
160
            return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']);
161
        }
162
163
        return true;
164
    }
165
166
    /**
167
     * Changes  the default/current mailbox th $mailbox
168
     *
169
     * @param string $mailbox
170
     * @return bool|\PEAR_Error Success/Pear_Error Failure
171
     */
172
    public function selectMailbox(string $mailbox)
173
    {
174
        $ret = $this->cmdSelect($mailbox);
175
        if ('OK' !== \mb_strtoupper($ret['RESPONSE']['CODE'])) {
176
            return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']);
177
        }
178
179
        return true;
180
    }
181
182
    /**
183
     * Checks  the mailbox $mailbox
184
     *
185
     * @param string $mailbox
186
     * @return array|\PEAR_Error Success/Pear_Error Failure
187
     */
188
    public function examineMailbox(string $mailbox)
189
    {
190
        $ret = $this->cmdExamine($mailbox);
191
        if ('OK' !== \mb_strtoupper($ret['RESPONSE']['CODE'])) {
192
            return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']);
193
        }
194
195
        //$ret_aux["EXISTS"]=$ret["PARSED"]["EXISTS"];
196
        //$ret_aux["RECENT"]=$ret["PARSED"]["RECENT"];
197
        return $ret;
198
    }
199
200
    /**
201
     * Returns the raw headers of the specified message.
202
     *
203
     * @param int $msg_id Message number
204
     * @return mixed|\PEAR_Error   Either raw headers or false on error
205
     */
206
    public function getRawHeaders(int $msg_id)
207
    {
208
        $ret = $this->cmdFetch($msg_id, 'BODY[HEADER]');
209
        if ('OK' !== \mb_strtoupper($ret['RESPONSE']['CODE'])) {
210
            return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']);
211
        }
212
        $ret = $ret['PARSED'][0]['EXT']['BODY[HEADER]']['CONTENT'];
213
214
        return $ret;
215
    }
216
217
    /**
218
     * Returns the  headers of the specified message in an
219
     * associative array. Array keys are the header names, array
220
     * values are the header values. In the case of multiple headers
221
     * having the same names, eg Received:, the array value will be
222
     * an indexed array of all the header values.
223
     *
224
     * @param int $msg_id Message number
225
     * @return array Either array of headers or false on error
226
     */
227
    public function getParsedHeaders(int $msg_id): array
228
    {
229
        $ret = $this->getRawHeaders($msg_id);
230
231
        $raw_headers = rtrim($ret);
0 ignored issues
show
It seems like $ret can also be of type PEAR_Error; however, parameter $string of rtrim() does only seem to accept string, 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

231
        $raw_headers = rtrim(/** @scrutinizer ignore-type */ $ret);
Loading history...
232
        $raw_headers = preg_replace("/\r\n[ \t]+/", ' ', $raw_headers); // Unfold headers
233
        $raw_headers = explode("\r\n", $raw_headers);
234
        foreach ($raw_headers as $value) {
235
            $name  = mb_substr($value, 0, $pos = mb_strpos($value, ':'));
236
            $value = ltrim(mb_substr($value, $pos + 1));
237
            if (isset($headers[$name]) && is_array($headers[$name])) {
238
                $headers[$name][] = $value;
239
            } elseif (isset($headers[$name])) {
240
                $headers[$name] = [$headers[$name], $value];
241
            } else {
242
                $headers[$name] = $value;
243
            }
244
        }
245
246
        return $headers;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $headers does not seem to be defined for all execution paths leading up to this point.
Loading history...
247
    }
248
249
    /**
250
     * Returns an array containing the message ID, the size and the UID
251
     * of each message selected.
252
     * message selection can be a valid IMAP command, a number or an array of
253
     * messages
254
     *
255
     * @param array|int|null $msg_id Message number
256
     * @return array|\PEAR_Error   Either array of message data or PearError on error
257
     */
258
    public function getMessagesList(int $msg_id = null)
259
    {
260
        if (null !== $msg_id) {
261
            if (is_array($msg_id)) {
0 ignored issues
show
The condition is_array($msg_id) is always false.
Loading history...
262
                $message_set = $this->_getSearchListFromArray($msg_id);
263
            } else {
264
                $message_set = $msg_id;
265
            }
266
        } else {
267
            $message_set = '1:*';
268
        }
269
        $ret = $this->cmdFetch($message_set, '(RFC822.SIZE UID)');
270
        if ('OK' !== \mb_strtoupper($ret['RESPONSE']['CODE'])) {
271
            return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']);
272
        }
273
        foreach ($ret['PARSED'] as $msg) {
274
            $ret_aux[] = ['msg_id' => $msg['NRO'], 'size' => $msg['EXT']['RFC822.SIZE'], 'uidl' => $msg['EXT']['UID']];
275
        }
276
277
        return $ret_aux;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $ret_aux seems to be defined by a foreach iteration on line 273. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
278
    }
279
280
    /**
281
     * @param array|string|null $msg_id
282
     * @return array|\PEAR_Error
283
     */
284
    public function getSummary($msg_id = null)
285
    {
286
        if (null !== $msg_id) {
287
            if (is_array($msg_id)) {
288
                $message_set = $this->_getSearchListFromArray($msg_id);
289
            } else {
290
                $message_set = $msg_id;
291
            }
292
        } else {
293
            $message_set = '1:*';
294
        }
295
        $ret = $this->cmdFetch($message_set, '(RFC822.SIZE UID FLAGS ENVELOPE INTERNALDATE)');
296
        if ('OK' !== \mb_strtoupper($ret['RESPONSE']['CODE'])) {
297
            return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']);
298
        }
299
300
        if (isset($ret['PARSED'])) {
301
            foreach ($ret['PARSED'] as $i => $iValue) {
302
                $a                 = $ret['PARSED'][$i]['EXT']['ENVELOPE'];
303
                $a['MSG_NUM']      = $ret['PARSED'][$i]['NRO'];
304
                $a['UID']          = $ret['PARSED'][$i]['EXT']['UID'];
305
                $a['FLAGS']        = $ret['PARSED'][$i]['EXT']['FLAGS'];
306
                $a['INTERNALDATE'] = $ret['PARSED'][$i]['EXT']['INTERNALDATE'];
307
                $a['SIZE']         = $ret['PARSED'][$i]['EXT']['RFC822.SIZE'];
308
                $env[]             = $a;
309
                $a                 = null;
0 ignored issues
show
The assignment to $a is dead and can be removed.
Loading history...
310
            }
311
312
            return $env;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $env seems to be defined by a foreach iteration on line 301. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
313
        }
314
        //return $ret;
315
    }
316
317
    /**
318
     * Returns the body of the message with given message number.
319
     *
320
     * @param int $msg_id Message number
321
     * @return mixed|\PEAR_Error   Either message body or false on error
322
     */
323
    public function getBody(int $msg_id)
324
    {
325
        $ret = $this->cmdFetch($msg_id, 'BODY[TEXT]');
326
        if ('OK' !== \mb_strtoupper($ret['RESPONSE']['CODE'])) {
327
            return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']);
328
        }
329
        $ret = $ret['PARSED'][0]['EXT']['BODY[TEXT]']['CONTENT'];
330
        //$ret=$resp["PARSED"][0]["EXT"]["RFC822"]["CONTENT"];
331
        return $ret;
332
    }
333
334
    /**
335
     * Returns the entire message with given message number.
336
     *
337
     * @param array|int|null $msg_id Message number
338
     * @param bool     $indexIsMessageNumber
339
     * @return array|\PEAR_Error Either entire message or false on error
340
     */
341
    public function getMessages(int $msg_id = null, bool $indexIsMessageNumber = true)
342
    {
343
        //$resp=$this->cmdFetch($msg_id,"(BODY[TEXT] BODY[HEADER])");
344
        if (null !== $msg_id) {
345
            if (is_array($msg_id)) {
0 ignored issues
show
The condition is_array($msg_id) is always false.
Loading history...
346
                $message_set = $this->_getSearchListFromArray($msg_id);
347
            } else {
348
                $message_set = $msg_id;
349
            }
350
        } else {
351
            $message_set = '1:*';
352
        }
353
354
        $ret = $this->cmdFetch($message_set, 'RFC822');
355
        if ('OK' !== \mb_strtoupper($ret['RESPONSE']['CODE'])) {
356
            return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']);
357
        }
358
        if (isset($ret['PARSED'])) {
359
            foreach ($ret['PARSED'] as $msg) {
360
                if (isset($msg['EXT']['RFC822']['CONTENT'])) {
361
                    if ($indexIsMessageNumber) {
362
                        $ret_aux[$msg['NRO']] = $msg['EXT']['RFC822']['CONTENT'];
363
                    } else {
364
                        $ret_aux[] = $msg['EXT']['RFC822']['CONTENT'];
365
                    }
366
                }
367
            }
368
369
            return $ret_aux;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $ret_aux does not seem to be defined for all execution paths leading up to this point.
Loading history...
370
        }
371
372
        return [];
373
    }
374
375
    /**
376
     * Returns number of messages in this mailbox
377
     *
378
     * @param string $mailbox the mailbox
379
     * @return int|mixed|\PEAR_Error Either number of messages or Pear_Error on error
380
     */
381
    public function getNumberOfMessages(string $mailbox = '')
382
    {
383
        if ('' === $mailbox || null === $mailbox) {
384
            $mailbox = $this->getCurrentMailbox();
385
        }
386
        $ret = $this->cmdStatus($mailbox, 'MESSAGES');
387
        if ('OK' !== \mb_strtoupper($ret['RESPONSE']['CODE'])) {
388
            return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']);
389
        }
390
        if (isset($ret['PARSED']['STATUS']['ATTRIBUTES']['MESSAGES'])) {
391
            if (!is_numeric($ret['PARSED']['STATUS']['ATTRIBUTES']['MESSAGES'])) {
392
                // if this array does not exists means that there is no messages in the mailbox
393
                return 0;
394
            }
395
396
            return $ret['PARSED']['STATUS']['ATTRIBUTES']['MESSAGES'];
397
        }
398
399
        return 0;
400
    }
401
402
    /**
403
     * Returns number of UnSeen messages in this mailbox
404
     *
405
     * @param string $mailbox the mailbox
406
     * @return int|mixed|\PEAR_Error Either number of messages or Pear_Error on error
407
     */
408
    public function getNumberOfUnSeenMessages(string $mailbox = '')
409
    {
410
        if ('' === $mailbox) {
411
            $mailbox = $this->getCurrentMailbox();
412
        }
413
        $ret = $this->cmdStatus($mailbox, 'UNSEEN');
414
        if ('OK' !== \mb_strtoupper($ret['RESPONSE']['CODE'])) {
415
            return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']);
416
        }
417
        if (isset($ret['PARSED']['STATUS']['ATTRIBUTES']['UNSEEN'])) {
418
            if (!is_numeric($ret['PARSED']['STATUS']['ATTRIBUTES']['UNSEEN'])) {
419
                // if this array does not exists means that there is no messages in the mailbox
420
                return 0;
421
            }
422
423
            return $ret['PARSED']['STATUS']['ATTRIBUTES']['UNSEEN'];
424
        }
425
426
        return 0;
427
    }
428
429
    /**
430
     * Returns number of UnSeen messages in this mailbox
431
     *
432
     * @param string $mailbox the mailbox
433
     * @return int|mixed|\PEAR_Error Either number of messages or Pear_Error on error
434
     */
435
    public function getNumberOfRecentMessages(string $mailbox = '')
436
    {
437
        if ('' === $mailbox) {
438
            $mailbox = $this->getCurrentMailbox();
439
        }
440
        $ret = $this->cmdStatus($mailbox, 'RECENT');
441
        if ('OK' !== \mb_strtoupper($ret['RESPONSE']['CODE'])) {
442
            return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']);
443
        }
444
        if (isset($ret['PARSED']['STATUS']['ATTRIBUTES']['RECENT'])) {
445
            if (!is_numeric($ret['PARSED']['STATUS']['ATTRIBUTES']['RECENT'])) {
446
                // if this array does not exists means that there is no messages in the mailbox
447
                return 0;
448
            }
449
450
            return $ret['PARSED']['STATUS']['ATTRIBUTES']['RECENT'];
451
        }
452
453
        return 0;
454
    }
455
456
    /**
457
     * Returns an array containing the message envelope
458
     *
459
     * @param string   $mailbox
460
     * @param array|int|null $msg_id
461
     * @return array|\PEAR_Error Either the envelopes or Pear_Error on error
462
     */
463
    public function getEnvelope(string $mailbox = '', int $msg_id = null)
464
    {
465
        if ('' === $mailbox) {
466
            $mailbox = $this->getCurrentMailbox();
0 ignored issues
show
The assignment to $mailbox is dead and can be removed.
Loading history...
467
        }
468
469
        if (null !== $msg_id) {
470
            if (is_array($msg_id)) {
0 ignored issues
show
The condition is_array($msg_id) is always false.
Loading history...
471
                $message_set = $this->_getSearchListFromArray($msg_id);
472
            } else {
473
                $message_set = $msg_id;
474
            }
475
        } else {
476
            $message_set = '1:*';
477
        }
478
479
        $ret = $this->cmdFetch($message_set, 'ENVELOPE');
480
        if ('OK' !== \mb_strtoupper($ret['RESPONSE']['CODE'])) {
481
            return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']);
482
        }
483
484
        if (isset($ret['PARSED'])) {
485
            foreach ($ret['PARSED'] as $i => $iValue) {
486
                $a            = $ret['PARSED'][$i]['EXT']['ENVELOPE'];
487
                $a['MSG_NUM'] = $ret['PARSED'][$i]['NRO'];
488
                $env[]        = $a;
489
            }
490
491
            return $env;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $env seems to be defined by a foreach iteration on line 485. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
492
        }
493
494
        return new PEAR_Error('Error, undefined number of messages');
495
    }
496
497
    /**
498
     * Returns the sum of all the sizes of messages in $mailbox
499
     *           WARNING!!!  The method's performance is not good
500
     *                       if you have a lot of messages in the mailbox
501
     *                       Use with care!
502
     * @param string $mailbox
503
     * @return mixed Either size of maildrop or false on error
504
     */
505
    public function getMailboxSize(string $mailbox = '')
506
    {
507
        if ('' != $mailbox && $mailbox != $this->getCurrentMailbox()) {
508
            // store the actual selected mailbox name
509
            $mailbox_aux = $this->getCurrentMailbox();
510
            if (PEAR::isError($ret = $this->selectMailbox($mailbox))) {
0 ignored issues
show
Bug Best Practice introduced by
The method PEAR::isError() is not static, but was called statically. ( Ignorable by Annotation )

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

510
            if (PEAR::/** @scrutinizer ignore-call */ isError($ret = $this->selectMailbox($mailbox))) {
Loading history...
511
                return $ret;
512
            }
513
        }
514
515
        $ret = $this->cmdFetch('1:*', 'RFC822.SIZE');
516
        if ('OK' !== \mb_strtoupper($ret['RESPONSE']['CODE'])) {
517
            // Restore the default mailbox if it was changed
518
            if ('' != $mailbox && $mailbox != $this->getCurrentMailbox()) {
519
                if (PEAR::isError($ret = $this->selectMailbox($mailbox_aux))) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $mailbox_aux does not seem to be defined for all execution paths leading up to this point.
Loading history...
520
                    return $ret;
521
                }
522
            }
523
            // return 0 because the server says that there is no message in the mailbox
524
            return 0;
525
        }
526
527
        $sum = 0;
528
529
        if (!isset($ret['PARSED'])) {
530
            // if the server does not return a "PARSED"  part
531
            // we think that it does not suppoprt select or has no messages in it.
532
            return 0;
533
        }
534
        foreach ($ret['PARSED'] as $msgSize) {
535
            if (isset($msgSize['EXT']['RFC822.SIZE'])) {
536
                $sum += $msgSize['EXT']['RFC822.SIZE'];
537
            }
538
        }
539
540
        if ('' != $mailbox && $mailbox != $this->getCurrentMailbox()) {
541
            // re-select the  mailbox
542
            if (PEAR::isError($ret = $this->selectMailbox($mailbox_aux))) {
543
                return $ret;
544
            }
545
        }
546
547
        return $sum;
548
    }
549
550
    /**
551
     * Marks a message for deletion. Only will be deleted if the
552
     * disconnect() method is called with auto-expunge on true or expunge()
553
     * method is called.
554
     *
555
     * @param array|int|null $msg_id Message to delete
556
     * @return bool|\PEAR_Error Success/Failure
557
     */
558
    public function deleteMessages(int $msg_id = null)
559
    {
560
        /* As said in RFC2060...
561
         C: A003 STORE 2:4 +FLAGS (\Deleted)
562
         S: * 2 FETCH FLAGS (\Deleted \Seen)
563
         S: * 3 FETCH FLAGS (\Deleted)
564
         S: * 4 FETCH FLAGS (\Deleted \Flagged \Seen)
565
         S: A003 OK STORE completed
566
         */ //Called without parammeters deletes all the messages in the mailbox
567
        // You can also provide an array of numbers to delete those emails
568
        if (null !== $msg_id) {
569
            if (is_array($msg_id)) {
0 ignored issues
show
The condition is_array($msg_id) is always false.
Loading history...
570
                $message_set = $this->_getSearchListFromArray($msg_id);
571
            } else {
572
                $message_set = $msg_id;
573
            }
574
        } else {
575
            $message_set = '1:*';
576
        }
577
578
        $dataitem = '+FLAGS.SILENT';
579
        $value    = '\Deleted';
580
        $ret      = $this->cmdStore($message_set, $dataitem, $value);
581
        if ('OK' !== \mb_strtoupper($ret['RESPONSE']['CODE'])) {
582
            return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']);
583
        }
584
585
        return true;
586
    }
587
588
    /**
589
     * Copies mail from one folder to another
590
     *
591
     * @param string      $dest_mailbox   mailbox name to copy sessages to
592
     * @param array|int|null    $msg_id
593
     * @param string|null $source_mailbox mailbox name from where the messages are copied
594
     *
595
     * @return array|bool|\PEAR_Error true on Success/PearError on Failure
596
     * @since 1.0
597
     */
598
    public function copyMessages(string $dest_mailbox, $msg_id = null, ?string $source_mailbox = null)
599
    {
600
        if (null === $source_mailbox) {
601
            $source_mailbox = $this->getCurrentMailbox();
0 ignored issues
show
The assignment to $source_mailbox is dead and can be removed.
Loading history...
602
        } else {
603
            if (PEAR::isError($ret = $this->selectMailbox($source_mailbox))) {
0 ignored issues
show
Bug Best Practice introduced by
The method PEAR::isError() is not static, but was called statically. ( Ignorable by Annotation )

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

603
            if (PEAR::/** @scrutinizer ignore-call */ isError($ret = $this->selectMailbox($source_mailbox))) {
Loading history...
604
                return $ret;
605
            }
606
        }
607
        //Called without parammeters copies all messages in the mailbox
608
        // You can also provide an array of numbers to copy those emails
609
        if (null !== $msg_id) {
610
            if (is_array($msg_id)) {
611
                $message_set = $this->_getSearchListFromArray($msg_id);
612
            } else {
613
                $message_set = $msg_id;
614
            }
615
        } else {
616
            $message_set = '1:*';
617
        }
618
619
        if (PEAR::isError($ret = $this->cmdCopy($message_set, $dest_mailbox))) {
620
            return $ret;
621
        }
622
623
        return true;
624
    }
625
626
    /**
627
     * Appends a mail to  a mailbox
628
     *
629
     * @param string $rfc_message the message to append in RFC822 format
630
     * @param string|null   $mailbox     mailbox name to append to
631
     *
632
     * @return bool|\PEAR_Error true on Success/PearError on Failure
633
     * @since 1.0
634
     */
635
    public function appendMessage(string $rfc_message, ?string $mailbox = null)
636
    {
637
        if (null === $mailbox) {
638
            $mailbox = $this->getCurrentMailbox();
639
        }
640
        $ret = $this->cmdAppend($mailbox, $rfc_message);
641
        if ('OK' !== \mb_strtoupper($ret['RESPONSE']['CODE'])) {
642
            return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']);
643
        }
644
645
        return true;
646
    }
647
648
    /******************************************************************
649
     **                                                               **
650
     **           MAILBOX RELATED METHODS                             **
651
     **                                                               **
652
     ******************************************************************/
653
654
    /**
655
     * Gets the HierachyDelimiter character used to create subfolders  cyrus users "."
656
     *   and wu-imapd uses "/"
657
     *
658
     * $param  string  the mailbox to get the hierarchy from
659
     * @param string $mailbox
660
     * @return string the hierarchy delimiter
661
     *
662
     * @since  1.0
663
     */
664
    public function getHierarchyDelimiter(string $mailbox = '')
665
    {
666
        /* RFC2060 says: "the command LIST "" "" means get the hierachy delimiter:
667
         An empty ("" string) mailbox name argument is a special request to
668
         return the hierarchy delimiter and the root name of the name given
669
         in the reference.  The value returned as the root MAY be null if
670
         the reference is non-rooted or is null.  In all cases, the
671
         hierarchy delimiter is returned.  This permits a client to get the
672
         hierarchy delimiter even when no mailboxes by that name currently
673
         exist."
674
         */
675
        if (PEAR::isError($ret = $this->cmdList($mailbox, ''))) {
0 ignored issues
show
Bug Best Practice introduced by
The method PEAR::isError() is not static, but was called statically. ( Ignorable by Annotation )

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

675
        if (PEAR::/** @scrutinizer ignore-call */ isError($ret = $this->cmdList($mailbox, ''))) {
Loading history...
676
            return $ret;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $ret returns the type PEAR_Error|array which is incompatible with the documented return type string.
Loading history...
677
        }
678
679
        return $ret['PARSED'][0]['EXT']['LIST']['HIERACHY_DELIMITER'] ?? new PEAR_Error('the IMAP Server does not support HIERACHY_DELIMITER!');
0 ignored issues
show
Bug Best Practice introduced by
The expression return $ret['PARSED'][0]...t HIERACHY_DELIMITER!') also could return the type PEAR_Error which is incompatible with the documented return type string.
Loading history...
680
    }
681
682
    /**
683
     * Returns an array containing the names of the selected mailboxes
684
     *
685
     * @param string $reference
686
     * @param int|bool|string    $restriction_search false or 0 means return all mailboxes  true or 1 return only the mailbox that contains that exact name
687
     *
688
     * 2  return all mailboxes in that hierarchy level
689
     * @param bool   $returnAttributes   true means return an assoc array containing mailbox names and mailbox attributes
690
     *
691
     * false - the default - means return an array of mailboxes
692
     *
693
     * @return array|\PEAR_Error true on Success/PearError on Failure
694
     * @since 1.0
695
     */
696
    public function getMailboxes(string $reference = '', int $restriction_search = 0, bool $returnAttributes = false)
697
    {
698
        if (is_bool($restriction_search)) {
0 ignored issues
show
The condition is_bool($restriction_search) is always false.
Loading history...
699
            $restriction_search = (int)$restriction_search;
700
        }
701
702
        if (is_int($restriction_search)) {
0 ignored issues
show
The condition is_int($restriction_search) is always true.
Loading history...
703
            switch ($restriction_search) {
704
                case 0:
705
                    $mailbox = '*';
706
                    break;
707
                case 1:
708
                    $mailbox   = $reference;
709
                    $reference = '%';
710
                    break;
711
                case 2:
712
                    $mailbox = '%';
713
                    break;
714
            }
715
        } else {
716
            if (is_string($restriction_search)) {
717
                $mailbox = $restriction_search;
718
            } else {
719
                return new PEAR_Error('UPS... you ');
720
            }
721
        }
722
723
        if (PEAR::isError($ret = $this->cmdList($reference, $mailbox))) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $mailbox does not seem to be defined for all execution paths leading up to this point.
Loading history...
Bug Best Practice introduced by
The method PEAR::isError() is not static, but was called statically. ( Ignorable by Annotation )

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

723
        if (PEAR::/** @scrutinizer ignore-call */ isError($ret = $this->cmdList($reference, $mailbox))) {
Loading history...
724
            return $ret;
725
        }
726
727
        if ('OK' !== \mb_strtoupper($ret['RESPONSE']['CODE'])) {
728
            return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']);
729
        }
730
        $ret_aux = [];
731
        if (isset($ret['PARSED'])) {
732
            foreach ($ret['PARSED'] as $mbox) {
733
                //If the folder has the \NoSelect atribute we don't put in the list
734
                // it solves a bug in wu-imap that crash the IMAP server if we select that mailbox
735
                if (isset($mbox['EXT']['LIST']['NAME_ATTRIBUTES'])) {
736
                    if (!in_array('\NoSelect', $mbox['EXT']['LIST']['NAME_ATTRIBUTES'], true)) {
737
                        if ($returnAttributes) {
738
                            $ret_aux[] = [
739
                                'MAILBOX'            => $mbox['EXT']['LIST']['MAILBOX_NAME'],
740
                                'ATTRIBUTES'         => $mbox['EXT']['LIST']['NAME_ATTRIBUTES'],
741
                                'HIERACHY_DELIMITER' => $mbox['EXT']['LIST']['HIERACHY_DELIMITER'],
742
                            ];
743
                        } else {
744
                            $ret_aux[] = $mbox['EXT']['LIST']['MAILBOX_NAME'];
745
                        }
746
                    }
747
                }
748
            }
749
        }
750
751
        return $ret_aux;
752
    }
753
754
    /**
755
     * check if the mailbox name exists
756
     *
757
     * @param string $mailbox mailbox name to check existance
758
     *
759
     * @return bool|\PEAR_Error true on Success/false on Failure
760
     * @since 1.0
761
     */
762
    public function mailboxExist(string $mailbox)
763
    {
764
        // true means do an exact match
765
        if (PEAR::isError($ret = $this->getMailboxes($mailbox, true))) {
0 ignored issues
show
Bug Best Practice introduced by
The method PEAR::isError() is not static, but was called statically. ( Ignorable by Annotation )

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

765
        if (PEAR::/** @scrutinizer ignore-call */ isError($ret = $this->getMailboxes($mailbox, true))) {
Loading history...
true of type true is incompatible with the type integer expected by parameter $restriction_search of Net_IMAP::getMailboxes(). ( Ignorable by Annotation )

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

765
        if (PEAR::isError($ret = $this->getMailboxes($mailbox, /** @scrutinizer ignore-type */ true))) {
Loading history...
766
            return $ret;
767
        }
768
        if (count($ret) > 0) {
0 ignored issues
show
$ret of type PEAR_Error is incompatible with the type Countable|array expected by parameter $value of count(). ( Ignorable by Annotation )

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

768
        if (count(/** @scrutinizer ignore-type */ $ret) > 0) {
Loading history...
769
            return true;
770
        }
771
772
        return false;
773
    }
774
775
    /**
776
     * Creates the mailbox $mailbox
777
     *
778
     * @param string $mailbox mailbox name to create
779
     *
780
     * @return bool|\PEAR_Error true on Success/PearError on Failure
781
     * @since 1.0
782
     */
783
    public function createMailbox(string $mailbox)
784
    {
785
        $ret = $this->cmdCreate($mailbox);
786
        if ('OK' !== \mb_strtoupper($ret['RESPONSE']['CODE'])) {
787
            return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']);
788
        }
789
790
        return true;
791
    }
792
793
    /**
794
     * Deletes the mailbox $mailbox
795
     *
796
     * @param string $mailbox mailbox name to delete
797
     *
798
     * @return bool|\PEAR_Error true on Success/PearError on Failure
799
     * @since 1.0
800
     */
801
    public function deleteMailbox(string $mailbox)
802
    {
803
        // TODO verificar que el mailbox se encuentra vacio y, sino borrar los mensajes antes~!!!!!!
804
        $ret = $this->cmdDelete($mailbox);
805
        if ('OK' !== \mb_strtoupper($ret['RESPONSE']['CODE'])) {
806
            return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']);
807
        }
808
809
        return true;
810
    }
811
812
    /**
813
     * Renames the mailbox $mailbox
814
     *
815
     * @param string $oldmailbox
816
     * @param string $newmailbox
817
     * @return bool|\PEAR_Error true on Success/PearError on Failure
818
     * @since 1.0
819
     */
820
    public function renameMailbox($oldmailbox, $newmailbox)
821
    {
822
        $ret = $this->cmdRename($oldmailbox, $newmailbox);
823
        if ('OK' !== \mb_strtoupper($ret['RESPONSE']['CODE'])) {
824
            return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']);
825
        }
826
827
        return true;
828
    }
829
830
    /******************************************************************
831
     **                                                               **
832
     **           SUBSCRIPTION METHODS                                **
833
     **                                                               **
834
     ******************************************************************/
835
836
    /**
837
     * Subscribes to the selected mailbox
838
     *
839
     * @param string|null $mailbox mailbox name to subscribe
840
     *
841
     * @return bool|\PEAR_Error true on Success/PearError on Failure
842
     * @since 1.0
843
     */
844
    public function subscribeMailbox(?string $mailbox = null)
845
    {
846
        if (null === $mailbox) {
847
            $mailbox = $this->getCurrentMailbox();
848
        }
849
        $ret = $this->cmdSubscribe($mailbox);
850
        if ('OK' !== \mb_strtoupper($ret['RESPONSE']['CODE'])) {
851
            return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']);
852
        }
853
854
        return true;
855
    }
856
857
    /**
858
     * Removes the subscription to a mailbox
859
     *
860
     * @param string|null $mailbox mailbox name to unsubscribe
861
     *
862
     * @return bool|\PEAR_Error true on Success/PearError on Failure
863
     * @since 1.0
864
     */
865
    public function unsubscribeMailbox(?string $mailbox = null)
866
    {
867
        if (null === $mailbox) {
868
            $mailbox = $this->getCurrentMailbox();
869
        }
870
        $ret = $this->cmdUnsubscribe($mailbox);
871
        if ('OK' !== \mb_strtoupper($ret['RESPONSE']['CODE'])) {
872
            return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']);
873
        }
874
875
        return true;
876
    }
877
878
    /**
879
     * Lists the subscription to mailboxes
880
     *
881
     * @param string $reference
882
     * @param int    $restriction_search
883
     * @param bool   $returnAttributes
884
     * @return array|\PEAR_Error true on Success/PearError on Failure
885
     * @since 1.0
886
     */
887
    public function listsubscribedMailboxes(string $reference = '', int $restriction_search = 0, bool $returnAttributes = false)
888
    {
889
        if (is_bool($restriction_search)) {
0 ignored issues
show
The condition is_bool($restriction_search) is always false.
Loading history...
890
            $restriction_search = (int)$restriction_search;
891
        }
892
893
        if (is_int($restriction_search)) {
0 ignored issues
show
The condition is_int($restriction_search) is always true.
Loading history...
894
            switch ($restriction_search) {
895
                case 0:
896
                    $mailbox = '*';
897
                    break;
898
                case 1:
899
                    $mailbox   = $reference;
900
                    $reference = '%';
901
                    break;
902
                case 2:
903
                    $mailbox = '%';
904
                    break;
905
            }
906
        } else {
907
            if (is_string($restriction_search)) {
908
                $mailbox = $restriction_search;
909
            } else {
910
                return new PEAR_Error('UPS... you ');
911
            }
912
        }
913
914
        if (PEAR::isError($ret = $this->cmdLsub($reference, $mailbox))) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $mailbox does not seem to be defined for all execution paths leading up to this point.
Loading history...
Bug Best Practice introduced by
The method PEAR::isError() is not static, but was called statically. ( Ignorable by Annotation )

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

914
        if (PEAR::/** @scrutinizer ignore-call */ isError($ret = $this->cmdLsub($reference, $mailbox))) {
Loading history...
915
            return $ret;
916
        }
917
        //$ret=$this->cmdLsub($mailbox_base, $mailbox_name);
918
919
        if ('OK' !== \mb_strtoupper($ret['RESPONSE']['CODE'])) {
920
            return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']);
921
        }
922
923
        $ret_aux = [];
924
        if (isset($ret['PARSED'])) {
925
            foreach ($ret['PARSED'] as $mbox) {
926
                if (isset($mbox['EXT']['LSUB']['MAILBOX_NAME'])) {
927
                    if ($returnAttributes) {
928
                        $ret_aux[] = [
929
                            'MAILBOX'            => $mbox['EXT']['LSUB']['MAILBOX_NAME'],
930
                            'ATTRIBUTES'         => $mbox['EXT']['LSUB']['NAME_ATTRIBUTES'],
931
                            'HIERACHY_DELIMITER' => $mbox['EXT']['LSUB']['HIERACHY_DELIMITER'],
932
                        ];
933
                    } else {
934
                        $ret_aux[] = $mbox['EXT']['LSUB']['MAILBOX_NAME'];
935
                    }
936
                }
937
            }
938
        }
939
940
        return $ret_aux;
941
    }
942
943
    /******************************************************************
944
     **                                                               **
945
     **           FLAGS METHODS                                       **
946
     **                                                               **
947
     ******************************************************************/
948
949
    /**
950
     * Lists the flags of the selected messages
951
     *
952
     * @param array|int|null $msg_id the message list
953
     *
954
     * @return array|\PEAR_Error array on Success/PearError on Failure
955
     * @since 1.0
956
     */
957
    public function getFlags($msg_id = null)
958
    {
959
        // You can also provide an array of numbers to those emails
960
        if (null !== $msg_id) {
961
            if (is_array($msg_id)) {
962
                $message_set = $this->_getSearchListFromArray($msg_id);
963
            } else {
964
                $message_set = $msg_id;
965
            }
966
        } else {
967
            $message_set = '1:*';
968
        }
969
970
        $ret = $this->cmdFetch($message_set, 'FLAGS');
971
        if ('OK' !== \mb_strtoupper($ret['RESPONSE']['CODE'])) {
972
            return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']);
973
        }
974
        $flags = [];
975
        if (isset($ret['PARSED'])) {
976
            foreach ($ret['PARSED'] as $msg_flags) {
977
                if (isset($msg_flags['EXT']['FLAGS'])) {
978
                    $flags[] = $msg_flags['EXT']['FLAGS'];
979
                }
980
            }
981
        }
982
983
        return $flags;
984
    }
985
986
    /**
987
     * check the Seen flag
988
     *
989
     * @param mixed $message_nro the message to check
990
     *
991
     * @return array|bool|\PEAR_Error true or false if the flag is sert PearError on Failure
992
     * @since 1.0
993
     */
994
    public function isSeen($message_nro)
995
    {
996
        return $this->hasFlag($message_nro, '\\Seen');
997
    }
998
999
    /**
1000
     * check the Answered flag
1001
     *
1002
     * @param mixed $message_nro the message to check
1003
     *
1004
     * @return array|bool|\PEAR_Error true or false if the flag is sert PearError on Failure
1005
     * @since 1.0
1006
     */
1007
    public function isAnswered($message_nro)
1008
    {
1009
        return $this->hasFlag($message_nro, '\\Answered');
1010
    }
1011
1012
    /**
1013
     * check the flagged flag
1014
     *
1015
     * @param mixed $message_nro the message to check
1016
     *
1017
     * @return array|bool|\PEAR_Error true or false if the flag is sert PearError on Failure
1018
     * @since 1.0
1019
     */
1020
    public function isFlagged($message_nro)
1021
    {
1022
        return $this->hasFlag($message_nro, '\\Flagged');
1023
    }
1024
1025
    /**
1026
     * check the Draft flag
1027
     *
1028
     * @param mixed $message_nro the message to check
1029
     *
1030
     * @return array|bool|\PEAR_Error true or false if the flag is sert PearError on Failure
1031
     * @since 1.0
1032
     */
1033
    public function isDraft($message_nro)
1034
    {
1035
        return $this->hasFlag($message_nro, '\\Draft');
1036
    }
1037
1038
    /**
1039
     * check the Deleted flag
1040
     *
1041
     * @param mixed $message_nro the message to check
1042
     *
1043
     * @return array|bool|\PEAR_Error true or false if the flag is sert PearError on Failure
1044
     * @since 1.0
1045
     */
1046
    public function isDeleted($message_nro)
1047
    {
1048
        return $this->hasFlag($message_nro, '\\Deleted');
1049
    }
1050
1051
    /**
1052
     * @param mixed $message_nro
1053
     * @param string $flag
1054
     * @return array|bool|\PEAR_Error
1055
     */
1056
    public function hasFlag($message_nro, $flag)
1057
    {
1058
        if (PEAR::isError($resp = $this->getFlags($message_nro))) {
0 ignored issues
show
Bug Best Practice introduced by
The method PEAR::isError() is not static, but was called statically. ( Ignorable by Annotation )

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

1058
        if (PEAR::/** @scrutinizer ignore-call */ isError($resp = $this->getFlags($message_nro))) {
Loading history...
1059
            return $resp;
1060
        }
1061
        if (isset($resp[0])) {
1062
            if (is_array($resp[0])) {
1063
                if (in_array($flag, $resp[0], true)) {
1064
                    return true;
1065
                }
1066
            }
1067
        }
1068
1069
        return false;
1070
    }
1071
1072
    /******************************************************************
1073
     **                                                               **
1074
     **           MISC METHODS                                        **
1075
     **                                                               **
1076
     ******************************************************************/
1077
1078
    /**
1079
     * expunge function. Sends the EXPUNGE command
1080
     *
1081
     *
1082
     * @return bool|\PEAR_Error Success/Failure
1083
     */
1084
    public function expunge()
1085
    {
1086
        $ret = $this->cmdExpunge();
1087
        if ('OK' !== \mb_strtoupper($ret['RESPONSE']['CODE'])) {
1088
            return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']);
1089
        }
1090
1091
        return true;
1092
    }
1093
1094
    /**
1095
     * search function. Sends the SEARCH command
1096
     *
1097
     * @param string $search_list
1098
     * @param false  $uidSearch
1099
     * @return mixed|\PEAR_Error bool Success/Failure
1100
     */
1101
    public function search(string $search_list, bool $uidSearch = false)
1102
    {
1103
        if ($uidSearch) {
1104
            $ret = $this->cmdUidSearch($search_list);
1105
        } else {
1106
            $ret = $this->cmdSearch($search_list);
1107
        }
1108
1109
        if ('OK' !== \mb_strtoupper($ret['RESPONSE']['CODE'])) {
1110
            return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']);
1111
        }
1112
1113
        return $ret['PARSED']['SEARCH']['SEARCH_LIST'];
1114
    }
1115
1116
    /******************************************************************
1117
     **                                                               **
1118
     **           QUOTA METHODS                                       **
1119
     **                                                               **
1120
     ******************************************************************/
1121
1122
    /**
1123
     * Returns STORAGE quota details
1124
     * @param string|null $mailbox_name Mailbox to get quota info.
1125
     * @return array|\PEAR_Error assoc array contaning the quota info  on success or PEAR_Error
1126
     *
1127
     * @since  1.0
1128
     */
1129
    public function getStorageQuota(?string $mailbox_name = null)
1130
    {
1131
        if (null === $mailbox_name) {
1132
            $mailbox_name = $this->getCurrentMailbox();
1133
        }
1134
1135
        if (PEAR::isError($ret = $this->cmdGetQuota($mailbox_name))) {
0 ignored issues
show
Bug Best Practice introduced by
The method PEAR::isError() is not static, but was called statically. ( Ignorable by Annotation )

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

1135
        if (PEAR::/** @scrutinizer ignore-call */ isError($ret = $this->cmdGetQuota($mailbox_name))) {
Loading history...
1136
            return new PEAR_Error($ret->getMessage());
1137
        }
1138
1139
        if ('OK' !== \mb_strtoupper($ret['RESPONSE']['CODE'])) {
1140
            // if the error is that the user does not have quota set return  an array
1141
            // and not pear error
1142
            if (0 === mb_strpos(mb_strtoupper($ret['RESPONSE']['STR_CODE']), 'QUOTA')) {
1143
                return ['USED' => 'NOT SET', 'QMAX' => 'NOT SET'];
1144
            }
1145
1146
            return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']);
1147
        }
1148
1149
        return $ret['PARSED']['EXT']['QUOTA']['STORAGE'] ?? ['USED' => 'NOT SET', 'QMAX' => 'NOT SET'];
1150
    }
1151
1152
    /**
1153
     * Returns MESSAGES quota details
1154
     * @param string|null $mailbox_name Mailbox to get quota info.
1155
     * @return array|\PEAR_Error assoc array contaning the quota info  on success or PEAR_Error
1156
     *
1157
     * @since  1.0
1158
     */
1159
    public function getMessagesQuota(?string $mailbox_name = null)
1160
    {
1161
        if (null === $mailbox_name) {
1162
            $mailbox_name = $this->getCurrentMailbox();
1163
        }
1164
1165
        if (PEAR::isError($ret = $this->cmdGetQuota($mailbox_name))) {
0 ignored issues
show
Bug Best Practice introduced by
The method PEAR::isError() is not static, but was called statically. ( Ignorable by Annotation )

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

1165
        if (PEAR::/** @scrutinizer ignore-call */ isError($ret = $this->cmdGetQuota($mailbox_name))) {
Loading history...
1166
            return new PEAR_Error($ret->getMessage());
1167
        }
1168
1169
        if ('OK' !== \mb_strtoupper($ret['RESPONSE']['CODE'])) {
1170
            // if the error is that the user does not have quota set return  an array
1171
            // and not pear error
1172
            if (0 === mb_strpos(mb_strtoupper($ret['RESPONSE']['STR_CODE']), 'QUOTA')) {
1173
                return ['USED' => 'NOT SET', 'QMAX' => 'NOT SET'];
1174
            }
1175
1176
            return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']);
1177
        }
1178
1179
        return $ret['PARSED']['EXT']['QUOTA']['MESSAGES'] ?? ['USED' => 'NOT SET', 'QMAX' => 'NOT SET'];
1180
    }
1181
1182
    /**
1183
     * sets STORAGE quota details
1184
     * @param string   $mailbox_name Mailbox to get quota info.
1185
     * @param int|null $quota
1186
     * @return \PEAR_Error|true
1187
     *
1188
     * @since  1.0
1189
     */
1190
    public function setStorageQuota(string $mailbox_name, ?int $quota)
1191
    {
1192
        if (PEAR::isError($ret = $this->cmdSetQuota($mailbox_name, $quota))) {
0 ignored issues
show
Bug Best Practice introduced by
The method PEAR::isError() is not static, but was called statically. ( Ignorable by Annotation )

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

1192
        if (PEAR::/** @scrutinizer ignore-call */ isError($ret = $this->cmdSetQuota($mailbox_name, $quota))) {
Loading history...
1193
            return new PEAR_Error($ret->getMessage());
1194
        }
1195
        if ('OK' !== \mb_strtoupper($ret['RESPONSE']['CODE'])) {
1196
            return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']);
1197
        }
1198
1199
        return true;
1200
    }
1201
1202
    /**
1203
     * sets MESSAGES quota details
1204
     * @param string   $mailbox_name Mailbox to get quota info.
1205
     * @param int|null $quota
1206
     * @return \PEAR_Error|true
1207
     *
1208
     * @since  1.0
1209
     */
1210
    public function setMessagesQuota(string $mailbox_name, ?int $quota)
1211
    {
1212
        if (PEAR::isError($ret = $this->cmdSetQuota($mailbox_name, '', $quota))) {
0 ignored issues
show
'' of type string is incompatible with the type integer|null expected by parameter $storageQuota of Net_IMAPProtocol::cmdSetQuota(). ( Ignorable by Annotation )

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

1212
        if (PEAR::isError($ret = $this->cmdSetQuota($mailbox_name, /** @scrutinizer ignore-type */ '', $quota))) {
Loading history...
Bug Best Practice introduced by
The method PEAR::isError() is not static, but was called statically. ( Ignorable by Annotation )

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

1212
        if (PEAR::/** @scrutinizer ignore-call */ isError($ret = $this->cmdSetQuota($mailbox_name, '', $quota))) {
Loading history...
1213
            return new PEAR_Error($ret->getMessage());
1214
        }
1215
        if ('OK' !== \mb_strtoupper($ret['RESPONSE']['CODE'])) {
1216
            return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']);
1217
        }
1218
1219
        return true;
1220
    }
1221
1222
    /******************************************************************
1223
     **                                                               **
1224
     **           ACL METHODS                                         **
1225
     **                                                               **
1226
     ******************************************************************/
1227
1228
    /**
1229
     * get the Access Control List details
1230
     * @param string|null $mailbox_name Mailbox to get ACL info.
1231
     * @return string on success or PEAR_Error
1232
     *
1233
     * @since  1.0
1234
     */
1235
    public function getACL(string $mailbox_name = null)
1236
    {
1237
        if (null === $mailbox_name) {
1238
            $mailbox_name = $this->getCurrentMailbox();
1239
        }
1240
        if (PEAR::isError($ret = $this->cmdGetACL($mailbox_name))) {
0 ignored issues
show
Bug Best Practice introduced by
The method PEAR::isError() is not static, but was called statically. ( Ignorable by Annotation )

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

1240
        if (PEAR::/** @scrutinizer ignore-call */ isError($ret = $this->cmdGetACL($mailbox_name))) {
Loading history...
1241
            return new PEAR_Error($ret->getMessage());
0 ignored issues
show
Bug Best Practice introduced by
The expression return new PEAR_Error($ret->getMessage()) returns the type PEAR_Error which is incompatible with the documented return type string.
Loading history...
1242
        }
1243
1244
        if ('OK' !== \mb_strtoupper($ret['RESPONSE']['CODE'])) {
1245
            return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']);
0 ignored issues
show
Bug Best Practice introduced by
The expression return new PEAR_Error($r...RESPONSE']['STR_CODE']) returns the type PEAR_Error which is incompatible with the documented return type string.
Loading history...
1246
        }
1247
1248
        return $ret['PARSED']['USERS'] ?? false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $ret['PARSED']['USERS'] ?? false could also return false which is incompatible with the documented return type string. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
1249
    }
1250
1251
    /**
1252
     * Set ACL on a mailbox
1253
     *
1254
     * @param string $mailbox_name the mailbox
1255
     * @param string $user         user to set the ACL
1256
     * @param string $acl          ACL list
1257
     * @return \PEAR_Error|bool  True on success, or PEAR_Error on false
1258
     *
1259
     * @since  1.0
1260
     */
1261
    public function setACL(string $mailbox_name, string $user, string $acl)
1262
    {
1263
        if (PEAR::isError($ret = $this->cmdSetACL($mailbox_name, $user, $acl))) {
0 ignored issues
show
Bug Best Practice introduced by
The method PEAR::isError() is not static, but was called statically. ( Ignorable by Annotation )

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

1263
        if (PEAR::/** @scrutinizer ignore-call */ isError($ret = $this->cmdSetACL($mailbox_name, $user, $acl))) {
Loading history...
1264
            return new PEAR_Error($ret->getMessage());
1265
        }
1266
        if ('OK' !== \mb_strtoupper($ret['RESPONSE']['CODE'])) {
1267
            return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']);
1268
        }
1269
1270
        return true;
1271
    }
1272
1273
    /**
1274
     * deletes the ACL on a mailbox
1275
     *
1276
     * @param string $mailbox_name the mailbox
1277
     * @param string $user         user to set the ACL
1278
     * @return \PEAR_Error|bool  True on success, or PEAR_Error on false
1279
     *
1280
     * @since  1.0
1281
     */
1282
    public function deleteACL(string $mailbox_name, string $user)
1283
    {
1284
        if (PEAR::isError($ret = $this->cmdDeleteACL($mailbox_name, $user))) {
0 ignored issues
show
Bug Best Practice introduced by
The method PEAR::isError() is not static, but was called statically. ( Ignorable by Annotation )

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

1284
        if (PEAR::/** @scrutinizer ignore-call */ isError($ret = $this->cmdDeleteACL($mailbox_name, $user))) {
Loading history...
1285
            return new PEAR_Error($ret->getMessage());
1286
        }
1287
        if ('OK' !== \mb_strtoupper($ret['RESPONSE']['CODE'])) {
1288
            return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']);
1289
        }
1290
1291
        return true;
1292
    }
1293
1294
    /**
1295
     * returns the rights that the user logged on has on the mailbox
1296
     * this method can be used by any user, not only the administrator
1297
     *
1298
     * @param string|null $mailbox_name the mailbox to query rights
1299
     * @return string|\PEAR_Error  string contailing the list of rights on success, or PEAR_Error on failure
1300
     *
1301
     * @since  1.0
1302
     */
1303
    public function getMyRights(?string $mailbox_name = null)
1304
    {
1305
        if (null === $mailbox_name) {
1306
            $mailbox_name = $this->getCurrentMailbox();
1307
        }
1308
1309
        if (PEAR::isError($ret = $this->cmdMyRights($mailbox_name))) {
0 ignored issues
show
Bug Best Practice introduced by
The method PEAR::isError() is not static, but was called statically. ( Ignorable by Annotation )

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

1309
        if (PEAR::/** @scrutinizer ignore-call */ isError($ret = $this->cmdMyRights($mailbox_name))) {
Loading history...
1310
            return new PEAR_Error($ret->getMessage());
1311
        }
1312
        if ('OK' !== \mb_strtoupper($ret['RESPONSE']['CODE'])) {
1313
            return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']);
1314
        }
1315
1316
        return $ret['PARSED']['GRANTED'] ?? new PEAR_Error('Bogus response from server!');
1317
    }
1318
1319
    /**
1320
     * returns an array containing the rights that a user logged on has on the mailbox
1321
     * this method can be used by any user, not only the administrator
1322
     *
1323
     * @param string      $user
1324
     * @param string|null $mailbox_name the mailbox to query rights
1325
     * @return string|\PEAR_Error  string contailing the list of rights on success, or PEAR_Error on failure
1326
     *
1327
     * @since  1.0
1328
     */
1329
    public function getACLRights(string $user, string $mailbox_name = null)
1330
    {
1331
        if (null === $mailbox_name) {
1332
            $mailbox_name = $this->getCurrentMailbox();
1333
        }
1334
1335
        if (PEAR::isError($ret = $this->cmdListRights($mailbox_name, $user))) {
0 ignored issues
show
Bug Best Practice introduced by
The method PEAR::isError() is not static, but was called statically. ( Ignorable by Annotation )

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

1335
        if (PEAR::/** @scrutinizer ignore-call */ isError($ret = $this->cmdListRights($mailbox_name, $user))) {
Loading history...
1336
            return new PEAR_Error($ret->getMessage());
1337
        }
1338
        if ('OK' !== \mb_strtoupper($ret['RESPONSE']['CODE'])) {
1339
            return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']);
1340
        }
1341
1342
        return $ret['PARSED']['GRANTED'] ?? new PEAR_Error('Bogus response from server!');
1343
    }
1344
1345
    /******************************************************************
1346
     **                                                               **
1347
     **           ANNOTATEMORE METHODS                                **
1348
     **                                                               **
1349
     *****************************************************************
1350
     * @param string      $entry
1351
     * @param array       $values
1352
     * @param string|null $mailbox_name
1353
     * @return bool|\PEAR_Error
1354
     */
1355
1356
    public function setAnnotation(string $entry, array $values, ?string $mailbox_name = null)
1357
    {
1358
        if (null === $mailbox_name) {
1359
            $mailbox_name = $this->getCurrentMailbox();
1360
        }
1361
1362
        if (PEAR::isError($ret = $this->cmdSetAnnotation($mailbox_name, $entry, $values))) {
0 ignored issues
show
Bug Best Practice introduced by
The method PEAR::isError() is not static, but was called statically. ( Ignorable by Annotation )

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

1362
        if (PEAR::/** @scrutinizer ignore-call */ isError($ret = $this->cmdSetAnnotation($mailbox_name, $entry, $values))) {
Loading history...
1363
            return new PEAR_Error($ret->getMessage());
1364
        }
1365
        if ('OK' !== \mb_strtoupper($ret['RESPONSE']['CODE'])) {
1366
            return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']);
1367
        }
1368
1369
        return true;
1370
    }
1371
1372
    /**
1373
     * @param string $entry
1374
     * @param array  $values
1375
     * @param string|null   $mailbox_name
1376
     * @return bool|\PEAR_Error
1377
     */
1378
    public function deleteAnnotation(string $entry, array $values, ?string $mailbox_name = null)
1379
    {
1380
        if (null === $mailbox_name) {
1381
            $mailbox_name = $this->getCurrentMailbox();
1382
        }
1383
1384
        if (PEAR::isError($ret = $this->cmdDeleteAnnotation($mailbox_name, $entry, $values))) {
0 ignored issues
show
Bug Best Practice introduced by
The method PEAR::isError() is not static, but was called statically. ( Ignorable by Annotation )

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

1384
        if (PEAR::/** @scrutinizer ignore-call */ isError($ret = $this->cmdDeleteAnnotation($mailbox_name, $entry, $values))) {
Loading history...
1385
            return new PEAR_Error($ret->getMessage());
1386
        }
1387
        if ('OK' !== \mb_strtoupper($ret['RESPONSE']['CODE'])) {
1388
            return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']);
1389
        }
1390
1391
        return true;
1392
    }
1393
1394
    /**
1395
     * @param array $entries
1396
     * @param array $values
1397
     * @param string|null  $mailbox_name
1398
     * @return array|mixed|\PEAR_Error
1399
     */
1400
    public function getAnnotation(array $entries, array $values, ?string $mailbox_name = null)
1401
    {
1402
        if (null === $mailbox_name) {
1403
            $mailbox_name = $this->getCurrentMailbox();
1404
        }
1405
        if (!is_array($entries)) {
0 ignored issues
show
The condition is_array($entries) is always true.
Loading history...
1406
            $entries = [$entries];
1407
        }
1408
        if (!is_array($values)) {
0 ignored issues
show
The condition is_array($values) is always true.
Loading history...
1409
            $values = [$values];
1410
        }
1411
1412
        if (PEAR::isError($ret = $this->cmdGetAnnotation($mailbox_name, $entries, $values))) {
0 ignored issues
show
Bug Best Practice introduced by
The method PEAR::isError() is not static, but was called statically. ( Ignorable by Annotation )

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

1412
        if (PEAR::/** @scrutinizer ignore-call */ isError($ret = $this->cmdGetAnnotation($mailbox_name, $entries, $values))) {
Loading history...
1413
            return new PEAR_Error($ret->getMessage());
1414
        }
1415
        if ('OK' !== \mb_strtoupper($ret['RESPONSE']['CODE'])) {
1416
            return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']);
1417
        }
1418
        $ret_aux = [];
1419
        if (isset($ret['PARSED'])) {
1420
            foreach ($ret['PARSED'] as $mbox) {
1421
                $rawvalues = $mbox['EXT']['ATTRIBUTES'];
1422
                $values    = [];
1423
                for ($i = 0, $iMax = count($rawvalues); $i < $iMax; $i += 2) {
1424
                    $values[$rawvalues[$i]] = $rawvalues[$i + 1];
1425
                }
1426
                $mbox['EXT']['ATTRIBUTES'] = $values;
1427
                $ret_aux[]                 = $mbox['EXT'];
1428
            }
1429
        }
1430
        if (1 == count($ret_aux) && $ret_aux[0]['MAILBOX'] == $mailbox_name) {
1431
            if (1 == count($entries) && $ret_aux[0]['ENTRY'] == $entries[0]) {
1432
                if (1 == count($ret_aux[0]['ATTRIBUTES']) && 1 === count($values)) {
1433
                    $attrs = array_keys($ret_aux[0]['ATTRIBUTES']);
1434
                    $vals  = array_keys($values);
1435
                    if ($attrs[0] == $vals[0]) {
1436
                        return $ret_aux[0]['ATTRIBUTES'][$attrs[0]];
1437
                    }
1438
                }
1439
            }
1440
        }
1441
1442
        return $ret_aux;
1443
    }
1444
1445
    /**
1446
     * Transform an array to a list to be used in the cmdFetch method
1447
     * @param array $arr
1448
     * @return string
1449
     */
1450
    public function _getSearchListFromArray(array $arr): string
1451
    {
1452
        $txt = implode(',', $arr);
1453
1454
        return $txt;
1455
    }
1456
1457
    /*****************************************************
1458
     * Net_POP3 Compatibility functions:
1459
     *
1460
     * Warning!!!
1461
     * Those functions could dissapear in the future
1462
     *********************************************************/
1463
1464
    public function getSize()
1465
    {
1466
        return $this->getMailboxSize();
1467
    }
1468
1469
    /**
1470
     * @param string|null $mailbox
1471
     * @return int|mixed|\PEAR_Error
1472
     */
1473
    public function numMsg(string $mailbox = null)
1474
    {
1475
        return $this->getNumberOfMessages($mailbox);
0 ignored issues
show
It seems like $mailbox can also be of type null; however, parameter $mailbox of Net_IMAP::getNumberOfMessages() does only seem to accept string, 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

1475
        return $this->getNumberOfMessages(/** @scrutinizer ignore-type */ $mailbox);
Loading history...
1476
    }
1477
1478
    /*
1479
     * Returns the entire message with given message number.
1480
     *
1481
     * @param  int $msg_id Message number
1482
     * @return mixed   Either entire message or false on error
1483
     */
1484
1485
    /**
1486
     * @param int $msg_id
1487
     * @return array|mixed|\PEAR_Error
1488
     */
1489
    public function getMsg(int $msg_id)
1490
    {
1491
        $ret = $this->getMessages($msg_id, false);
1492
        // false means that getMessages() must not use the msg number as array key
1493
        return $ret[0] ?? $ret;
1494
    }
1495
1496
    /**
1497
     * @param string|int|null $msg_id
1498
     * @return \PEAR_Error
1499
     */
1500
    public function getListing($msg_id = null)
1501
    {
1502
        return $this->getMessagesList($msg_id);
0 ignored issues
show
It seems like $msg_id can also be of type string; however, parameter $msg_id of Net_IMAP::getMessagesList() does only seem to accept integer|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

1502
        return $this->getMessagesList(/** @scrutinizer ignore-type */ $msg_id);
Loading history...
1503
    }
1504
1505
    /**
1506
     * @param int $msg_id
1507
     * @return bool|\PEAR_Error
1508
     */
1509
    public function deleteMsg(int $msg_id)
1510
    {
1511
        return $this->deleteMessages($msg_id);
1512
    }
1513
}
1514