MailReader::setMailbox()   A
last analyzed

Complexity

Conditions 3
Paths 4

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 18
rs 9.4285
cc 3
eloc 10
nc 4
nop 1
1
<?php
2
3
namespace JM\MailReader;
4
5
class MailReader
6
{
7
8
    /**
9
     * @var array
10
     */
11
    private $settings = ['server' => '', 'username' => '', 'password' => ''];
12
13
    /**
14
     * @var array
15
     */
16
    private $messages = [];
17
18
    /**
19
     * @var string
20
     */
21
    private $mailbox = 'INBOX';
22
23
    /**
24
     * @var resource
25
     */
26
    private $conn;
27
28
29
    /**
30
     * When this class is destructed we
31
     * might want to close the connection.
32
     */
33
    public function __destruct()
34
    {
35
        $this->close();
36
    }
37
38
39
    /**
40
     * Open a connection to a mail server.
41
     *
42
     * @param array $credentials
43
     *
44
     * @return bool
45
     * @throws \Exception
46
     */
47
    public function connect($credentials = [])
48
    {
49
        if ($diff = array_diff(array_keys($this->settings), array_keys($credentials))) {
50
            throw new \Exception("Missing credentials, the following fields are missing ".implode('/', $diff));
51
        }
52
53
        $this->settings = array_merge($this->settings, $credentials);
54
55
        if (isset($this->settings['port']) === false) {
56
            $this->settings['port'] = 143;
57
        }
58
59
        $this->conn = @imap_open('{'.$this->settings['server'].':'.$this->settings['port'].'/notls}',
60
            $this->settings['username'], $this->settings['password']);
61
62
        if ($this->conn == false) {
63
            throw new \Exception("Could not connect or authorize to ".$this->settings['server'].':'.$this->settings['port']);
64
        }
65
66
        return ($this->conn != null);
67
    }
68
69
70
    /**
71
     * Close the connection to the mail server.
72
     */
73
    private function close()
74
    {
75
        if ($this->conn) {
76
            imap_close($this->conn);
77
        }
78
    }
79
80
81
    /**
82
     * @param string $mailbox
83
     *
84
     * @return bool
85
     */
86
    public function setMailbox($mailbox = 'INBOX')
87
    {
88
89
        if ($mailbox == 'INBOX') {
90
            $mailbox = "{".$this->settings['server']."}INBOX";
91
        } else {
92
            $mailbox = "{".$this->settings['server']."}INBOX.".imap_utf7_encode($mailbox);
93
        }
94
95
        $result = false;
96
97
        if ($this->conn) {
98
            $result = imap_reopen($this->conn, $mailbox);
99
            $this->mailbox = $mailbox;
100
        }
101
102
        return $result;
103
    }
104
105
106
    /**
107
     * Return the name of the current mailbox.
108
     *
109
     * @return string
110
     */
111
    public function getMailbox()
112
    {
113
        $mailbox = str_replace("{".$this->settings['server']."}", '', $this->mailbox);
114
        $mailbox = (substr($mailbox, 0, 6) == 'INBOX.') ? substr($mailbox, -6) : $mailbox;
115
116
        return $mailbox;
117
    }
118
119
120
    /**
121
     * Mark a given message as read.
122
     *
123
     * @param string $index
124
     *
125
     * @return bool
126
     */
127
    public function markMessageAsRead($index = '')
128
    {
129
        return imap_setflag_full($this->conn, $index, "\\Seen");
130
    }
131
132
133
    /**
134
     * Filter unread message sent to $to
135
     *
136
     * @param string $to
137
     *
138
     * @return array
139
     */
140
    public function filterUnReadMessagesTo($to = '')
141
    {
142
        $filteredResult = $this->filterTo($to);
143
        $filteredMessages = [];
144
145
        if (is_array($filteredResult) && count($filteredResult) > 0) {
146
            foreach ($filteredResult as $message) {
147
                if (isset($message['header'])) {
148
                    $header = $message['header'];
149
                    if ($header->Unseen == 'U') {
150
                        $filteredMessages[] = $message;
151
                    }
152
                }
153
            }
154
        }
155
156
        return $filteredMessages;
157
    }
158
159
160
    /**
161
     * Filter message sent to $to
162
     *
163
     * @param string $to
164
     *
165
     * @return array
166
     */
167
    public function filterTo($to = '')
168
    {
169
        $msg_cnt = imap_num_msg($this->conn);
170
        if ($msg_cnt > 0 && count($this->messages) == 0) {
171
            $this->readMailbox();
172
        }
173
174
        $filteredResult = imap_search($this->conn, 'TO "'.$to.'"');
175
        $filteredMessages = [];
176
177
        if (is_array($filteredResult) && count($filteredResult) > 0) {
178
            foreach ($filteredResult as $index) {
179
                $filteredMessages[] = $this->getMessageInformation($index);
180
            }
181
        }
182
183
        return $filteredMessages;
184
    }
185
186
187
    /**
188
     * Create a mailbox (folder)
189
     *
190
     * @param string $name
191
     *
192
     * @return bool
193
     */
194
    public function createMailbox($name = '')
195
    {
196
        if (empty($name)) {
197
            return false;
198
        }
199
200
        $name = imap_utf7_encode($name);
201
202
        return imap_createmailbox($this->conn, "{".$this->settings['server']."}INBOX.".$name);
203
    }
204
205
206
    /**
207
     * Subscribe to a mailbox.
208
     *
209
     * @param string $name
210
     *
211
     * @return bool
212
     */
213
    public function subscribeMailbox($name = '') {
214
        if (empty($name)) {
215
            return false;
216
        }
217
218
        $name = imap_utf7_encode($name);
219
        return imap_subscribe ( $this->conn, "{".$this->settings['server']."}INBOX.".$name );
220
    }
221
222
    /**
223
     * This function will be deleted in version 1.3
224
     * This function is deprecated because of the naming
225
     * inconsistency.
226
     *
227
     * @param string $name
228
     *
229
     * @deprecated
230
     * @return bool
231
     */
232
    public function removeMailbox($name = '')
233
    {
234
        return $this->deleteMailbox($name);
235
    }
236
237
238
    /**
239
     * Delete a mailbox (folder)
240
     *
241
     * @param string $name
242
     *
243
     * @return bool
244
     */
245
    public function deleteMailbox($name = '')
246
    {
247
        if (empty($name)) {
248
            return false;
249
        }
250
251
        $name = imap_utf7_encode($name);
252
253
        return imap_deletemailbox($this->conn, "{".$this->settings['server']."}INBOX.".$name);
254
    }
255
256
257
258
259
    /**
260
     * Check to see if a given mailbox (folder) exists on the server.
261
     *
262
     * @param string $name
263
     *
264
     * @return bool
265
     */
266
    public function mailboxExists($name = '')
267
    {
268
        if (empty($name)) {
269
            return false;
270
        }
271
272
        $name = imap_utf7_encode($name);
273
        $prefixedName = "{".$this->settings['server']."}INBOX.".$name;
274
        $mailboxes = imap_list($this->conn, "{".$this->settings['server']."}", "*");
275
276
        return in_array($prefixedName, $mailboxes);
277
    }
278
279
280
    /**
281
     * Return all mailboxes (folders) on the server.
282
     *
283
     * @return array
284
     */
285
    public function getMailboxes()
286
    {
287
        return imap_list($this->conn, "{".$this->settings['server']."}", "*");
288
    }
289
290
291
    /**
292
     * Return all mailboxes (folders) on the server. This function removes the
293
     * mailbox prefixes like {server}INBOX.<name here>
294
     *
295
     * @return array
296
     */
297
    public function getPrettyMailboxes()
298
    {
299
        $mailboxes = $this->getMailboxes();
300
        $result = [];
301
        if (is_array($mailboxes) && count($mailboxes) > 0) {
302
            $prefixedMailbox = "INBOX.";
303
            foreach ($mailboxes as $mailbox) {
304
                // Remove the server prefix
305
                $mailbox = str_replace('{'.$this->settings['server'].'}', '', $mailbox);
306
307
                // Remove the INBOX. prefix (if present)
308
                $mailbox = str_replace($prefixedMailbox, '', $mailbox);
309
310
                $result[] = $mailbox;
311
            }
312
        }
313
314
        return $result;
315
    }
316
317
318
    /**
319
     * Rename a mailbox (folder)
320
     *
321
     * @param string $from
322
     * @param string $to
323
     *
324
     * @return bool
325
     */
326
    public function renameMailbox($from = '', $to = '')
327
    {
328
        if (empty($from) || empty($to)) {
329
            return false;
330
        }
331
332
        $from = imap_utf7_encode($from);
333
        $to = imap_utf7_encode($to);
334
335
        return imap_renamemailbox($this->conn, "{".$this->settings['server']."}INBOX.".$from,
336
            "{".$this->settings['server']."}INBOX.".$to);
337
    }
338
339
340
    /**
341
     * Move a given message at $index to a given mailbox (folder).
342
     *
343
     * @param int    $index
344
     * @param string $to
345
     *
346
     * @return bool
347
     */
348
    public function moveMessage($index = -1, $to = '')
349
    {
350
        if (empty($to)) {
351
            return false;
352
        }
353
354
        $msgId = 0;
355
356
        if (is_array($this->messages) == true) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
357
            foreach($this ->messages as $msg) {
358
                if ($msg['index'] == $index) {
359
                    $msgId = $msg['index'];
360
                    break;
361
                }
362
            }
363
        }
364
365
366
        if ($msgId >= 0) {
367
            $to = imap_utf7_encode($to);
368
369
            imap_mail_move($this->conn, $msgId, "INBOX.".$to);
370
            imap_expunge($this->conn);
371
        }
372
373
        return false;
374
    }
