#native_company# #native_desc#
#native_cta#

POP3 class with secure APOP authentication

By Kevin McDermott
on May 10, 2001

Version: 0.3

Type: Class

Category: Networking

License: GNU General Public License

Description: This class allows you to maintain a POP3 connection, and authenticate through the secure APOP method or through the traditional plain text manner. Server error checking is handled more appropriatly than the POP3 functions in the standard php ‘imap_’ library.

# A class to allow you to connect to POP3 servers 

# Written by someone on some newsgroup, but modified by me, 
# Kevin McDermott [email protected]

class Pop3 {
	var $user;
	var $pass;
	var $Socket;				// the current socket
	var $Line;
	var $Status;
	var $Banner;

	function Pop3($Server = "localhost",$Port = 110)
	{    
		return $this->pop3_open($Server, $Port);
	}

	# This will handle the connection process for you, just feed it the
	# information it needs. It will default to APOP secure connection but
	# fall back to plain text if that doesn't work.  WARNING: some servers
	# will kick you out after one failed attempt so after the failed APOP
	# authentication, you'll be kicked out, and this will fail, disable
	# APOP authentication if this is the case, and APOP doesn't work.
	function Pop3($Server = "localhost", $Port = 110, $user = "", $pass = "") {
		if ( !$this->pop3_open($Server, $Port) ) {
			$this->Status["Connection"] = 
			    "Could not contact server '$Server' on port $Port";
			return;
		}

		if (false && $this->Banner) { # disable this pending further APOP tests
			 if (!$this->pop3_apop($user, $pass)) {
				if ( !$this->pop3_user($user) ) {
					$this->Status["Connection"] = "Username '$user' is invalid";
					return;
				}
				if ( !$this->pop3_pass($pass) ) {
					$this->Status["Connection"] = 
					    "Username '$user' or Password is invalid";
					return;
				}
			}
		} else {
			if ( !$this->pop3_user($user) ) {
				$this->Status["Connection"] = "Username '$user' is invalid";
				return;
			}
			if ( !$this->pop3_pass($pass) ) {
				$this->Status["Connection"] = 
				    "Username '$user' or Password is invalid";
				return;
			}	
		}
		return true;
	}

	function pop3_open($server, $port)  
	{

		$this->Socket = fsockopen($server, $port);
		if ($this->Socket <= 0){
			return false;
		}
		$this->Line = fgets($this->Socket, 1024);
		$this->Status["LASTRESULT"] = substr($this->Line, 0, 1);
		$this->Status["LASTRESULTTXT"] = substr($this->Line, 0, 1024);
		if (preg_match("/<[wd-.]+@[wd-.]+>/",
			$this->Status["LASTRESULTTXT"], $matched)) {
			$this->Banner = $matched[0];
		} else {
			$this->Banner = "";
		}
	
		if ($this->Status["LASTRESULT"] <> "+") return false;
		return true;
	}

	function pop3_user($user)
	{
		$this->user = $user;
		if ($this->Socket < 0){
		  return false;
		}
		fputs($this->Socket, "USER $this->userrn");
		$this->Line = fgets($this->Socket, 1024);
		$this->Status["LASTRESULT"] = substr($this->Line, 0, 1);
		$this->Status["LASTRESULTTXT"] = substr($this->Line, 0, 1024);

		if ($this->Status["LASTRESULT"] <> "+") return false;

		return true;
	}

	function pop3_pass($pass)
	{
		$this->pass = $pass;
		fputs($this->Socket, "PASS $this->passrn");
		$this->Line = fgets($this->Socket, 1024);
		$this->Status["LASTRESULT"] = substr($this->Line, 0, 1);
		$this->Status["LASTRESULTTXT"] = substr($this->Line, 0, 1024);

		if ($this->Status["LASTRESULT"] <> "+") return false;

		return true;
	}
	function pop3_apop($user, $pass)
	{
		fputs($this->Socket, "APOP $user ".md5($this->Banner.$pass)."rn");
		$this->Line = fgets($this->Socket, 1024);
		$this->Status["LASTRESULT"] = substr($this->Line, 0, 1);
		$this->Status["LASTRESULTTXT"] = substr($this->Line, 0, 1024);

		if ($this->Status["LASTRESULT"] <> "+") return false;

		return true;
	}
	function pop3_stat()
	{

		fputs($this->Socket, "STATrn");
		$this->Line = fgets($this->Socket, 1024);
		$this->Status["LASTRESULT"] = substr($this->Line, 0, 1);
		$this->Status["LASTRESULTTXT"] = substr($this->Line, 0, 1024);

		if ($this->Status["LASTRESULT"] <> "+") return false;

		if (!eregi("+OK (.*) (.*)", $this->Line, $regs)) 
			return false;

		return $regs[1];
	}

	function pop3_list()
	{
		fputs($this->Socket, "LISTrn");
		$this->Line = fgets($this->Socket, 1024);
		$this->Status["LASTRESULT"] = substr($this->Line, 0, 1);
		$this->Status["LASTRESULTTXT"] = substr($this->Line, 0, 1024);

		if ($this->Status["LASTRESULT"] <> "+") return false;

		$i = 0;
		while (substr($this->Line = fgets($this->Socket, 1024), 0, 1) <> ".") {
			$articles[$i] = $this->Line;
			$i++;
		}

		return $articles;
	}

	# This retreaves the whole message, and sets the Status: field in the 
	# message to read (it adds an 'R' to that field).
	function pop3_retr($nr)
	{
	
		fputs($this->Socket, "RETR $nrrn");
		$this->Line = fgets($this->Socket, 1024);
		$this->Status["LASTRESULT"] = substr($this->Line, 0, 1);
		$this->Status["LASTRESULTTXT"] = substr($this->Line, 0, 1024);

		if ($this->Status["LASTRESULT"] <> "+") return 0;

		while (substr($this->Line = fgets($this->Socket, 1024), 0, 1) <> ".") {
			$data[$i] = $this->Line;
			$i++;
		}

		return $data;
	}

	# This will view the header of a message (and $lines number of lines
	# afterwards WITHOUT setting the Status: field as read (doesn't add an 'R'
	# to that field.
	function pop3_top($nr, $lines)
	{
	
		fputs($this->Socket, "TOP $nr $linesrn");
		$this->Line = fgets($this->Socket, 1024);
		$this->Status["LASTRESULT"] = substr($this->Line, 0, 1);
		$this->Status["LASTRESULTTXT"] = substr($this->Line, 0, 1024);

		if ($this->Status["LASTRESULT"] <> "+") return 0;

		while (substr($this->Line = fgets($this->Socket, 1024), 0, 1) <> ".") {
			$data[$i] = $this->Line;
			$i++;
		}

		return $data;
	}

	function pop3_dele( $nr)
	{

		fputs($this->Socket, "DELE $nrrn");
		$this->Line = fgets($this->Socket, 1024);
		$this->Status["LASTRESULT"] = substr($this->Line, 0, 1);
		$this->Status["LASTRESULTTXT"] = substr($this->Line, 0, 1024);

		if ($this->Status["LASTRESULT"] <> "+") return 0;
		return 1;
	}

	function pop3_quit()
	{

		fputs($this->Socket, "QUITrn");
		$this->Line = fgets($this->Socket, 1024);
		$this->Status["LASTRESULT"] = substr($this->Line, 0, 1);
		$this->Status["LASTRESULTTXT"] = substr($this->Line, 0, 1024);

		if ($this->Status["LASTRESULT"] <> "+") return 0;

		return 1;
	}
}