Location: PHPKode > scripts > clsImap > clsimap/clsImap.php
<?
/***************************************************************************************
Título/Title: 	 Modulo para el acceso a servidores de Correo.
				 Mail access module

Autor/Author:	 Daniel Marjos

Descripción/     Estos servicios pueden ser utilizados tanto para acceder a casillas IMAP, como tambien 
Descripion:      a casillas POP3 y NNTP
				 This services can be used to access IMAP, POP3 and NNTP accounts

F. Inicio/
Started At:		 21 de Agosto de 2003 / August 21, 2003

Ult Modif./
Last Modified:   21 de Agosto de 2003 / August 21, 2003
***************************************************************************************/

/*

This class represents a single message.
Esta clase representa un unico mensaje.

The fields are quite self-explanatories, but here is a little documentation:

date 					: the date the message was sent
msgID					: the ID the SMTP server gave to this message
from					: who sent the message. 
to						: the message's recipients. Semicolon separated.
cc						: carbon-copy recipients.
cco						: blind carbon copy
hasAttachments			: True if the message has any attachment. False otherwise
subject					: the message subject
body					: the message body
attachments				: array holding all the attachments
*/
class clsMessage { 
	var $date; 
	var $msgID;
	var $from;
        var $size;
	var $to;
	var $cc;
	var $cco;
	var $hasAttachs = false;
	var $subject;
	var $body;
	var $attachments = array();
}

/*
Main class.


*/
class clsImapHandler {

	var $login = ""; // The login name
	var $password = ""; // Password to log in into the account
	var $servername = "localhost"; // the server to access
	var $protocol = "143/imap/notls"; // default protocol
	var $folder = "INBOX"; // default folder
	var $mbox; // internal use - the mbox identifier
	var $Messages; // the number of messages in the folder
	var $dispos; // internal use - used to process attachments
	var $currMsg; // internal use - the number of current processing message 
	
	/*
	Constructor.
	Sets up the internal fields.
	Receives as parameters:
	
	login 			: as explained above
	password		: as explained above
	server			: optional. allows to set a explicit server to access
	proto			: the protocol to use
	folder			: the folder to access
	*/
	function clsImapHandler($login,$password,$server="",$proto="",$folder="") {
		
		$this->login=$login;
		$this->password=$password;
		if (!empty($server)) $this->servername=$server;
		if (!empty($proto)) $this->protocol=$proto;
		if (!empty($folder)) $this->folder=$folder;
		$this->mbox=-1;
		$this->Messages=0;
		$this->dispos=0;		
	}
	
	/*
	function Open
	
	used to establish a connection to the mail server. Once connected succesfully, it retrieves 
	the number of messages, sets the mailbox identifier, and returns true. If unsuccesfull, 
	returns false
	*/
	function open() {
	
		$fqsn="{".$this->servername.":".$this->protocol."}".$this->folder;
		$_mbox=imap_open($fqsn,$this->login,$this->password);
		if ($_mbox) {
			$_headers=imap_headers($_mbox);
			$this->Messages=count($_headers);
			$this->mbox=$_mbox;
			return true;
		} else {
			return false;
		}
		
	}

	/*
	Function Close
	
	used to close the connection to the server
	*/
	function close() {
		
		imap_close($this->mbox);
		
	}

	/*
	
	Internal function _decodeString
	
	used to decode a string from bas64 or quoted_printable
	
	thanks to PHP.net user comments
	*/
	function _decodeString($theString) {
		if(ereg("=\?.{0,}\?[Bb]\?",$theString)){ 
			$arrHead=split("=\?.{0,}\?[Bb]\?",$theString); 
			while(list($key,$value)=each($arrHead)){ 
				if(ereg("\?=",$value)){ 
					$arrTemp=split("\?=",$value); 
					$arrTemp[0]=base64_decode($arrTemp[0]); 
					$arrHead[$key]=join("",$arrTemp); 
				} 
			} 
			$strHead=join("",$arrHead); 
		} elseif(ereg("=\?.{0,}\?[Qq]\?",$theString)){ 
			$strHead=quoted_printable_decode($theString); 
			$strHead=ereg_replace("=\?.{0,}\?[Qq]\?","",$strHead); 
			$strHead=ereg_replace("\?=","",$strHead); 
		} else {
			$strHead=$theString;
		}
		
		return $strHead;
	}

