Subversion Repositories cheapmusic

Rev

Rev 25 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
25 - 1
<?php
2
/**
3
 * PHPMailer POP-Before-SMTP Authentication Class.
4
 * PHP Version 5.5.
5
 *
6
 * @see       https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
7
 *
8
 * @author    Marcus Bointon (Synchro/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 2012 - 2017 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
namespace PHPMailer\PHPMailer;
22
 
23
/**
24
 * PHPMailer POP-Before-SMTP Authentication Class.
25
 * Specifically for PHPMailer to use for RFC1939 POP-before-SMTP authentication.
26
 * 1) This class does not support APOP authentication.
27
 * 2) Opening and closing lots of POP3 connections can be quite slow. If you need
28
 *   to send a batch of emails then just perform the authentication once at the start,
29
 *   and then loop through your mail sending script. Providing this process doesn't
30
 *   take longer than the verification period lasts on your POP3 server, you should be fine.
31
 * 3) This is really ancient technology; you should only need to use it to talk to very old systems.
32
 * 4) This POP3 class is deliberately lightweight and incomplete, and implements just
33
 *   enough to do authentication.
34
 *   If you want a more complete class there are other POP3 classes for PHP available.
35
 *
36
 * @author  Richard Davey (original author) <rich@corephp.co.uk>
37
 * @author  Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
38
 * @author  Jim Jagielski (jimjag) <jimjag@gmail.com>
39
 * @author  Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
40
 */
