<?php

class POP3
{
    public $POP3_PORT = 110;
    public $POP3_TIMEOUT = 30;
    public $CRLF = "\r\n";
    public $do_debug = 2;
    public $host = NULL;
    public $port = NULL;
    public $tval = NULL;
    public $username = NULL;
    public $password = NULL;
    private $pop_conn = NULL;
    private $connected = NULL;
    private $error = NULL;
    public function __construct()
    {
        $this->pop_conn = 0;
        $this->connected = false;
        $this->error = NULL;
    }
    public function Authorise($host, $port = false, $tval = false, $username, $password, $debug_level = 0)
    {
        $this->host = $host;
        if (!$port) {
            $this->port = $this->POP3_PORT;
        } else {
            $this->port = $port;
        }
        if (!$tval) {
            $this->tval = $this->POP3_TIMEOUT;
        } else {
            $this->tval = $tval;
        }
        $this->do_debug = $debug_level;
        $this->username = $username;
        $this->password = $password;
        $this->error = NULL;
        $result = $this->Connect($this->host, $this->port, $this->tval);
        if ($result) {
            $login_result = $this->Login($this->username, $this->password);
            if ($login_result) {
                $this->Disconnect();
                return true;
            }
        }
        $this->Disconnect();
        return false;
    }
    public function Connect($host, $port = false, $tval = 30)
    {
        if ($this->connected) {
            return true;
        }
        set_error_handler([$this, "catchWarning"]);
        $this->pop_conn = fsockopen($host, $port, $errno, $errstr, $tval);
        restore_error_handler();
        if ($this->error && 1 <= $this->do_debug) {
            $this->displayErrors();
        }
        if (!$this->pop_conn) {
            $this->error = ["error" => "Failed to connect to server " . $host . " on port " . $port, "errno" => $errno, "errstr" => $errstr];
            if (1 <= $this->do_debug) {
                $this->displayErrors();
            }
            return false;
        }
        if (version_compare(phpversion(), "5.0.0", "ge")) {
            stream_set_timeout($this->pop_conn, $tval, 0);
        } else {
            if (substr(PHP_OS, 0, 3) !== "WIN") {
                socket_set_timeout($this->pop_conn, $tval, 0);
            }
        }
        $pop3_response = $this->getResponse();
        if ($this->checkResponse($pop3_response)) {
            $this->connected = true;
            return true;
        }
    }
    public function Login($username = "", $password = "")
    {
        if (!$this->connected) {
            $this->error = "Not connected to POP3 server";
            if (1 <= $this->do_debug) {
                $this->displayErrors();
            }
        }
        if (empty($username)) {
            $username = $this->username;
        }
        if (empty($password)) {
            $password = $this->password;
        }
        $pop_username = "USER " . $username . $this->CRLF;
        $pop_password = "PASS " . $password . $this->CRLF;
        $this->sendString($pop_username);
        $pop3_response = $this->getResponse();
        if ($this->checkResponse($pop3_response)) {
            $this->sendString($pop_password);
            $pop3_response = $this->getResponse();
            if ($this->checkResponse($pop3_response)) {
                return true;
            }
            return false;
        }
        return false;
    }
    public function Disconnect()
    {
        $this->sendString("QUIT");
        fclose($this->pop_conn);
    }
    private function getResponse($size = 128)
    {
        $pop3_response = fgets($this->pop_conn, $size);
        return $pop3_response;
    }
    private function sendString($string)
    {
        $bytes_sent = fwrite($this->pop_conn, $string, strlen($string));
        return $bytes_sent;
    }
    private function checkResponse($string)
    {
        if (substr($string, 0, 3) !== "+OK") {
            $this->error = ["error" => "Server reported an error: " . $string, "errno" => 0, "errstr" => ""];
            if (1 <= $this->do_debug) {
                $this->displayErrors();
            }
            return false;
        }
        return true;
    }
    private function displayErrors()
    {
        echo "<pre>";
        foreach ($this->error as $single_error) {
            print_r($single_error);
        }
        echo "</pre>";
    }
    private function catchWarning($errno, $errstr, $errfile, $errline)
    {
        $this->error[] = ["error" => "Connecting to the POP3 server raised a PHP warning: ", "errno" => $errno, "errstr" => $errstr];
    }
}

?>