source: trunk/library/Zend/Mail/Protocol/Pop3.php @ 5146

Revision 5146, 12.7 KB checked in by wmerlotto, 12 years ago (diff)

Ticket #2305 - Enviando alteracoes, desenvolvidas internamente na Prognus. Library: adicionando arquivos.

Line 
1<?php
2/**
3 * Zend Framework
4 *
5 * LICENSE
6 *
7 * This source file is subject to the new BSD license that is bundled
8 * with this package in the file LICENSE.txt.
9 * It is also available through the world-wide-web at this URL:
10 * http://framework.zend.com/license/new-bsd
11 * If you did not receive a copy of the license and are unable to
12 * obtain it through the world-wide-web, please send an email
13 * to license@zend.com so we can send you a copy immediately.
14 *
15 * @category   Zend
16 * @package    Zend_Mail
17 * @subpackage Protocol
18 * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
19 * @license    http://framework.zend.com/license/new-bsd     New BSD License
20 * @version    $Id: Pop3.php 20096 2010-01-06 02:05:09Z bkarwin $
21 */
22
23
24/**
25 * @category   Zend
26 * @package    Zend_Mail
27 * @subpackage Protocol
28 * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
29 * @license    http://framework.zend.com/license/new-bsd     New BSD License
30 */
31class Zend_Mail_Protocol_Pop3
32{
33    /**
34     * Default timeout in seconds for initiating session
35     */
36    const TIMEOUT_CONNECTION = 30;
37
38    /**
39     * saves if server supports top
40     * @var null|bool
41     */
42    public $hasTop = null;
43
44    /**
45     * socket to pop3
46     * @var null|resource
47     */
48    protected $_socket;
49
50    /**
51     * greeting timestamp for apop
52     * @var null|string
53     */
54    protected $_timestamp;
55
56
57    /**
58     * Public constructor
59     *
60     * @param  string      $host  hostname or IP address of POP3 server, if given connect() is called
61     * @param  int|null    $port  port of POP3 server, null for default (110 or 995 for ssl)
62     * @param  bool|string $ssl   use ssl? 'SSL', 'TLS' or false
63     * @throws Zend_Mail_Protocol_Exception
64     */
65    public function __construct($host = '', $port = null, $ssl = false)
66    {
67        if ($host) {
68            $this->connect($host, $port, $ssl);
69        }
70    }
71
72
73    /**
74     * Public destructor
75     */
76    public function __destruct()
77    {
78        $this->logout();
79    }
80
81
82    /**
83     * Open connection to POP3 server
84     *
85     * @param  string      $host  hostname or IP address of POP3 server
86     * @param  int|null    $port  of POP3 server, default is 110 (995 for ssl)
87     * @param  string|bool $ssl   use 'SSL', 'TLS' or false
88     * @return string welcome message
89     * @throws Zend_Mail_Protocol_Exception
90     */
91    public function connect($host, $port = null, $ssl = false)
92    {
93        if ($ssl == 'SSL') {
94            $host = 'ssl://' . $host;
95        }
96
97        if ($port === null) {
98            $port = $ssl == 'SSL' ? 995 : 110;
99        }
100
101        $errno  =  0;
102        $errstr = '';
103        $this->_socket = @fsockopen($host, $port, $errno, $errstr, self::TIMEOUT_CONNECTION);
104        if (!$this->_socket) {
105            /**
106             * @see Zend_Mail_Protocol_Exception
107             */
108            require_once 'Zend/Mail/Protocol/Exception.php';
109            throw new Zend_Mail_Protocol_Exception('cannot connect to host; error = ' . $errstr .
110                                                   ' (errno = ' . $errno . ' )');
111        }
112
113        $welcome = $this->readResponse();
114
115        strtok($welcome, '<');
116        $this->_timestamp = strtok('>');
117        if (!strpos($this->_timestamp, '@')) {
118            $this->_timestamp = null;
119        } else {
120            $this->_timestamp = '<' . $this->_timestamp . '>';
121        }
122
123        if ($ssl === 'TLS') {
124            $this->request('STLS');
125            $result = stream_socket_enable_crypto($this->_socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);
126            if (!$result) {
127                /**
128                 * @see Zend_Mail_Protocol_Exception
129                 */
130                require_once 'Zend/Mail/Protocol/Exception.php';
131                throw new Zend_Mail_Protocol_Exception('cannot enable TLS');
132            }
133        }
134
135        return $welcome;
136    }
137
138
139    /**
140     * Send a request
141     *
142     * @param string $request your request without newline
143     * @return null
144     * @throws Zend_Mail_Protocol_Exception
145     */
146    public function sendRequest($request)
147    {
148        $result = @fputs($this->_socket, $request . "\r\n");
149        if (!$result) {
150            /**
151             * @see Zend_Mail_Protocol_Exception
152             */
153            require_once 'Zend/Mail/Protocol/Exception.php';
154            throw new Zend_Mail_Protocol_Exception('send failed - connection closed?');
155        }
156    }
157
158
159    /**
160     * read a response
161     *
162     * @param  boolean $multiline response has multiple lines and should be read until "<nl>.<nl>"
163     * @return string response
164     * @throws Zend_Mail_Protocol_Exception
165     */
166    public function readResponse($multiline = false)
167    {
168        $result = @fgets($this->_socket);
169        if (!is_string($result)) {
170            /**
171             * @see Zend_Mail_Protocol_Exception
172             */
173            require_once 'Zend/Mail/Protocol/Exception.php';
174            throw new Zend_Mail_Protocol_Exception('read failed - connection closed?');
175        }
176
177        $result = trim($result);
178        if (strpos($result, ' ')) {
179            list($status, $message) = explode(' ', $result, 2);
180        } else {
181            $status = $result;
182            $message = '';
183        }
184
185        if ($status != '+OK') {
186            /**
187             * @see Zend_Mail_Protocol_Exception
188             */
189            require_once 'Zend/Mail/Protocol/Exception.php';
190            throw new Zend_Mail_Protocol_Exception('last request failed');
191        }
192
193        if ($multiline) {
194            $message = '';
195            $line = fgets($this->_socket);
196            while ($line && rtrim($line, "\r\n") != '.') {
197                if ($line[0] == '.') {
198                    $line = substr($line, 1);
199                }
200                $message .= $line;
201                $line = fgets($this->_socket);
202            };
203        }
204
205        return $message;
206    }
207
208
209    /**
210     * Send request and get resposne
211     *
212     * @see sendRequest(), readResponse()
213     *
214     * @param  string $request    request
215     * @param  bool   $multiline  multiline response?
216     * @return string             result from readResponse()
217     * @throws Zend_Mail_Protocol_Exception
218     */
219    public function request($request, $multiline = false)
220    {
221        $this->sendRequest($request);
222        return $this->readResponse($multiline);
223    }
224
225
226    /**
227     * End communication with POP3 server (also closes socket)
228     *
229     * @return null
230     */
231    public function logout()
232    {
233        if (!$this->_socket) {
234            return;
235        }
236
237        try {
238            $this->request('QUIT');
239        } catch (Zend_Mail_Protocol_Exception $e) {
240            // ignore error - we're closing the socket anyway
241        }
242
243        fclose($this->_socket);
244        $this->_socket = null;
245    }
246
247
248    /**
249     * Get capabilities from POP3 server
250     *
251     * @return array list of capabilities
252     * @throws Zend_Mail_Protocol_Exception
253     */
254    public function capa()
255    {
256        $result = $this->request('CAPA', true);
257        return explode("\n", $result);
258    }
259
260
261    /**
262     * Login to POP3 server. Can use APOP
263     *
264     * @param  string $user      username
265     * @param  string $password  password
266     * @param  bool   $try_apop  should APOP be tried?
267     * @return void
268     * @throws Zend_Mail_Protocol_Exception
269     */
270    public function login($user, $password, $tryApop = true)
271    {
272        if ($tryApop && $this->_timestamp) {
273            try {
274                $this->request("APOP $user " . md5($this->_timestamp . $password));
275                return;
276            } catch (Zend_Mail_Protocol_Exception $e) {
277                // ignore
278            }
279        }
280
281        $result = $this->request("USER $user");
282        $result = $this->request("PASS $password");
283    }
284
285
286    /**
287     * Make STAT call for message count and size sum
288     *
289     * @param  int $messages  out parameter with count of messages
290     * @param  int $octets    out parameter with size in octects of messages
291     * @return void
292     * @throws Zend_Mail_Protocol_Exception
293     */
294    public function status(&$messages, &$octets)
295    {
296        $messages = 0;
297        $octets = 0;
298        $result = $this->request('STAT');
299
300        list($messages, $octets) = explode(' ', $result);
301    }
302
303
304    /**
305     * Make LIST call for size of message(s)
306     *
307     * @param  int|null $msgno number of message, null for all
308     * @return int|array size of given message or list with array(num => size)
309     * @throws Zend_Mail_Protocol_Exception
310     */
311    public function getList($msgno = null)
312    {
313        if ($msgno !== null) {
314            $result = $this->request("LIST $msgno");
315
316            list(, $result) = explode(' ', $result);
317            return (int)$result;
318        }
319
320        $result = $this->request('LIST', true);
321        $messages = array();
322        $line = strtok($result, "\n");
323        while ($line) {
324            list($no, $size) = explode(' ', trim($line));
325            $messages[(int)$no] = (int)$size;
326            $line = strtok("\n");
327        }
328
329        return $messages;
330    }
331
332
333    /**
334     * Make UIDL call for getting a uniqueid
335     *
336     * @param  int|null $msgno number of message, null for all
337     * @return string|array uniqueid of message or list with array(num => uniqueid)
338     * @throws Zend_Mail_Protocol_Exception
339     */
340    public function uniqueid($msgno = null)
341    {
342        if ($msgno !== null) {
343            $result = $this->request("UIDL $msgno");
344
345            list(, $result) = explode(' ', $result);
346            return $result;
347        }
348
349        $result = $this->request('UIDL', true);
350
351        $result = explode("\n", $result);
352        $messages = array();
353        foreach ($result as $line) {
354            if (!$line) {
355                continue;
356            }
357            list($no, $id) = explode(' ', trim($line), 2);
358            $messages[(int)$no] = $id;
359        }
360
361        return $messages;
362
363    }
364
365
366    /**
367     * Make TOP call for getting headers and maybe some body lines
368     * This method also sets hasTop - before it it's not known if top is supported
369     *
370     * The fallback makes normale RETR call, which retrieves the whole message. Additional
371     * lines are not removed.
372     *
373     * @param  int  $msgno    number of message
374     * @param  int  $lines    number of wanted body lines (empty line is inserted after header lines)
375     * @param  bool $fallback fallback with full retrieve if top is not supported
376     * @return string message headers with wanted body lines
377     * @throws Zend_Mail_Protocol_Exception
378     */
379    public function top($msgno, $lines = 0, $fallback = false)
380    {
381        if ($this->hasTop === false) {
382            if ($fallback) {
383                return $this->retrieve($msgno);
384            } else {
385                /**
386                 * @see Zend_Mail_Protocol_Exception
387                 */
388                require_once 'Zend/Mail/Protocol/Exception.php';
389                throw new Zend_Mail_Protocol_Exception('top not supported and no fallback wanted');
390            }
391        }
392        $this->hasTop = true;
393
394        $lines = (!$lines || $lines < 1) ? 0 : (int)$lines;
395
396        try {
397            $result = $this->request("TOP $msgno $lines", true);
398        } catch (Zend_Mail_Protocol_Exception $e) {
399            $this->hasTop = false;
400            if ($fallback) {
401                $result = $this->retrieve($msgno);
402            } else {
403                throw $e;
404            }
405        }
406
407        return $result;
408    }
409
410
411    /**
412     * Make a RETR call for retrieving a full message with headers and body
413     *
414     * @deprecated since 1.1.0; this method has a typo - please use retrieve()
415     * @param  int $msgno  message number
416     * @return string message
417     * @throws Zend_Mail_Protocol_Exception
418     */
419    public function retrive($msgno)
420    {
421        return $this->retrieve($msgno);
422    }
423
424
425    /**
426     * Make a RETR call for retrieving a full message with headers and body
427     *
428     * @param  int $msgno  message number
429     * @return string message
430     * @throws Zend_Mail_Protocol_Exception
431     */
432    public function retrieve($msgno)
433    {
434        $result = $this->request("RETR $msgno", true);
435        return $result;
436    }
437
438    /**
439     * Make a NOOP call, maybe needed for keeping the server happy
440     *
441     * @return null
442     * @throws Zend_Mail_Protocol_Exception
443     */
444    public function noop()
445    {
446        $this->request('NOOP');
447    }
448
449
450    /**
451     * Make a DELE count to remove a message
452     *
453     * @return null
454     * @throws Zend_Mail_Protocol_Exception
455     */
456    public function delete($msgno)
457    {
458        $this->request("DELE $msgno");
459    }
460
461
462    /**
463     * Make RSET call, which rollbacks delete requests
464     *
465     * @return null
466     * @throws Zend_Mail_Protocol_Exception
467     */
468    public function undelete()
469    {
470        $this->request('RSET');
471    }
472}
Note: See TracBrowser for help on using the repository browser.