Location: PHPKode > scripts > Mail Parser > mail-parser/MailParser.php
<?php
/**
 * Author:  Ashish Kumar Srivastava
 * Email:   hide@address.com 
 * Purpose: The class is written for parsing IMAP supported mailbox

 *
 * This class is used for parsing IMAP supported mailboxes.
 * It is used for accessing plain text, html, headers and attachements of the messages 
 * by message id, by subject, by received date, by sender address of the messages. It can also
 * filter messages by unread status. If more than one message have  same subject or received date
 * or from address then it accesses all the messages and provides information for each.
 */

class MailParser {

	const MESSAGE_ID		= 0;
    const RECEIVED_DATE		= 1;
	const SUBJECT			= 2;
	const FROM_ADDRESS		= 3;
	const UNREAD			= 4;
	const TRY_TO_CONNECT	= 3; // Try to connect mail server three times

	/**
	 * This array is resultant array which further contains an associative array as an element.
	 * And the associative array contain attachments, htmlBody, plainBody as its keys.
	 *
	 * @var Array
	 */
	private $result = array();

	/**
	 * This associative array contains attached file name as a key
	 * and corresponding binary file as a value.
	 *
	 * @var Array
	 */
	private $attachments = array();

	/**
	 * This contains standard object of header information
	 *
	 * @var Object
	 */
	private $headers;

	/**
	 * This variable conatains the html part of a message.
	 *
	 * @var String
	 */
	private $htmlBody = '';

	/**
	 * This variable conatains the plain text part of a message.
	 *
	 * @var String
	 */
	private $plainBody = "";

	/**
	 * It consists a mail server name
	 *
	 * @var string
	 */
	private $mailServerName = '';

	/**
	 * User name for the mail account
	 *
	 * @var string
	 */
	private $userName = '';

	/**
	 * Password for the mail account
	 *
	 * @var string
	 */
	private $password = '';


	/**
	 * Parameterised constructor
	 */
	function __construct($mailServerName, $userName, $password) {
		$this->mailServerName = $mailServerName;
		$this->userName		  = $userName;
		$this->password		  = $password;
	}

	/**
	 * This is the funtion for settion connection to the given mail server.
	 * 
	 * @param String $mailbox
	 * @param String $user
	 * @param String $pass
	 * @param IMAP stream as a connection
	 * @return IMAP stream as a connection
	 */
	public function setConnection($mailbox, $user, $pass, $conn = null) {		

		// If connection is not exist then make a connection
		if(!$conn) {
			// If folder name for processing is not present
			if (substr(trim($mailbox), -1) == '}') {
				$mailbox = $mailbox . 'INBOX';
			}
			// Try to connect three times 
			for($i = 0; $i < self::TRY_TO_CONNECT; $i++) {
				$conn = imap_open($mailbox, $user, $pass);
				if($conn) {
					return $conn;
				}
			}	
			echo 'Unable to connect mail server';
			exit(); // User can throw an exception here
		}
		return $conn;
	}

	/**
	 * This is the funtion for getting message
	 * 
	 * @param String $conn
	 * @param Integer $messageId
	 */
	public function getMessage($conn, $messageId) {

		$structure = imap_fetchstructure($conn, $messageId);

		// If message is not multipart
		if (!$structure->parts) {
			$this->getMessagePart($conn, $messageId, $structure, 0);
		}
		else {
			foreach ($structure->parts as $partno => $part) {
				$this->getMessagePart($conn, $messageId, $part, $partno+1);
			}
		 }
	}

	/**
	 * This is the funtion for parsing messge parts
	 * 
	 * @param String $conn
	 * @param Integer $messageId
	 * @param Object $partObj
	 * @param Integer $partno
	 */
	public function getMessagePart($conn, $messageId, $partObj, $partno) {   

		// If partno is 0 then fetch body as a single part message
		$data = ($partno) ? imap_fetchbody($conn, $messageId, $partno) : imap_body($conn, $messageId);

		// Any part may be encoded, even plain text messages, so decoding it
		if ($partObj->encoding == 4) {
			$data = quoted_printable_decode($data);
		}
		elseif ($partObj->encoding == 3) {
			$data = base64_decode($data);
		}

		// Collection all parameters, like name, filenames of attachments, etc.
		$params = array();
		if ($partObj->parameters) {
			foreach ((array) $partObj->parameters as $x) {
				$params[strtolower($x->attribute)] = $x->value;
			}
		}
		if ($partObj->dparameters) {
			foreach ((array) $partObj->dparameters as $x) {
				$params[strtolower($x->attribute)] = $x->value;
			}
		}

		// Any part with a filename is an attachment,
		if ($params['filename'] || $params['name']) {
			// Filename may be given as 'Filename' or 'Name' or both
			$filename = ($params['filename'])? $params['filename'] : $params['name'];
			$this->attachments[$filename] = $data;
		}

		// Processing plain text message
		if ($partObj->type == 0 && $data) {
			// Messages may be split in different parts because of inline attachments,
			// so append parts together with blank row.
			if (strtolower($partObj->subtype) == 'plain') {
				$this->plainBody .= trim($data);
			}
			else {
				$this->htmlBody .= $data;
			}
		}

		// Some times it happens that one message embeded in another.
		// This is used to appends the raw source to the main message.
		elseif ($partObj->type == 2 && $data) {
			$this->plainBody .= $data;
		}

		// Here is recursive call for subpart of the message
		if ($partObj->parts) {
			foreach ((array) $partObj->parts as $partno2 => $part2) {
				$this->getMessagePart($conn, $messageId, $part2, $partno.'.'.($partno2+1));
			}
		}
	}