	/*
	function getMessage
	
	retrieves the message given as parameter.
	
	*/
	function getMessage($msgNo) {

		// sets the internal message pointer
		$this->currMsg=$msgNo;		
		
		// creates a new instance of clsMessage
		$theMessage = new clsMessage;
		
		// get the header info for the message
		$_theHeader=imap_headerinfo($this->mbox,$msgNo);
		
		// ---- Start Block
		/*
		This block sets the from field
		*/
		$_from=array();
		while (list($k,$v)=each($_theHeader->from)){
			if (!empty($v->personal)) {
				$strHead=$this->_decodeString($v->personal);
				$_address="\"".$strHead."\" <".$v->mailbox."@".$v->host.">";
			} else 
				$_address=$v->mailbox."@".$v->host;
			$_from[]="$_address";
		}
		$theMessage->from=implode(";",$_from);
		// ---- End Block

		// ---- Start Block
		/*
		This block sets the to field
		*/
		$_to=array();
		if (is_array($_theHeader->to)) {
			while (list($k,$v)=each($_theHeader->to)){
				if (!empty($v->personal))  {
					$strHead=$this->_decodeString($v->personal);
					$_address="\"".$strHead."\" <".$v->mailbox."@".$v->host.">";
				} else 
					$_address=$v->mailbox."@".$v->host;
				$_to[]=$_address;
			}
		} else
			$_to[]=$_theHeader->to;
		$theMessage->to=implode(";",$_to);
		// ---- End Block

		// ---- Start Block
		/*
		This block sets the cc field
		*/
		$_cc=array();
		if (is_array($_theHeader->cc)) {
			while (list($k,$v)=each($_theHeader->cc)){
				if (!empty($v->personal))  {
					$strHead=$this->_decodeString($v->personal);
					$_address="\"".$strHead."\" <".$v->mailbox."@".$v->host.">";
				} else 
					$_address=$v->mailbox."@".$v->host;
				$_cc[]=$_address;
			}
		} else
			$_cc[]=$_theHeader->cc;
		$theMessage->cc=implode(";",$_cc);
		// ---- End Block

		// ---- Start Block
		/*
		This block sets the cco field
		*/
		$_cco=array();
		if (is_array($_theHeader->cco)) {
			while (list($k,$v)=each($_theHeader->cco)){
				if (!empty($v->personal))  {
					$strHead=$this->_decodeString($v->personal);
					$_address="\"".$strHead."\" <".$v->mailbox."@".$v->host.">";
				} else 
					$_address=$v->mailbox."@".$v->host;
				$_cco[]=$_address;
			}
		} else
			$_cco[]=$_theHeader->cco;
		$theMessage->cco=implode(";",$_cco);
		// ---- End Block

		// sets date, subject and msgID fields
		$theMessage->date=$_theHeader->udate;
		$theMessage->subject=$_theHeader->subject;
		$theMessage->msgID=$_theHeader->message_id;

		// Fetchs the structure for the message
		$_theStructure=imap_fetchstructure($this->mbox,$msgNo);

                $theMessage->size = ceil(($_theStructure->bytes/1024));

		// tries to guess if the message has or not any attachment.
		if ((count($_theStructure->parts)==2) and (($_theStructure->parts[0]->type==0 and $_theStructure->parts[0]->subtype=="PLAIN") and ($_theStructure->parts[1]->type==0 and $_theStructure->parts[1]->subtype=="HTML"))) {
			$theMessage->hasAttachs=0;
		} else {
			$theMessage->hasAttachs=1;
		}
		
		// if the message has any attach, get them
		if ($theMessage->hasAttachs==1) {
			$this->_getAttachments($theMessage,$_theStructure,1);
		}
		
		$sections = $this->parse($_theStructure);
		if(count($theMessage->attachments)>1) {
			$theMessage->body = imap_fetchbody($this->mbox,  $msgNo, $sections[0]["pid"]);
		} else {
			// sets the body wenn kein attachment
			$theMessage->body = imap_body($this->mbox,$msgNo);
		}
		// returns the message.
		return $theMessage;
	}