375
376
377
378
    /**
379
     * Delete a given email message. The param $index
380
     * is bases of the [index] field on an email array.
381
     *
382
     * @param int $index
383
     *
384
     * @return bool
385
     */
386
    public function deleteMessage($index = -1)
387
    {
388
        if ($index == -1) {
389
            return false;
390
        }
391
392
        $result = imap_delete($this->conn, $index);
393
        if ($result) {
394
            // Real delete emails marked as deleted
395
            imap_expunge($this->conn);
396
        }
397
        return $result;
398
    }
399
400
401
    /**
402
     * Return message information without reading it from the server
403
     *
404
     * @param string $id
405
     *
406
     * @return mixed
407
     */
408
    public function getMessageInformation($id = '')
409
    {
410
        $message = [];
411
        if (is_array($this->messages) == true) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
412
            foreach($this ->messages as $msg) {
413
                if ($msg['index'] == $id) {
414
                    return $msg;
415
                }
416
            }
417
        }
418
        return $message;
419
    }
420
421
    /**
422
     * Return a message based on its index in the mailbox.
423
     *
424
     * @param string $id
425
     *
426
     * @return mixed
427
     */
428
    public function getMessage($id = '')
429
    {
430
        $message = [];
431
        if (is_array($this->messages) == true) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
432
            foreach($this ->messages as $msg) {
433
                if ($msg['index'] == $id) {
434
                    $message = $msg;
435
                    break;
436
                }
437
            }
438
        }
439
440
        if (is_array($message) === true) {
441
            // Get the message body but do not mark as read
442
            $message['body'] = quoted_printable_decode(imap_fetchbody($this->conn, $message['index'], FT_PEEK));
443
        }
444
445
        return $message;
446
    }
447
448
449
    /**
450
     * Retrieve a list of message in the mailbox.
451
     *
452
     * @return array
453
     */
454
    public function readMailbox()
455
    {
456
        $msg_cnt = imap_num_msg($this->conn);
457
458
        $messages = [];
459
        for ($i = 1; $i <= $msg_cnt; $i++) {
460
            $header = imap_headerinfo($this->conn, $i);
461
            $messages[] = [
462
                'index'     => trim($header->Msgno),
463
                'header'    => $header,
464
                'structure' => imap_fetchstructure($this->conn, $i)
465
            ];
466
        }
467
        $this->messages = $messages;
468
        return $this->messages;
469
    }
470
}