POP3::connect()   B
last analyzed

Complexity

Conditions 5
Paths 7

Size

Total Lines 51

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
nc 7
nop 3
dl 0
loc 51
rs 8.7579
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * PHPMailer POP-Before-SMTP Authentication Class.
4
 * PHP Version 5
5
 * @package   PHPMailer
6
 * @link      https://github.com/PHPMailer/PHPMailer/
7
 * @author    Marcus Bointon (Synchro/coolbru) <[email protected]>
8
 * @author    Jim Jagielski (jimjag) <[email protected]>
9
 * @author    Andy Prevost (codeworxtech) <[email protected]>
10
 * @author    Brent R. Matzelle (original founder)
11
 * @copyright 2012 - 2014 Marcus Bointon
12
 * @copyright 2010 - 2012 Jim Jagielski
13
 * @copyright 2004 - 2009 Andy Prevost
14
 * @license   http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
15
 * @note      This program is distributed in the hope that it will be useful - WITHOUT
16
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17
 * FITNESS FOR A PARTICULAR PURPOSE.
18
 */
19
20
/**
21
 * PHPMailer POP-Before-SMTP Authentication Class.
22
 * Specifically for PHPMailer to use for RFC1939 POP-before-SMTP authentication.
23
 * Does not support APOP.
24
 * @package PHPMailer
25
 * @author  Richard Davey (original author) <[email protected]>
26
 * @author  Marcus Bointon (Synchro/coolbru) <[email protected]>
27
 * @author  Jim Jagielski (jimjag) <[email protected]>
28
 * @author  Andy Prevost (codeworxtech) <[email protected]>
29
 */