41
class POP3
42
{
43
    /**
44
     * The POP3 PHPMailer Version number.
45
     *
46
     * @var string
47
     */
73 - 48
    const VERSION = '6.0.7';
25 - 49
 
50
    /**
51
     * Default POP3 port number.
52
     *
53
     * @var int
54
     */
55
    const DEFAULT_PORT = 110;
56
 
57
    /**
58
     * Default timeout in seconds.
59
     *
60
     * @var int
61
     */
62
    const DEFAULT_TIMEOUT = 30;
63
 
64
    /**
65
     * Debug display level.
66
     * Options: 0 = no, 1+ = yes.
67
     *
68
     * @var int
69
     */
70
    public $do_debug = 0;
71
 
72
    /**
73
     * POP3 mail server hostname.
74
     *
75
     * @var string
76
     */
77
    public $host;
78
 
79
    /**
80
     * POP3 port number.
81
     *
82
     * @var int
83
     */
84
    public $port;
85
 
86
    /**
87
     * POP3 Timeout Value in seconds.
88
     *
89
     * @var int
90
     */
91
    public $tval;
92
 
93
    /**
94
     * POP3 username.
95
     *
96
     * @var string
97
     */
98
    public $username;
99
 
100
    /**
101
     * POP3 password.
102
     *
103
     * @var string
104
     */
105
    public $password;
106
 
107
    /**
108
     * Resource handle for the POP3 connection socket.
109
     *
110
     * @var resource
111
     */
112
    protected $pop_conn;
113
 
114
    /**
115
     * Are we connected?
116
     *
117
     * @var bool
118
     */
119
    protected $connected = false;
120
 
121
    /**
122
     * Error container.
123
     *
124
     * @var array
125
     */
126
    protected $errors = [];
127
 
128
    /**
129
     * Line break constant.
130
     */
131
    const LE = "\r\n";
132
 
133
    /**
134
     * Simple static wrapper for all-in-one POP before SMTP.
135
     *
136
     * @param string   $host        The hostname to connect to
137
     * @param int|bool $port        The port number to connect to
138
     * @param int|bool $timeout     The timeout value
139
     * @param string   $username
140
     * @param string   $password
141
     * @param int      $debug_level
142
     *
143
     * @return bool
144
     */
145
    public static function popBeforeSmtp(
146
        $host,
147
        $port = false,
148
        $timeout = false,
149
        $username = '',
150
        $password = '',
151
        $debug_level = 0
152
    ) {
153
        $pop = new self();
154
 
155
        return $pop->authorise($host, $port, $timeout, $username, $password, $debug_level);
156
    }
157
 
158
    /**
159
     * Authenticate with a POP3 server.
160
     * A connect, login, disconnect sequence
161
     * appropriate for POP-before SMTP authorisation.
162
     *
163
     * @param string   $host        The hostname to connect to
164
     * @param int|bool $port        The port number to connect to
165
     * @param int|bool $timeout     The timeout value
166
     * @param string   $username
167
     * @param string   $password
168
     * @param int      $debug_level
169
     *
170
     * @return bool
171
     */
172
    public function authorise($host, $port = false, $timeout = false, $username = '', $password = '', $debug_level = 0)
173
    {
174
        $this->host = $host;
175
        // If no port value provided, use default
176
        if (false === $port) {
177
            $this->port = static::DEFAULT_PORT;
178
        } else {
179
            $this->port = (int) $port;
180
        }
181
        // If no timeout value provided, use default
182
        if (false === $timeout) {
183
            $this->tval = static::DEFAULT_TIMEOUT;
184
        } else {
185
            $this->tval = (int) $timeout;
186
        }
187
        $this->do_debug = $debug_level;
188
        $this->username = $username;
189
        $this->password = $password;
190
        //  Reset the error log
191
        $this->errors = [];
192
        //  connect
193
        $result = $this->connect($this->host, $this->port, $this->tval);
194
        if ($result) {
195
            $login_result = $this->login($this->username, $this->password);
196
            if ($login_result) {
197
                $this->disconnect();
198
 
199
                return true;
200
            }
201
        }
202
        // We need to disconnect regardless of whether the login succeeded
203
        $this->disconnect();
204
 
205
        return false;
206
    }
207
 
208
    /**
209
     * Connect to a POP3 server.
210
     *
211
     * @param string   $host
212
     * @param int|bool $port
213
     * @param int      $tval
214
     *
215
     * @return bool
216
     */
217
    public function connect($host, $port = false, $tval = 30)
218
    {
219
        //  Are we already connected?
220
        if ($this->connected) {
221
            return true;
222
        }
223
 
224
        //On Windows this will raise a PHP Warning error if the hostname doesn't exist.
225
        //Rather than suppress it with @fsockopen, capture it cleanly instead
226
        set_error_handler([$this, 'catchWarning']);
227
 
228
        if (false === $port) {
229
            $port = static::DEFAULT_PORT;
230
        }
231
 
232
        //  connect to the POP3 server
233
        $this->pop_conn = fsockopen(
234
            $host, //  POP3 Host
235
            $port, //  Port #
236
            $errno, //  Error Number
237
            $errstr, //  Error Message
238
            $tval
239
        ); //  Timeout (seconds)
240
        //  Restore the error handler
241
        restore_error_handler();
242
 
243
        //  Did we connect?
244
        if (false === $this->pop_conn) {
245
            //  It would appear not...
246
            $this->setError(
247
                "Failed to connect to server $host on port $port. errno: $errno; errstr: $errstr"
248
            );
249
 
250
            return false;
251
        }
252
 
253
        //  Increase the stream time-out
254
        stream_set_timeout($this->pop_conn, $tval, 0);
255
 
256
        //  Get the POP3 server response
257
        $pop3_response = $this->getResponse();
258
        //  Check for the +OK
259
        if ($this->checkResponse($pop3_response)) {
260
            //  The connection is established and the POP3 server is talking
261
            $this->connected = true;
262
 
263
            return true;
264
        }
265
 
266
        return false;
267
    }
268
 
269
    /**
270
     * Log in to the POP3 server.
271
     * Does not support APOP (RFC 2828, 4949).
272
     *
273
     * @param string $username
274
     * @param string $password
275
     *
276
     * @return bool
277
     */
278
    public function login($username = '', $password = '')
279
    {
280
        if (!$this->connected) {
281
            $this->setError('Not connected to POP3 server');
282
        }
283
        if (empty($username)) {
284
            $username = $this->username;
285
        }
286
        if (empty($password)) {
287
            $password = $this->password;
288
        }
289
 
290
        // Send the Username
291
        $this->sendString("USER $username" . static::LE);
292
        $pop3_response = $this->getResponse();
293
        if ($this->checkResponse($pop3_response)) {
294
            // Send the Password
295
            $this->sendString("PASS $password" . static::LE);
296
            $pop3_response = $this->getResponse();
297
            if ($this->checkResponse($pop3_response)) {
298
                return true;
299
            }
300
        }
301
 
302
        return false;
303
    }
304
 
305
    /**
306
     * Disconnect from the POP3 server.
307
     */
308
    public function disconnect()
309
    {
310
        $this->sendString('QUIT');
311
        //The QUIT command may cause the daemon to exit, which will kill our connection
312
        //So ignore errors here
313
        try {
314
            @fclose($this->pop_conn);
315
        } catch (Exception $e) {
316
            //Do nothing
317
        }
318
    }
319
 
320
    /**
321
     * Get a response from the POP3 server.
322
     *
323
     * @param int $size The maximum number of bytes to retrieve
324
     *
325
     * @return string
326
     */
327
    protected function getResponse($size = 128)
328
    {
329
        $response = fgets($this->pop_conn, $size);
330
        if ($this->do_debug >= 1) {
331
            echo 'Server -> Client: ', $response;
332
        }
333
 
334
        return $response;
335
    }
336
 
337
    /**
338
     * Send raw data to the POP3 server.
339
     *
340
     * @param string $string
341
     *
342
     * @return int
343
     */
344
    protected function sendString($string)
345
    {
346
        if ($this->pop_conn) {
347
            if ($this->do_debug >= 2) { //Show client messages when debug >= 2
348
                echo 'Client -> Server: ', $string;
349
            }
350
 
351
            return fwrite($this->pop_conn, $string, strlen($string));
352
        }
353
 
354
        return 0;
355
    }
356
 
357
    /**
358
     * Checks the POP3 server response.
359
     * Looks for for +OK or -ERR.
360
     *
361
     * @param string $string
362
     *
363
     * @return bool
364
     */
365
    protected function checkResponse($string)
366
    {
367
        if (substr($string, 0, 3) !== '+OK') {
368
            $this->setError("Server reported an error: $string");
369
 
370
            return false;
371
        }
372
 
373
        return true;
374
    }
375
 
376
    /**
377
     * Add an error to the internal error store.
378
     * Also display debug output if it's enabled.
379
     *
380
     * @param string $error
381
     */
382
    protected function setError($error)
383
    {
384
        $this->errors[] = $error;
385
        if ($this->do_debug >= 1) {
386
            echo '<pre>';
387
            foreach ($this->errors as $e) {
388
                print_r($e);
389
            }
390
            echo '</pre>';
391
        }
392
    }
393
 
394
    /**
395
     * Get an array of error messages, if any.
396
     *
397
     * @return array
398
     */
399
    public function getErrors()
400
    {
401
        return $this->errors;
402
    }
403
 
404
    /**
405
     * POP3 connection error handler.
406
     *
407
     * @param int    $errno
408
     * @param string $errstr
409
     * @param string $errfile
410
     * @param int    $errline
411
     */
412
    protected function catchWarning($errno, $errstr, $errfile, $errline)
413
    {
414
        $this->setError(
415
            'Connecting to the POP3 server raised a PHP warning:' .
416
            "errno: $errno errstr: $errstr; errfile: $errfile; errline: $errline"
417
        );
418
    }
73 - 419
}