	/*
	internal function _getAttachments
	
	This is a recursive function, used to traversing the message to gaet all the attachments to it.
	*/
	function _getAttachments(&$theMessage,$part,$id){

		// How many attachments had we processed so far?		
		$ans=sizeof($theMessage->attachments);

		// if this part has an attach, increase the level.
		if($part->ifdisposition){ 
			$this->dispos++; 
		}
		
		switch($part->type){ // depending on what kind of part we have here...
			case 1: // is this a multipart type? so, skip that...
				if((strtolower($part->subtype)=="mixed") or (strtolower($part->subtype)=="alternative") or (strtolower($part->subtype)=="related")) 
					break;
			default: // Otherwise...

				// How many attachments had we processed so far?		
				$an = sizeof($theMessage->attachments);
				
				if($part->ifdparameters){ // do we have any disposition parameter in this part?
					$dpara = $part->dparameters; // get the parameters
					for ($v=0;$v<sizeof($dpara);$v++){
						if (eregi("filename", $dpara[$v]->attribute)) // is a filename?
							$fname = $dpara[$v]->value; // so, get it...
					}
				}
				if($part->ifparameters){ // do we have any disposition parameter in this part?
					if(empty($fname)){ // is $fname empty? so...
						$para = $part->parameters; // get parameters
						for ($v=0;$v<sizeof($para);$v++){
							if (eregi("name", $para[$v]->attribute)) // do we have a file name ?
								$fname = $para[$v]->value; // so get it...
						}
					}
				}
				
				if ($this->dispos<=1) { // the attachment level is main?
					if(empty($fname)) $fname = "Unknown"; // no file name... :(
					$theMessage->attachments[$an]->id = ($an+1); // sets the attachment ID
					$theMessage->attachments[$an]->part = $id; // sets the attachment part number

					// let's get the mime part number, in the form x.y[.z]
					$_thePartsArray=explode(".",$id);
					$_theParts=array();
					for ($_theIndex=1; $_theIndex<count($_thePartsArray); $_theIndex++){
						$_theParts[]=$_thePartsArray[$_theIndex];
					}
					$_theMimePart=implode(".",$_theParts);
					
					// let's set the fields for this attachment.
					$theMessage->attachments[$an]->mime_part=$_theMimePart;
					$theMessage->attachments[$an]->filename = $fname;
					$theMessage->attachments[$an]->type=$part->type;
					$theMessage->attachments[$an]->subtype=$part->subtype;
					$theMessage->attachments[$an]->dispos=$this->dispos;
					$theMessage->attachments[$an]->disposition=$part->disposition;
					$theMessage->attachments[$an]->size=$part->bytes;
					$theMessage->attachments[$an]->encoding=$part->encoding;
					$theMessage->attachments[$an]->mime_type=$this->_get_mime_type($part);
					$theMessage->attachments[$an]->content=imap_fetchbody($this->mbox,$this->currMsg,$_theMimePart);
				}
				break;
		}
		
		// now, we'll recurse with all the parts found so far...
		for($x = 0; $x < count($part->parts); $x++){
			$this->_getAttachments($theMessage,$part->parts[$x], $id.".".($x+1));
		}
		
		if($part->ifdisposition) $this->dispos--;
	}

	/*
	internal function _get_mime_type
	
	used to get a text representation of the mime part
	*/
	function _get_mime_type(&$structure) {
		$primary_mime_type = array("TEXT", "MULTIPART","MESSAGE", "APPLICATION", "AUDIO","IMAGE", "VIDEO", "OTHER");
		if($structure->subtype) {
			return $primary_mime_type[(int) $structure->type] . '/' .$structure->subtype;
		}
		return "TEXT/PLAIN";
	}
	
	/*
	internal function _get_encoding
	
	not implemented yet. reserved for future extensions.
	*/
	function _get_enconding(&$structure) {
	}

	// parse message body
	
	function parse($structure){
	// Thanks to Harry Wiens
	
	global $type;
	global $encoding;
	
	// create an array to hold message sections
	
	$ret = array();
	
	// split structure into parts
	$parts = $structure->parts;
	
	/*
	iterate through parts
	and create an array whose every element
	represents one part
	each element is itself an associative array
	with keys representing the
	
	- part number
	- part type
	- encoding
	- disposition
	- size
	- filename
	*/
	
	for($x=0; $x<sizeof($parts); $x++) {
		$ret[$x]["pid"] = ($x+1);
		$_this = $parts[$x];
		// default to text
		if ($_this->type == "") $_this->type = 0; 
		$ret[$x]["type"] = $type[$_this->type] . "/" . strtolower($_this->subtype);
		// default to 7bit
		if ($_this->encoding == "") $_this->encoding = 0; 
		$ret[$x]["encoding"] = $encoding[$_this->encoding];
		$ret[$x]["size"] = strtolower($_this->bytes);
		$ret[$x]["disposition"] = strtolower($_this->disposition);
		if (strtolower($_this->disposition) == "attachment") { 
			$params = $_this->dparameters;
			foreach ($params as $p) {
				if($p->attribute == "FILENAME") {
					$ret[$x]["name"] = $p->value;
					break;
				}
			}
		}
		
		return $ret;
	}
	}
	
	
	
}

?>
Return current item: clsImap