POP3::disconnect()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 4
dl 0
loc 8
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 0
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.28';
38
39
    /**
40
     * Default POP3 port number.
41
     * @var integer
42
     * @access public
43
     */
44
    public $POP3_PORT = 110;
45
46
    /**
47
     * Default timeout in seconds.
48
     * @var integer
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 integer
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 integer
79
     * @access public
80
     */
81
    public $port;
82
83
    /**
84
     * POP3 Timeout Value in seconds.
85
     * @var integer
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 boolean
114
     * @access protected
115
     */
116
    protected $connected = false;
117
118
    /**
119
     * Error container.
120
     * @var array
121
     * @access protected
122
     */
123
    protected $errors = array();
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 integer|boolean $port The port number to connect to
134
     * @param integer|boolean $timeout The timeout value
135
     * @param string $username
136
     * @param string $password
137
     * @param integer $debug_level
138
     * @return boolean
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 POP3;
149
        return $pop->authorise($host, $port, $timeout, $username, $password, $debug_level);
150
    }
151
152
    /**
153
     * Authenticate with a POP3 server.
154
     * A connect, login, disconnect sequence
155
     * appropriate for POP-before SMTP authorisation.
156
     * @access public
157
     * @param string $host The hostname to connect to
158
     * @param integer|boolean $port The port number to connect to
159
     * @param integer|boolean $timeout The timeout value
160
     * @param string $username
161
     * @param string $password
162
     * @param integer $debug_level
163
     * @return boolean
164
     */
165
    public function authorise($host, $port = false, $timeout = false, $username = '', $password = '', $debug_level = 0)
166
    {
167
        $this->host = $host;
168
        // If no port value provided, use default
169
        if (false === $port) {
170
            $this->port = $this->POP3_PORT;
171
        } else {
172
            $this->port = (integer)$port;
173
        }
174
        // If no timeout value provided, use default
175
        if (false === $timeout) {
176
            $this->tval = $this->POP3_TIMEOUT;
177
        } else {
178
            $this->tval = (integer)$timeout;
179
        }
180
        $this->do_debug = $debug_level;
181
        $this->username = $username;
182
        $this->password = $password;
183
        //  Reset the error log
184
        $this->errors = array();
185
        //  connect
186
        $result = $this->connect($this->host, $this->port, $this->tval);
187
        if ($result) {
188
            $login_result = $this->login($this->username, $this->password);
189
            if ($login_result) {
190
                $this->disconnect();
191
                return true;
192
            }
193
        }
194
        // We need to disconnect regardless of whether the login succeeded
195
        $this->disconnect();
196
        return false;
197
    }
198
199
    /**
200
     * Connect to a POP3 server.
201
     * @access public
202
     * @param string $host
203
     * @param integer|boolean $port
204
     * @param integer $tval
205
     * @return boolean
206
     */
207
    public function connect($host, $port = false, $tval = 30)
208
    {
209
        //  Are we already connected?
210
        if ($this->connected) {
211
            return true;
212
        }
213
214
        //On Windows this will raise a PHP Warning error if the hostname doesn't exist.
215
        //Rather than suppress it with @fsockopen, capture it cleanly instead
216
        set_error_handler(array($this, 'catchWarning'));
217
218
        if (false === $port) {
219
            $port = $this->POP3_PORT;
220
        }
221
222
        //  connect to the POP3 server
223
        $this->pop_conn = fsockopen(
224
            $host, //  POP3 Host
225
            $port, //  Port #
0 ignored issues
show
Bug introduced by
It seems like $port can also be of type boolean; however, parameter $port of fsockopen() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

225
            /** @scrutinizer ignore-type */ $port, //  Port #
Loading history...
226
            $errno, //  Error Number
227
            $errstr, //  Error Message
228
            $tval
229
        ); //  Timeout (seconds)
230
        //  Restore the error handler
231
        restore_error_handler();
232
233
        //  Did we connect?
234
        if (false === $this->pop_conn) {
235
            //  It would appear not...
236
            $this->setError(array(
237
                'error' => "Failed to connect to server $host on port $port",
238
                'errno' => $errno,
239
                'errstr' => $errstr
240
            ));
241
            return false;
242
        }
243
244
        //  Increase the stream time-out
245
        stream_set_timeout($this->pop_conn, $tval, 0);
246
247
        //  Get the POP3 server response
248
        $pop3_response = $this->getResponse();
249
        //  Check for the +OK
250
        if ($this->checkResponse($pop3_response)) {
251
            //  The connection is established and the POP3 server is talking
252
            $this->connected = true;
253
            return true;
254
        }
255
        return false;
256
    }
