Project

General

Profile

1
<?php
2
/**
3
 * PHPMailer POP-Before-SMTP Authentication Class.
4
 * PHP Version 5.0.0
5
 * Version 5.2.7
6
 * @package PHPMailer
7
 * @link https://github.com/PHPMailer/PHPMailer/
8
 * @author Marcus Bointon (coolbru) <phpmailer@synchromedia.co.uk>
9
 * @author Jim Jagielski (jimjag) <jimjag@gmail.com>
10
 * @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
11
 * @author Brent R. Matzelle (original founder)
12
 * @copyright 2013 Marcus Bointon
13
 * @copyright 2010 - 2012 Jim Jagielski
14
 * @copyright 2004 - 2009 Andy Prevost
15
 * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
16
 * @note This program is distributed in the hope that it will be useful - WITHOUT
17
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18
 * FITNESS FOR A PARTICULAR PURPOSE.
19
 */
20

    
21
/**
22
 * PHPMailer POP-Before-SMTP Authentication Class.
23
 * Specifically for PHPMailer to use for RFC1939 POP-before-SMTP authentication.
24
 * Does not support APOP.
25
 * @package PHPMailer
26
 * @author Richard Davey (original author) <rich@corephp.co.uk>
27
 * @author Marcus Bointon (coolbru) <phpmailer@synchromedia.co.uk>
28
 * @author Jim Jagielski (jimjag) <jimjag@gmail.com>
29
 * @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
30
 */