	/**
	 * This is the funtion for parsing message
	 * 
	 * @param String $conn
	 * @param Integer $messageId
	 */
	public function parseMessage($conn, $messageId) {

		$this->getMessage($conn, $messageId);
		$this->makeResult();
	}

	/**
	 * Return Received date in to mm-dd-yyyy format
	 *
	 * @param String $date format Thu, 20 Aug 2009 15:55:52 +0530
	 * @return String $date format 08-20-2009
	 */
	private function getRecDate($date) {
		$date = substr($date, 5, 20);
		$timestamp = strtotime($date);
		return date('m-d-Y', $timestamp);
	}

	/**
	 * This function is used for checking the particular email id is present
	 * in the from addresses of headder information. It returns true if present,
	 * otherwise returns false.
	 * 
	 * @param String $fromAddresses
	 * @param String $userInput
	 */
	private function containsFromAddress($fromAddresses, $userInput) {
		
		if(strpos($fromAddresses, $userInput) != false) {
			return true;
		}
		return false;
	}

	/**
	 * Used for parsing the message by message id.
	 * If flag is false then fuction parse the message with given message id,
	 * otherwise parse only if message with given id is unread.
	 *
	 * @param Integer $messageId
	 * @param Boolean $flag 
	 */
	public function pasrseMessageById($messageId, $flag = false) {
		$this->parseMessageByFilter($messageId, self::MESSAGE_ID, $flag);
	}

	/**
	 * Used for parsing unread messages.
	 *
	 */
	public function pasrseUnreadMessages() {
		$this->parseMessageByFilter('', self::UNREAD, true);
	}

	/**
	 * Used for parsing the message by subject of the message.
	 * If flag is false then fuction parse all the messages with given subject,
	 * otherwise parse only unread messages with the given subject.
	 *
	 * @param Integer $subject
	 * @param Boolean $flag 
	 */
	public function pasrseMessagesBySubject($subject, $flag = false) {
		$this->parseMessageByFilter($subject, self::SUBJECT, $flag);
	}
	
	/**
	 * Used for parsing the message by the from address of the messages.
	 * If flag is false then fuction parse all the messages with given from address,
	 * otherwise parse only unread messages with the given from address.
	 *
	 * @param Integer $fromAddress
	 * @param Boolean $flag 
	 */
	public function pasrseMessagesByFromAddress($fromAddress, $flag = false) {
		$this->parseMessageByFilter($fromAddress, self::FROM_ADDRESS, $flag);
	}

	/**
	 * Used for parsing the message by received date of the message.
	 * $rdate should be in mm-dd-yyyy format.
	 * If flag is false then fuction parse all the messages with given date,
	 * otherwise parse only unread messages with the given date.
	 *
	 * @param Integer $rdate
	 * @param Boolean $flag 
	 */
	public function pasrseMessagesByRecDate($rdate, $flag = false) {
		$this->parseMessageByFilter($rdate, self::RECEIVED_DATE, $flag);
	}

	/**
	 * Used for parsing the message by filter given by user
	 *
	 * @param Integer $userInput
	 * @param Integer $filterType
	 * @param Boolean $flag 
	 */
	public function parseMessageByFilter($userInput, $filterType, $flag) {

		$conn = $this->setConnection($this->mailServerName, $this->userName, $this->password);
		$countMsg = imap_num_msg($conn);

		// Iteration on mailbox messages
		for ($i = 1; $i <= $countMsg; $i++) {
			$this->headers = @imap_headerinfo($conn, $i);
			
			// Preparing filter by given filter type
			
			if($filterType == 0) {
				$filter = $this->headers && ($this->headers->Msgno == trim($userInput));
			}
			else if($filterType == 1) {
				$filter = $this->headers && ($this->getRecDate($this->headers->date) == trim($userInput));
			}
			else if($filterType == 2) {
				$filter = $this->headers && ($this->headers->Subject == trim($userInput));
			}
			else if($filterType == 3) {
				$filter = $this->headers && ($this->containsFromAddress($this->headers->fromaddress, trim($userInput)));
			}
			else if($filterType == 4) {
				$filter = $this->headers && true;
			}
			// Process only filtered messages by received date
			if ($filter) {
				if($flag) {
					if($this->headers->Unseen == 'U')
						$this->parseMessage($conn, $i);
				}
				else {
					$this->parseMessage($conn, $i);
				}
			}
		}
		imap_close($conn);
	}

	/**
	 * Used for preparing resultant array.
	 *
	 */
	private function makeResult() {
		$temp = array();
		$temp['attachments']  = $this->attachments;
		$temp['htmlBody']	  = $this->htmlBody;
		$temp['plainBody']    = $this->plainBody;
		$temp['headers']	  = $this->headers;

		$this->result[] = $temp;

		// Unsetting the variables for next message
		unset($this->attachments);
		unset($this->htmlBody);
		unset($this->plainBody);
		unset($this->headers);
	}

	/**
	 * This method returns the resultant array.
	 *
	 * @retuen Array result
	 */
	public function getResult() {
		return $this->result;
	}
}

?>
Return current item: Mail Parser