Completed
Push — master ( a81350...e6a872 )
by Wanderson
05:44
created

POP3::getResponse()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 5
nc 2
nop 1
dl 0
loc 9
rs 9.6666
c 0
b 0
f 0
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) <[email protected]>
9
 * @author    Jim Jagielski (jimjag) <[email protected]>
10
 * @author    Andy Prevost (codeworxtech) <[email protected]>
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) <[email protected]>
37
 * @author  Marcus Bointon (Synchro/coolbru) <[email protected]>
38
 * @author  Jim Jagielski (jimjag) <[email protected]>
39
 * @author  Andy Prevost (codeworxtech) <[email protected]>
40
 */
41
class POP3
42
{
43
    /**
44
     * The POP3 PHPMailer Version number.
45
     *
46
     * @var string
47
     */
48
    const VERSION = '6.0.1';
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);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
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 $error) {
388
                print_r($error);
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
    }
419
}
420