Location: PHPKode > projects > OpenBizMap > obm2007.1/mydata/script/clsimap.php
<?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

Modified By: Grzegorz Nawara, OpenDataBag.net, 2006
Fixes.
***************************************************************************************/

/*

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)
  {
    $strHead=quoted_printable_decode($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(1 or 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 delMessage

	removes the message

	*/
	function delMessage($msgNo) {

    imap_delete($this->mbox, $msgNo);
    imap_expunge($this->mbox);
  }

	/*
	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);
		}

    $theMessage->header = $_theHeader;

		$sections = $this->parse($_theStructure);
		if(count($theMessage->attachments)>1)
    {
			$theMessage->body = $this->_decodeString(imap_fetchbody($this->mbox,  $msgNo, $sections[0]["pid"]));
		}
    else//if($_theStructure->parts[0]->type==0 and $_theStructure->parts[0]->subtype=="PLAIN")
    {
      $theMessage->body = $this->_decodeString(imap_fetchbody($this->mbox, $msgNo, 1));
    }
    //~ 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);

          if ($theMessage->attachments[$an]->encoding == 3)
            $theMessage->attachments[$an]->content = base64_decode($theMessage->attachments[$an]->content);
          elseif($theMessage->attachments[$an]->encoding == 4)
            $theMessage->attachments[$an]->content = imap_qprint($theMessage->attachments[$an]->content);

				}
				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: OpenBizMap