31

    
32
class POP3
33
{
34
    /**
35
     * The POP3 PHPMailer Version number.
36
     * @type string
37
     * @access public
38
     */
39
    public $Version = '5.2.7';
40

    
41
    /**
42
     * Default POP3 port number.
43
     * @type int
44
     * @access public
45
     */
46
    public $POP3_PORT = 110;
47

    
48
    /**
49
     * Default timeout in seconds.
50
     * @type int
51
     * @access public
52
     */
53
    public $POP3_TIMEOUT = 30;
54

    
55
    /**
56
     * POP3 Carriage Return + Line Feed.
57
     * @type string
58
     * @access public
59
     * @deprecated Use the constant instead
60
     */
61
    public $CRLF = "\r\n";
62

    
63
    /**
64
     * Debug display level.
65
     * Options: 0 = no, 1+ = yes
66
     * @type int
67
     * @access public
68
     */
69
    public $do_debug = 0;
70

    
71
    /**
72
     * POP3 mail server hostname.
73
     * @type string
74
     * @access public
75
     */
76
    public $host;
77

    
78
    /**
79
     * POP3 port number.
80
     * @type int
81
     * @access public
82
     */
83
    public $port;
84

    
85
    /**
86
     * POP3 Timeout Value in seconds.
87
     * @type int
88
     * @access public
89
     */
90
    public $tval;
91

    
92
    /**
93
     * POP3 username
94
     * @type string
95
     * @access public
96
     */
97
    public $username;
98

    
99
    /**
100
     * POP3 password.
101
     * @type string
102
     * @access public
103
     */
104
    public $password;
105

    
106
    /**
107
     * Resource handle for the POP3 connection socket.
108
     * @type resource
109
     * @access private
110
     */
111
    private $pop_conn;
112

    
113
    /**
114
     * Are we connected?
115
     * @type bool
116
     * @access private
117
     */
118
    private $connected;
119

    
120
    /**
121
     * Error container.
122
     * @type array
123
     * @access private
124
     */
125
    private $error;
126

    
127
    /**
128
     * Line break constant
129
     */
130
    const CRLF = "\r\n";
131

    
132
    /**
133
     * Constructor.
134
     * @access public
135
     */
136
    public function __construct()
137
    {
138
        $this->pop_conn = 0;
139
        $this->connected = false;
140
        $this->error = null;
141
    }
142

    
143
    /**
144
     * Simple static wrapper for all-in-one POP before SMTP
145
     * @param $host
146
     * @param bool $port
147
     * @param bool $tval
148
     * @param string $username
149
     * @param string $password
150
     * @param int $debug_level
151
     * @return bool
152
     */
153
    public static function popBeforeSmtp(
154
        $host,
155
        $port = false,
156
        $tval = false,
157
        $username = '',
158
        $password = '',
159
        $debug_level = 0
160
    ) {
161
        $pop = new POP3;
162
        return $pop->authorise($host, $port, $tval, $username, $password, $debug_level);
163
    }
164

    
165
    /**
166
     * Authenticate with a POP3 server.
167
     * A connect, login, disconnect sequence
168
     * appropriate for POP-before SMTP authorisation.
169
     * @access public
170
     * @param string $host
171
     * @param bool|int $port
172
     * @param bool|int $tval
173
     * @param string $username
174
     * @param string $password
175
     * @param int $debug_level
176
     * @return bool
177
     */
178
    public function authorise($host, $port = false, $tval = false, $username = '', $password = '', $debug_level = 0)
179
    {
180
        $this->host = $host;
181
        // If no port value provided, use default
182
        if ($port === false) {
183
            $this->port = $this->POP3_PORT;
184
        } else {
185
            $this->port = $port;
186
        }
187
        // If no timeout value provided, use default
188
        if ($tval === false) {
189
            $this->tval = $this->POP3_TIMEOUT;
190
        } else {
191
            $this->tval = $tval;
192
        }
193
        $this->do_debug = $debug_level;
194
        $this->username = $username;
195
        $this->password = $password;
196
        //  Refresh the error log
197
        $this->error = null;
198
        //  connect
199
        $result = $this->connect($this->host, $this->port, $this->tval);
200
        if ($result) {
201
            $login_result = $this->login($this->username, $this->password);
202
            if ($login_result) {
203
                $this->disconnect();
204
                return true;
205
            }
206
        }
207
        // We need to disconnect regardless of whether the login succeeded
208
        $this->disconnect();
209
        return false;
210
    }
211

    
212
    /**
213
     * Connect to a POP3 server.
214
     * @access public
215
     * @param string $host
216
     * @param bool|int $port
217
     * @param integer $tval
218
     * @return boolean
219
     */
220
    public function connect($host, $port = false, $tval = 30)
221
    {
222
        //  Are we already connected?
223
        if ($this->connected) {
224
            return true;
225
        }
226

    
227
        //On Windows this will raise a PHP Warning error if the hostname doesn't exist.
228
        //Rather than suppress it with @fsockopen, capture it cleanly instead
229
        set_error_handler(array($this, 'catchWarning'));
230

    
231
        //  connect to the POP3 server
232
        $this->pop_conn = fsockopen(
233
            $host, //  POP3 Host
234
            $port, //  Port #
235
            $errno, //  Error Number
236
            $errstr, //  Error Message
237
            $tval
238
        ); //  Timeout (seconds)
239
        //  Restore the error handler
240
        restore_error_handler();
241
        //  Does the Error Log now contain anything?
242
        if ($this->error && $this->do_debug >= 1) {
243
            $this->displayErrors();
244
        }
245
        //  Did we connect?
246
        if ($this->pop_conn == false) {
247
            //  It would appear not...
248
            $this->error = array(
249
                'error' => "Failed to connect to server $host on port $port",
250
                'errno' => $errno,
251
                'errstr' => $errstr
252
            );
253
            if ($this->do_debug >= 1) {
254
                $this->displayErrors();
255
            }
256
            return false;
257
        }
258

    
259
        //  Increase the stream time-out
260
        //  Check for PHP 4.3.0 or later
261
        if (version_compare(phpversion(), '5.0.0', 'ge')) {
262
            stream_set_timeout($this->pop_conn, $tval, 0);
263
        } else {
264
            //  Does not work on Windows
265
            if (substr(PHP_OS, 0, 3) !== 'WIN') {
266
                socket_set_timeout($this->pop_conn, $tval, 0);
267
            }
268
        }
269

    
270
        //  Get the POP3 server response
271
        $pop3_response = $this->getResponse();
272
        //  Check for the +OK
273
        if ($this->checkResponse($pop3_response)) {
274
            //  The connection is established and the POP3 server is talking
275
            $this->connected = true;
276
            return true;
277
        }
278
        return false;
279
    }
280

    
281
    /**
282
     * Log in to the POP3 server.
283
     * Does not support APOP (RFC 2828, 4949).
284
     * @access public
285
     * @param string $username
286
     * @param string $password
287
     * @return boolean
288
     */
289
    public function login($username = '', $password = '')
290
    {
291
        if ($this->connected == false) {
292
            $this->error = 'Not connected to POP3 server';
293

    
294
            if ($this->do_debug >= 1) {
295
                $this->displayErrors();
296
            }
297
        }
298
        if (empty($username)) {
299
            $username = $this->username;
300
        }
301
        if (empty($password)) {
302
            $password = $this->password;
303
        }
304

    
305
        // Send the Username
306
        $this->sendString("USER $username" . self::CRLF);
307
        $pop3_response = $this->getResponse();
308
        if ($this->checkResponse($pop3_response)) {
309
            // Send the Password
310
            $this->sendString("PASS $password" . self::CRLF);
311
            $pop3_response = $this->getResponse();
312
            if ($this->checkResponse($pop3_response)) {
313
                return true;
314
            }
315
        }
316
        return false;
317
    }
318

    
319
    /**
320
     * Disconnect from the POP3 server.
321
     * @access public
322
     */
323
    public function disconnect()
324
    {
325
        $this->sendString('QUIT');
326
        //The QUIT command may cause the daemon to exit, which will kill our connection
327
        //So ignore errors here
328
        @fclose($this->pop_conn);
329
    }
330

    
331
    /**
332
     * Get a response from the POP3 server.
333
     * $size is the maximum number of bytes to retrieve
334
     * @param integer $size
335
     * @return string
336
     * @access private
337
     */
338
    private function getResponse($size = 128)
339
    {
340
        $r = fgets($this->pop_conn, $size);
341
        if ($this->do_debug >= 1) {
342
            echo "Server -> Client: $r";
343
        }
344
        return $r;
345
    }
346

    
347
    /**
348
     * Send raw data to the POP3 server.
349
     * @param string $string
350
     * @return integer
351
     * @access private
352
     */
353
    private function sendString($string)
354
    {
355
        if ($this->pop_conn) {
356
            if ($this->do_debug >= 2) { //Show client messages when debug >= 2
357
                echo "Client -> Server: $string";
358
            }
359
            return fwrite($this->pop_conn, $string, strlen($string));
360
        }
361
        return 0;
362
    }
363

    
364
    /**
365
     * Checks the POP3 server response.
366
     * Looks for for +OK or -ERR.
367
     * @param string $string
368
     * @return boolean
369
     * @access private
370
     */
371
    private function checkResponse($string)
372
    {
373
        if (substr($string, 0, 3) !== '+OK') {
374
            $this->error = array(
375
                'error' => "Server reported an error: $string",
376
                'errno' => 0,
377
                'errstr' => ''
378
            );
379
            if ($this->do_debug >= 1) {
380
                $this->displayErrors();
381
            }
382
            return false;
383
        } else {
384
            return true;
385
        }
386
    }
387

    
388
    /**
389
     * Display errors if debug is enabled.
390
     * @access private
391
     */
392
    private function displayErrors()
393
    {
394
        echo '<pre>';
395
        foreach ($this->error as $single_error) {
396
            print_r($single_error);
397
        }
398
        echo '</pre>';
399
    }
400

    
401
    /**
402
     * POP3 connection error handler.
403
     * @param integer $errno
404
     * @param string $errstr
405
     * @param string $errfile
406
     * @param integer $errline
407
     * @access private
408
     */
409
    private function catchWarning($errno, $errstr, $errfile, $errline)
410
    {
411
        $this->error[] = array(
412
            'error' => "Connecting to the POP3 server raised a PHP warning: ",
413
            'errno' => $errno,
414
            'errstr' => $errstr,
415
            'errfile' => $errfile,
416
            'errline' => $errline
417
        );
418
    }
419
}
(3-3/5)