Completed
Push — master ( 0b6af6...254ffc )
by Johnny
02:18
created

MailReader::connect()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 21
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 21
rs 9.0534
cc 4
eloc 11
nc 5
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
                $header = $message['header'];
148
                if ($header->Unseen == 'U') {
149
                    $filteredMessages[] = $message;
150
                }
151
            }
152
        }
153
154
        return $filteredMessages;
155
    }
156
157
158
    /**
159
     * Filter message sent to $to
160
     *
161
     * @param string $to
162
     *
163
     * @return array
164
     */
165
    public function filterTo($to = '')
166
    {
167
        $msg_cnt = imap_num_msg($this->conn);
168
        if ($msg_cnt > 0 && count($this->messages) == 0) {
169
            $this->readMailbox();
170
        }
171
172
        $filteredResult = imap_search($this->conn, 'TO "'.$to.'"');
173
        $filteredMessages = [];
174
175
        if (is_array($filteredResult) && count($filteredResult) > 0) {
176
            foreach ($filteredResult as $index) {
177
                $filteredMessages[] = $this->getMessage($index - 1);
178
            }
179
        }
180
181
        return $filteredMessages;
182
    }
183
184
185
    /**
186
     * Create a mailbox (folder)
187
     *
188
     * @param string $name
189
     *
190
     * @return bool
191
     */
192
    public function createMailbox($name = '')
193
    {
194
        if (empty($name)) {
195
            return false;
196
        }
197
198
        $name = imap_utf7_encode($name);
199
200
        return imap_createmailbox($this->conn, "{".$this->settings['server']."}INBOX.".$name);
201
    }
202
203
204
    /**
205
     * Remove a mailbox (folder)
206
     *
207
     * @param string $name
208
     *
209
     * @return bool
210
     */
211
    public function removeMailbox($name = '')
212
    {
213
        if (empty($name)) {
214
            return false;
215
        }
216
217
        $name = imap_utf7_encode($name);
218
219
        return imap_deletemailbox($this->conn, "{".$this->settings['server']."}INBOX.".$name);
220
    }
221
222
223
    /**
224
     * Check to see if a given mailbox (folder) exists on the server.
225
     *
226
     * @param string $name
227
     *
228
     * @return bool
229
     */
230
    public function mailboxExists($name = '')
231
    {
232
        if (empty($name)) {
233
            return false;
234
        }
235
236
        $name = imap_utf7_encode($name);
237
        $prefixedName = "{".$this->settings['server']."}INBOX.".$name;
238
        $mailboxes = imap_list($this->conn, "{".$this->settings['server']."}", "*");
239
240
        return in_array($prefixedName, $mailboxes);
241
    }
242
243
244
    /**
245
     * Return all mailboxes (folders) on the server.
246
     *
247
     * @return array
248
     */
249
    public function getMailboxes()
250
    {
251
        return imap_list($this->conn, "{".$this->settings['server']."}", "*");
252
    }
253
254
255
    /**
256
     * Return all mailboxes (folders) on the server. This function removes the
257
     * mailbox prefixes like {server}INBOX.<name here>
258
     *
259
     * @return array
260
     */
261
    public function getPrettyMailboxes()
262
    {
263
        $mailboxes = $this->getMailboxes();
264
        $result = [];
265
        if (is_array($mailboxes) && count($mailboxes) > 0) {
266
            $prefixedMailbox = "INBOX.";
267
            foreach ($mailboxes as $mailbox) {
268
                // Remove the server prefix
269
                $mailbox = str_replace('{'.$this->settings['server'].'}', '', $mailbox);
270
271
                // Remove the INBOX. prefix (if present)
272
                $mailbox = str_replace($prefixedMailbox, '', $mailbox);
273
274
                $result[] = $mailbox;
275
            }
276
        }
277
278
        return $result;
279
    }
280
281
282
    /**
283
     * Rename a mailbox (folder)
284
     *
285
     * @param string $from
286
     * @param string $to
287
     *
288
     * @return bool
289
     */
290
    public function renameMailbox($from = '', $to = '')
291
    {
292
        if (empty($from) || empty($to)) {
293
            return false;
294
        }
295
296
        $from = imap_utf7_encode($from);
297
        $to = imap_utf7_encode($to);
298
299
        return imap_renamemailbox($this->conn, "{".$this->settings['server']."}INBOX.".$from,
300
            "{".$this->settings['server']."}INBOX.".$to);
301
    }
302
303
304
    /**
305
     * Move a given message at $index to a given mailbox (folder).
306
     *
307
     * @param int    $index
308
     * @param string $to
309
     *
310
     * @return bool
311
     */
312
    public function moveMessage($index = -1, $to = '')
313
    {
314
        if (empty($to)) {
315
            return false;
316
        }
317
318
        if ($index >= 0) {
319
            $to = imap_utf7_encode($to);
320
321
            imap_mail_move($this->conn, $index, "INBOX.".$to);
322
            imap_expunge($this->conn);
323
        }
324
325
        return false;
326
    }
327
328
329
    /**
330
     * Delete a given email message. The param $index
331
     * is bases of the [index] field on an email array.
332
     *
333
     * @param int $index
334
     *
335
     * @return bool
336
     */
337
    public function deleteMessage($index = -1)
338
    {
339
        if ($index == -1) {
340
            return false;
341
        }
342
343
        $result = imap_delete($this->conn, $index);
344
        if ($result) {
345
            // Real delete emails marked as deleted
346
            imap_expunge($this->conn);
347
        }
348
        return $result;
349
    }
350
351
352
    /**
353
     * Return a message based on its index in the mailbox.
354
     *
355
     * @param string $id
356
     *
357
     * @return mixed
358
     */
359
    public function getMessage($id = '')
360
    {
361
        $message = $this->messages[$id];
362
        if (is_array($message) === true) {
363
            // Get the message body but do not mark as read
364
            $message['body'] = imap_body($this->conn, $message['index'], FT_PEEK);
365
        }
366
367
        return $message;
368
    }
369
370
371
    /**
372
     * Retrieve a list of message in the mailbox.
373
     *
374
     * @return array
375
     */
376
    public function readMailbox()
377
    {
378
        $msg_cnt = imap_num_msg($this->conn);
379
380
        $messages = [];
381
        for ($i = 1; $i <= $msg_cnt; $i++) {
382
            $messages[] = [
383
                'index'     => $i,
384
                'header'    => imap_headerinfo($this->conn, $i),
385
                'structure' => imap_fetchstructure($this->conn, $i)
386
            ];
387
        }
388
        $this->messages = $messages;
389
390
        return $this->messages;
391
    }
392
}