<?php
//
// +--------------------------------------------------------------------------+
// | |
// | XS PHP Library Generic Classes Library |
// | |
// | Copyright (c) 2001-2002 XSPHPLib Group. |
// | |
// +--------------------------------------------------------------------------+
// | |
// | Distributed under the terms of the GNU Lesser General Public License as |
// | published by the Free Software Foundation version 2.1 |
// | See the GNU Lesser General Public License for more details. You should |
// | have received a copy of the GNU Lesser General Public License along with |
// | this package; if not, write to the Free Software Foundation, Inc., |
// | 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
// | |
// +--------------------------------------------------------------------------+
// | |
// | Authors: Robert Bala <hide@address.com> |
// | |
// +--------------------------------------------------------------------------+
//
// $Id: pop3.inc.php,v 1.2 2002/11/28 09:50:30 rbala Exp $
/**
* POP3 access class.
*
* POP3 class is a wrapper to the POP3 protocol, as specified by RFC 1939.
* All mandatory POP3 commands are available, as are a few optional POP3
* commands. It can be used to construct POP3 based web mail program, check for
* new mail from the web, or even to authenticate secured areas of the web site.
*
* @author Robert Bala <hide@address.com>
* @access public
* @package net
* @version $Id: pop3.inc.php,v 1.2 2002/11/28 09:50:30 rbala Exp $
*/
class POP3 extends Object {
/**
* IP address or host name.
* @access private
* @var string
*/
var $_host;
/**
* TCP port number.
* @access private
* @var int
*/
var $_port;
/**
* The banner returned by the POP3 server.
* @access private
* @var int
*/
var $_banner;
/**
* The last response status returned by the POP3 server.
* @access private
* @var int
*/
var $_status;
/**
* The socket resource being used to connect to the POP3 server.
* @access private
* @var resource
*/
var $_socket;
/**
* POP3 class constructor.
*
* Creates the new instance of POP3 class and sets up basic properties.
*
* @access public
* @param string $host IP address or host name, defaults to "".
* @param int $port TCP port number, defaults to 110.
* @return void
*/
function POP3($host='', $port=110) {
Object::Object();
$this->_host = $host;
$this->_port = $port;
$this->_banner = '';
$this->_status = '';
$this->_socket = null;
}
/**
* Gets the IP address or host name.
*
* Returns IP address or host name.
*
* @access public
* @return string
*/
function getHost() {
return $this->_host;
}
/**
* Gets the TCP port number.
*
* Returns TCP port number.
*
* @access public
* @return int
*/
function getPort() {
return $this->_port;
}
/**
* Gets the banner returned by the POP3 server.
*
* If called when the connection is already established, it returns the
* banner returned by the POP3 server otherwise it returns empty string.
*
* @access public
* @return string
*/
function getBanner() {
return $this->_banner;
}
/**
* Gets the last response message returned by the POP3 server.
*
* If called when the connection is already established, it returns the
* last response smessage returned by the POP3 server otherwise it returns
* empty string.
*
* @access public
* @return string
*/
function getStatus() {
return $this->_status;
}
/**
* Sets the IP address or host name.
*
* Returns True on success or a error object if the connection is
* already established.
*
* @access public
* @return mixed
*/
function setHost($host) {
if (!$this->isOpened()) {
$this->_host = $host;
} else {
return new Error('sethost(): POP3 connection already established.');
}
return true;
}
/**
* Sets the TCP port number.
*
* Returns True on success or a error object if the connection is
* already established.
*
* @access public
* @return mixed
*/
function setPort($port) {
if (!$this->isOpened()) {
$this->_port = $port;
} else {
return new Error('setport(): POP3 connection already established.');
}
return true;
}
/**
* Attempt to open connection to the POP3 server.
*
* If called when the connection is already established, it returns error
* object otherwise it returns true on success or a error object with an
* error message on any kind of failure.
*
* @access public
* @return mixed
*/
function open() {
if (!$this->isOpened()) {
$socket = new Socket($this->_host, $this->_port, 1, 512);
if (object_isError($socket)) {
return new Error('open(): POP3 unable to open socket.');
}
if (object_isError($socket->open())) {
return new Error('open(): POP3 unable to open socket.');
}
$this->_status = $socket->readLine();
if (pop3_extractCode($this->_status) != '+OK') {
return new Error('open(): POP3 server not 220 ready.');
}
$this->_banner = pop3_extractInfo($this->_status);
$this->_socket =& $socket;
} else {
return new Error('open(): POP3 socket connection already established.');
}
return true;
}
/**
* Attempt to close connection from the POP3 server.
*
* If called when the connection is not established, it returns error
* object otherwise it returns true on success or a error object with an
* error message on any kind of failure.
*
* @access public
* @return mixed
*/
function close() {
if ($this->isOpened()) {
if (object_isError($this->_socket->writeLine('QUIT'))) {
return new Error('close(): POP3 write to socket failed');
}
$this->_status = $this->_socket->readLine();
if (pop3_extractCode($this->_status) != '+OK') {
return new Error('close(): POP3 +OK not received.');
}
if (object_isError($this->_socket->close())) {
return new Error('close(): POP3 unable to close socket.');
}
} else {
return new Error('close(): POP3 socket connection not established.');
}
return true;
}
/**
* Send the RSET command.
*
* If called when the connection is not established, it returns error
* object otherwise it returns true on success or a error object with an
* error message on any kind of failure.
*
* @access public
* @return mixed
*/
function rset() {
if ($this->isOpened()) {
if (object_isError($this->_socket->writeLine('RSET'))) {
return new Error('rset(): POP3 write to socket failed.');
}
$this->_status = $this->_socket->readLine();
if (pop3_extractCode($this->_status) != '+OK') {
return new Error('rset(): POP3 +OK not received.');
}
} else {
return new Error('rset(): POP3 socket connection not established.');
}
return true;
}
/**
* Send the NOOP command.
*
* If called when the connection is not established, it returns error
* object otherwise it returns true on success or a error object with an
* error message on any kind of failure.
*
* @access public
* @return mixed
*/
function noop() {
if ($this->isOpened()) {
if (object_isError($this->_socket->writeLine('NOOP'))) {
return new Error('noop(): POP3 write to socket failed.');
}
$this->_status = $this->_socket->readLine();
if (pop3_extractCode($this->_status) != '+OK') {
return new Error('noop(): POP3 +OK not received.');
}
} else {
return new Error('noop(): POP3 socket connection not established.');
}
return true;
}
/**
* Send the USER command.
*
* If called when the connection is not established, it returns error
* object otherwise it returns true on success or a error object with an
* error message on any kind of failure.
*
* @access public
* @param string $user the username to login.
* @return mixed
*/
function user($user) {
if ($this->isOpened()) {
if (object_isError($this->_socket->writeLine('USER ' . $user))) {
return new Error('user(): POP3 write to socket failed.');
}
$this->_status = $this->_socket->readLine();
if (pop3_extractCode($this->_status) != '+OK') {
return new Error('user(): POP3 +OK not received.');
}
} else {
return new Error('user(): POP3 socket connection not established.');
}
return true;
}
/**
* Send the PASS command.
*
* If called when the connection is not established, it returns error
* object otherwise it returns true on success or a error object with an
* error message on any kind of failure.
*
* @access public
* @param string $pass the password to login.
* @return mixed
*/
function pass($pass) {
if ($this->isOpened()) {
if (object_isError($this->_socket->writeLine('PASS ' . $pass))) {
return new Error('pass(): POP3 write to socket failed.');
}
$this->_status = $this->_socket->readLine();
if (pop3_extractCode($this->_status) != '+OK') {
return new Error('pass(): POP3 +OK not received.');
}
} else {
return new Error('user(): POP3 socket connection not established.');
}
return true;
}
/**
* Attempt to do user authentication.
*
* Attempt to do user authentication at single command. If called when the
* connection is not established, it returns error object otherwise it
* returns true on success or a error object with an error message on any
* kind of failure.
*
* @access public
* @param string $user the username to login.
* @param string $pass the password to login.
* @return mixed
*/
function auth($user, $pass) {
if ($this->isOpened()) {
if (object_isError($this->user($user))) {
return new Error('auth(): POP3 +OK not received.');
}
if (object_isError($this->pass($pass))) {
return new Error('auth(): POP3 +OK not received.');
}
} else {
return new Error('auth(): POP3 socket connection not established.');
}
return true;
}
/**
* Send the STAT command.
*
* If called when the connection is not established, it returns error
* object otherwise it returns array of number of messages and maildrop
* size on success or a error object with an error message on any
* kind of failure.
*
* @access public
* @return mixed
*/
function stat() {
if ($this->isOpened()) {
$count = 0;
$bytes = 0;
if (object_isError($this->_socket->writeLine('STAT'))) {
return new Error('stat(): POP3 write to socket failed.');
}
$this->_status = $this->_socket->readLine();
if (pop3_extractCode($this->_status) != '+OK') {
return new Error('stat(): POP3 +OK not received.');
}
list($reply, $count, $bytes) = explode(' ', $this->_status);
settype($count, 'integer');
settype($bytes, 'integer');
} else {
return new Error('stat(): POP3 socket connection not established.');
}
return array($count, $bytes);
}
/**
* Send the RETR command.
*
* If called when the connection is not established, it returns error
* object otherwise it returns mail message on success or a error object
* with an error message on any kind of failure.
*
* @access public
* @param int $index the message index to retrieve.
* @return mixed
*/
function retr($index) {
if ($this->isOpened()) {
if (object_isError($this->_socket->writeLine('RETR ' . $index))) {
return new Error('retr(): POP3 write to socket failed.');
}
$this->_status = $this->_socket->readLine();
if (pop3_extractCode($this->_status) != '+OK') {
return new Error('retr(): POP3 +OK not received.');
}
$result = '';
do {
$reply = $this->_socket->readLine();
if ((strlen($reply) == 1) && ($reply == '.')) {
break;
}
$result .= $reply . "\r\n";
} while (true);
} else {
return new Error('retr(): POP3 socket connection not established.');
}
return $result;
}
/**
* Send the DELE command.
*
* If called when the connection is not established, it returns error
* object otherwise it returns true on success or a error object with
* an error message on any kind of failure.
*
* @access public
* @param int $index the message index to delete.
* @return mixed
*/
function dele($index) {
if ($this->isOpened()) {
if (object_isError($this->_socket->writeLine('DELE ' . $index))) {
return new Error('dele(): POP3 write to socket failed.');
}
$this->_status = $this->_socket->readLine();
if (pop3_extractCode($this->_status) != '+OK') {
return new Error('dele(): POP3 +OK not received.');
}
} else {
return new Error('dele(): POP3 socket connection not established.');
}
return true;
}
/**
* Send the UIDL command.
*
* If called when the connection is not established, it returns error
* object. If the index param was given the returned value is unique-id of
* the message otherwise it returns array indexed by message index and
* unique-id of the message as the value. In any kind of failure it
* returns error object with an error message.
*
* @access public
* @param int $index the message index (optional), defaults to null.
* @return mixed
*/
function uidl($index=null) {
if ($this->isOpened()) {
if (isset($index) && strlen($index)) {
if (object_isError($this->_socket->writeLine('UIDL ' . $index))) {
return new Error('uidl(): POP3 write to socket failed.');
}
$this->_status = $this->_socket->readLine();
if (pop3_extractCode($this->_status) != '+OK') {
return new Error('uidl(): POP3 +OK not received.');
}
list($reply, $index, $result) = explode(' ', $this->_status);
settype($result, 'string');
} else{
if (object_isError($this->_socket->writeLine('UIDL'))) {
return new Error('uidl(): POP3 write to socket failed.');
}
$this->_status = $this->_socket->readLine();
if (pop3_extractCode($this->_status) != '+OK') {
return new Error('uidl(): POP3 +OK not received.');
}
$result = array();
do {
$reply = $this->_socket->readLine();
if ((strlen($reply) == 1) && ($reply == '.')) {
break;
}
list($index, $ident) = explode(' ', $reply);
settype($ident, 'string');
$result[$index] = $ident;
} while (true);
}
} else {
return new Error('uidl(): POP3 socket connection not established.');
}
return $result;
}
/**
* Send the LIST command.
*
* If called when the connection is not established, it returns error
* object. If the index param was given the returned value is exact size of
* the message in octets otherwise it returns array of arrays which consists
* of index and exact size of the message in octets as the value. In any
* kind of failure it returns error object with an error message.
*
* @access public
* @param int $index the message index (optional), defaults to null.
* @return mixed
*/
function lst($index=null) {
if ($this->isOpened()) {
if (isset($index) && strlen($index)) {
if (object_isError($this->_socket->writeLine('LIST ' . $index))) {
return new Error('lst(): POP3 write to socket failed.');
}
$this->_status = $this->_socket->readLine();
if (pop3_extractCode($this->_status) != '+OK') {
return new Error('lst(): POP3 +OK not received.');
}
list($reply, $index, $result) = explode(' ', $this->_status);
settype($result, 'integer');
} else{
if (object_isError($this->_socket->writeLine('LIST'))) {
return new Error('lst(): POP3 write to socket failed.');
}
$this->_status = $this->_socket->readLine();
if (pop3_extractCode($this->_status) != '+OK') {
return new Error('lst(): POP3 +OK not received.');
}
$result = array();
do {
$reply = $this->_socket->readLine();
if ((strlen($reply) == 1) && ($reply == '.')) {
break;
}
list($index, $bytes) = explode(' ', $reply);
settype($index, 'integer');
settype($bytes, 'integer');
$result[] = array($index, $bytes);
} while (true);
}
} else {
return new Error('lst(): POP3 socket connection not established.');
}
return $result;
}
/**
* Send the TOP command.
*
* If called when the connection is not established, it returns error
* object otherwise it returns headers of the message, the blank
* line separating the headers from the body, and then the number of lines
* of the indicated message's body on success or a error object with
* an error message on any kind of failure.
*
* @access public
* @param int $index the message index to retrieve.
* @param int $index the non-negative number of lines.
* @return mixed
*/
function top($index, $lines) {
if ($this->isOpened()) {
if (object_isError($this->_socket->writeLine('TOP ' . $index . ' ' . $lines))) {
return new Error('top(): POP3 write to socket failed.');
}
$this->_status = $this->_socket->readLine();
if (pop3_extractCode($this->_status) != '+OK') {
return new Error('top(): POP3 +OK not received.');
}
$headers = '';
$message = '';
do {
$reply = $this->_socket->readLine();
if ($reply == '') {
break;
}
$headers .= $reply . "\r\n";
} while (true);
do {
$reply = $this->_socket->readLine();
if ((strlen($reply) == 1) && ($reply == '.')) {
break;
}
$message .= $reply . "\r\n";
} while (true);
} else {
return new Error('top(): POP3 socket connection not established.');
}
return array($headers, $message);
}
/**
* Finds whether the socket connection is opened.
*
* Returns true if the connection is established, false otherwise.
*
* @access public
* @return boolean
*/
function isOpened() {
return (isset($this->_socket) && $this->_socket->isOpened());
}
}
/**
* Extracts response code returned from POP3 server.
*
* Returns response code returned from POP3 server on success, empty string
* otherwise.
*
* @author Robert Bala <hide@address.com>
* @access private
* @param string $string the response returned from POP3 server.
* @return string
*/
function pop3_extractCode($string) {
return strtok($string, ' ');
}
/**
* Extracts response message returned from POP3 server.
*
* Returns response message returned from POP3 server on success, empty string
* otherwise.
*
* @author Robert Bala <hide@address.com>
* @access private
* @param string $string the response returned from POP3 server.
* @return string
*/
function pop3_extractInfo($string) {
$indent = pop3_extractCode($string);
if ($indent == $string) {
return '';
}
return substr($string, strlen($indent) + 1, strlen($string) - strlen($indent) - 1);
}
?>