257
258
    /**
259
     * Log in to the POP3 server.
260
     * Does not support APOP (RFC 2828, 4949).
261
     * @access public
262
     * @param string $username
263
     * @param string $password
264
     * @return boolean
265
     */
266
    public function login($username = '', $password = '')
267
    {
268
        if (!$this->connected) {
269
            $this->setError('Not connected to POP3 server');
270
        }
271
        if (empty($username)) {
272
            $username = $this->username;
273
        }
274
        if (empty($password)) {
275
            $password = $this->password;
276
        }
277
278
        // Send the Username
279
        $this->sendString("USER $username" . self::CRLF);
280
        $pop3_response = $this->getResponse();
281
        if ($this->checkResponse($pop3_response)) {
282
            // Send the Password
283
            $this->sendString("PASS $password" . self::CRLF);
284
            $pop3_response = $this->getResponse();
285
            if ($this->checkResponse($pop3_response)) {
286
                return true;
287
            }
288
        }
289
        return false;
290
    }
291
292
    /**
293
     * Disconnect from the POP3 server.
294
     * @access public
295
     */
296
    public function disconnect()
297
    {
298
        $this->sendString('QUIT');
299
        //The QUIT command may cause the daemon to exit, which will kill our connection
300
        //So ignore errors here
301
        try {
302
            @fclose($this->pop_conn);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for fclose(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

302
            /** @scrutinizer ignore-unhandled */ @fclose($this->pop_conn);

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...
303
        } catch (Exception $e) {
304
            //Do nothing
305
        };
306
    }
307
308
    /**
309
     * Get a response from the POP3 server.
310
     * $size is the maximum number of bytes to retrieve
311
     * @param integer $size
312
     * @return string
313
     * @access protected
314
     */
315
    protected function getResponse($size = 128)
316
    {
317
        $response = fgets($this->pop_conn, $size);
318
        if ($this->do_debug >= 1) {
319
            echo "Server -> Client: $response";
320
        }
321
        return $response;
322
    }
323
324
    /**
325
     * Send raw data to the POP3 server.
326
     * @param string $string
327
     * @return integer
328
     * @access protected
329
     */
330
    protected function sendString($string)
331
    {
332
        if ($this->pop_conn) {
333
            if ($this->do_debug >= 2) { //Show client messages when debug >= 2
334
                echo "Client -> Server: $string";
335
            }
336
            return fwrite($this->pop_conn, $string, strlen($string));
337
        }
338
        return 0;
339
    }
340
341
    /**
342
     * Checks the POP3 server response.
343
     * Looks for for +OK or -ERR.
344
     * @param string $string
345
     * @return boolean
346
     * @access protected
347
     */
348
    protected function checkResponse($string)
349
    {
350
        if (substr($string, 0, 3) !== '+OK') {
351
            $this->setError(array(
352
                'error' => "Server reported an error: $string",
353
                'errno' => 0,
354
                'errstr' => ''
355
            ));
356
            return false;
357
        } else {
358
            return true;
359
        }
360
    }
361
362
    /**
363
     * Add an error to the internal error store.
364
     * Also display debug output if it's enabled.
365
     * @param $error
366
     * @access protected
367
     */
368
    protected function setError($error)
369
    {
370
        $this->errors[] = $error;
371
        if ($this->do_debug >= 1) {
372
            echo '<pre>';
373
            foreach ($this->errors as $error) {
0 ignored issues
show
introduced by
$error is overwriting one of the parameters of this function.
Loading history...
374
                print_r($error);
375
            }
376
            echo '</pre>';
377
        }
378
    }
379
380
    /**
381
     * Get an array of error messages, if any.
382
     * @return array
383
     */
384
    public function getErrors()
385
    {
386
        return $this->errors;
387
    }
388
389
    /**
390
     * POP3 connection error handler.
391
     * @param integer $errno
392
     * @param string $errstr
393
     * @param string $errfile
394
     * @param integer $errline
395
     * @access protected
396
     */
397
    protected function catchWarning($errno, $errstr, $errfile, $errline)
398
    {
399
        $this->setError(array(
400
            'error' => "Connecting to the POP3 server raised a PHP warning: ",
401
            'errno' => $errno,
402
            'errstr' => $errstr,
403
            'errfile' => $errfile,
404
            'errline' => $errline
405
        ));
406
    }
407
}
408