30
class POP3
31
{
32
    /**
33
     * The POP3 PHPMailer Version number.
34
     * @var string
35
     * @access public
36
     */
37
    public $Version = '5.2.26';
38
39
    /**
40
     * Default POP3 port number.
41
     * @var int
42
     * @access public
43
     */
44
    public $POP3_PORT = 110;
45
46
    /**
47
     * Default timeout in seconds.
48
     * @var int
49
     * @access public
50
     */
51
    public $POP3_TIMEOUT = 30;
52
53
    /**
54
     * POP3 Carriage Return + Line Feed.
55
     * @var string
56
     * @access     public
57
     * @deprecated Use the constant instead
58
     */
59
    public $CRLF = "\r\n";
60
61
    /**
62
     * Debug display level.
63
     * Options: 0 = no, 1+ = yes
64
     * @var int
65
     * @access public
66
     */
67
    public $do_debug = 0;
68
69
    /**
70
     * POP3 mail server hostname.
71
     * @var string
72
     * @access public
73
     */
74
    public $host;
75
76
    /**
77
     * POP3 port number.
78
     * @var int
79
     * @access public
80
     */
81
    public $port;
82
83
    /**
84
     * POP3 Timeout Value in seconds.
85
     * @var int
86
     * @access public
87
     */
88
    public $tval;
89
90
    /**
91
     * POP3 username
92
     * @var string
93
     * @access public
94
     */
95
    public $username;
96
97
    /**
98
     * POP3 password.
99
     * @var string
100
     * @access public
101
     */
102
    public $password;
103
104
    /**
105
     * Resource handle for the POP3 connection socket.
106
     * @var resource
107
     * @access protected
108
     */
109
    protected $pop_conn;
110
111
    /**
112
     * Are we connected?
113
     * @var bool
114
     * @access protected
115
     */
116
    protected $connected = false;
117
118
    /**
119
     * Error container.
120
     * @var array
121
     * @access protected
122
     */
123
    protected $errors = [];
124
125
    /**
126
     * Line break constant
127
     */
128
    const CRLF = "\r\n";
129
130
    /**
131
     * Simple static wrapper for all-in-one POP before SMTP
132
     * @param          $host
133
     * @param int|bool $port    The port number to connect to
134
     * @param int|bool $timeout The timeout value
135
     * @param string   $username
136
     * @param string   $password
137
     * @param int      $debug_level
138
     * @return bool
139
     */
140
    public static function popBeforeSmtp(
141
        $host,
142
        $port = false,
143
        $timeout = false,
144
        $username = '',
145
        $password = '',
146
        $debug_level = 0)
147
    {
148
        $pop = new self();
149
150
        return $pop->authorise($host, $port, $timeout, $username, $password, $debug_level);
151
    }
152
153
    /**
154
     * Authenticate with a POP3 server.
155
     * A connect, login, disconnect sequence
156
     * appropriate for POP-before SMTP authorisation.
157
     * @access public
158
     * @param string   $host    The hostname to connect to
159
     * @param int|bool $port    The port number to connect to
160
     * @param int|bool $timeout The timeout value
161
     * @param string   $username
162
     * @param string   $password
163
     * @param int      $debug_level
164
     * @return bool
165
     */
166
    public function authorise($host, $port = false, $timeout = false, $username = '', $password = '', $debug_level = 0)
167
    {
168
        $this->host = $host;
169
        // If no port value provided, use default
170
        if (false === $port) {
171
            $this->port = $this->POP3_PORT;
172
        } else {
173
            $this->port = (int)$port;
174
        }
175
        // If no timeout value provided, use default
176
        if (false === $timeout) {
177
            $this->tval = $this->POP3_TIMEOUT;
178
        } else {
179
            $this->tval = (int)$timeout;
180
        }
181
        $this->do_debug = $debug_level;
182
        $this->username = $username;
183
        $this->password = $password;
184
        //  Reset the error log
185
        $this->errors = [];
186
        //  connect
187
        $result = $this->connect($this->host, $this->port, $this->tval);
188
        if ($result) {
189
            $login_result = $this->login($this->username, $this->password);
190
            if ($login_result) {
191
                $this->disconnect();
192
193
                return true;
194
            }
195
        }
196
        // We need to disconnect regardless of whether the login succeeded
197
        $this->disconnect();
198
199
        return false;
200
    }
201
202
    /**
203
     * Connect to a POP3 server.
204
     * @access public
205
     * @param string $host
206
     * @param int    $port
0 ignored issues
show
Documentation introduced by
Should the type for parameter $port not be false|integer?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
207
     * @param int    $tval
208
     * @return bool
209
     */
210
    public function connect($host, $port = false, $tval = 30)
211
    {
212
        //  Are we already connected?
213
        if ($this->connected) {
214
            return true;
215
        }
216
217
        //On Windows this will raise a PHP Warning error if the hostname doesn't exist.
218
        //Rather than suppress it with @fsockopen, capture it cleanly instead
219
        set_error_handler([$this, 'catchWarning']);
220
221
        if (false === $port) {
222
            $port = $this->POP3_PORT;
223
        }
224
225
        //  connect to the POP3 server
226
        $this->pop_conn = fsockopen($host, //  POP3 Host
227
                                    $port, //  Port #
228
                                    $errno, //  Error Number
229
                                    $errstr, //  Error Message
230
                                    $tval); //  Timeout (seconds)
231
        //  Restore the error handler
232
        restore_error_handler();
233
234
        //  Did we connect?
235
        if (false === $this->pop_conn) {
236
            //  It would appear not...
237
            $this->setError([
238
                                'error'  => "Failed to connect to server $host on port $port",
239
                                'errno'  => $errno,
240
                                'errstr' => $errstr,
241
                            ]);
242
243
            return false;
244
        }
245
246
        //  Increase the stream time-out
247
        stream_set_timeout($this->pop_conn, $tval, 0);
248
249
        //  Get the POP3 server response
250
        $pop3_response = $this->getResponse();
251
        //  Check for the +OK
252
        if ($this->checkResponse($pop3_response)) {
253
            //  The connection is established and the POP3 server is talking
254
            $this->connected = true;
255
256
            return true;
257
        }
258
259
        return false;
260
    }
261
262
    /**
263
     * Log in to the POP3 server.
264
     * Does not support APOP (RFC 2828, 4949).
265
     * @access public
266
     * @param string $username
267
     * @param string $password
268
     * @return bool
269
     */
270
    public function login($username = '', $password = '')
271
    {
272
        if (!$this->connected) {
273
            $this->setError('Not connected to POP3 server');
274
        }
275
        if (empty($username)) {
276
            $username = $this->username;
277
        }
278
        if (empty($password)) {
279
            $password = $this->password;
280
        }
281
282
        // Send the Username
283
        $this->sendString("USER $username" . self::CRLF);
284
        $pop3_response = $this->getResponse();
285
        if ($this->checkResponse($pop3_response)) {
286
            // Send the Password
287
            $this->sendString("PASS $password" . self::CRLF);
288
            $pop3_response = $this->getResponse();
289
            if ($this->checkResponse($pop3_response)) {
290
                return true;
291
            }
292
        }
293
294
        return false;
295
    }
296
297
    /**
298
     * Disconnect from the POP3 server.
299
     * @access public
300
     */
301
    public function disconnect()
302
    {
303
        $this->sendString('QUIT');
304
        //The QUIT command may cause the daemon to exit, which will kill our connection
305
        //So ignore errors here
306
        try {
307
            @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...
308
        }
309
        catch (Exception $e) {
310
            //Do nothing
311
        }
312
    }
313
314
    /**
315
     * Get a response from the POP3 server.
316
     * $size is the maximum number of bytes to retrieve
317
     * @param int $size
318
     * @return string
319
     * @access protected
320
     */
321
    protected function getResponse($size = 128)
322
    {
323
        $response = fgets($this->pop_conn, $size);
324
        if ($this->do_debug >= 1) {
325
            echo "Server -> Client: $response";
326
        }
327
328
        return $response;
329
    }
330
331
    /**
332
     * Send raw data to the POP3 server.
333
     * @param string $string
334
     * @return int
335
     * @access protected
336
     */
337
    protected function sendString($string)
338
    {
339
        if ($this->pop_conn) {
340
            if ($this->do_debug >= 2) { //Show client messages when debug >= 2
341
                echo "Client -> Server: $string";
342
            }
343
344
            return fwrite($this->pop_conn, $string, mb_strlen($string));
345
        }
346
347
        return 0;
348
    }
349
350
    /**
351
     * Checks the POP3 server response.
352
     * Looks for for +OK or -ERR.
353
     * @param string $string
354
     * @return bool
355
     * @access protected
356
     */
357
    protected function checkResponse($string)
358
    {
359
        if ('+OK' !== mb_substr($string, 0, 3)) {
360
            $this->setError([
361
                                'error'  => "Server reported an error: $string",
362
                                'errno'  => 0,
363
                                'errstr' => '',
364
                            ]);
365
366
            return false;
367
        }
368
369
        return true;
370
    }
371
372
    /**
373
     * Add an error to the internal error store.
374
     * Also display debug output if it's enabled.
375
     * @param $error
376
     * @access protected
377
     */
378
    protected function setError($error)
379
    {
380
        $this->errors[] = $error;
381
        if ($this->do_debug >= 1) {
382
            echo '<pre>';
383
            foreach ($this->errors as $error) {
384
                print_r($error);
385
            }
386
            echo '</pre>';
387
        }
388
    }
389
390
    /**
391
     * Get an array of error messages, if any.
392
     * @return array
393
     */
394
    public function getErrors()
395
    {
396
        return $this->errors;
397
    }
398
399
    /**
400
     * POP3 connection error handler.
401
     * @param int    $errno
402
     * @param string $errstr
403
     * @param string $errfile
404
     * @param int    $errline
405
     * @access protected
406
     */
407
    protected function catchWarning($errno, $errstr, $errfile, $errline)
408
    {
409
        $this->setError([
410
                            'error'   => 'Connecting to the POP3 server raised a PHP warning: ',
411
                            'errno'   => $errno,
412
                            'errstr'  => $errstr,
413
                            'errfile' => $errfile,
414
                            'errline' => $errline,
415
                        ]);
416
    }
417
}
418