Location: PHPKode > scripts > SMTP4PHP > SMTP4PHP-2011/email.php
<?php
/**
*
* SMTP4PHP :  SMTP for PHP
* This project is a collection of PHP 5.x classes, written in OOP style, 
* providing exception support, dedicated for sending mails fast and easily,
* with or without embedded images and/or attachments.
* 
* Copyright (c) 2011, Raul IONESCU <hide@address.com>, 
* Bucharest, ROMANIA
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @package      SMTP4PHP
* @copyright    Copyright (c) 2011, Raul IONESCU.
* @author       Raul IONESCU <hide@address.com>
* @license      http://www.opensource.org/licenses/mit-license.php The MIT License
* @access       public
*
* PHP versions 5.3 or greater
*/
/*///////////////////////////////////////////////////////////////////////////////////////*/
function exception_error_handler($errno, $errstr, $errfile, $errline ) 
{ throw new ErrorException($errstr, $errno, 0, $errfile, $errline); }
/*///////////////////////////////////////////////////////////////////////////////////////*/
set_error_handler("exception_error_handler");
/*///////////////////////////////////////////////////////////////////////////////////////*/
/*///////////////////////////////////////////////////////////////////////////////////////*/
/*///////////////////////////////////////////////////////////////////////////////////////*/
class eMailUser implements Iterator
{
const VERSION = eMail::VERSION;
protected $user;



public function __construct($name = NULL, $address = NULL) { $this->user = array('name' => $name, 'address' => $address); }
public function __get($property) 
{
switch($property = strtoupper($property))
	{
	 case 'NAME':			         
	 case 'ADDRESS':		        
		return $this->user[$property];
	 default:
		return NULL;
	}
}
public function __toString()            { return (($this->name)?('"'.$this->name.'" '):('')).(($this->address)?('<'.$this->address.'>'):('')); }
public function __invoke($property)     { return $this->$property; }
public function current()               { return current($this->user); }
public function key()                   { return key($this->user); }
public function next()                  { return next($this->user); }
public function rewind()                { return reset($this->user); }
public function valid()                 { return isset($this->user[$this->key()]); }
}
/*///////////////////////////////////////////////////////////////////////////////////////*/
/*///////////////////////////////////////////////////////////////////////////////////////*/
/*///////////////////////////////////////////////////////////////////////////////////////*/
class eMail
{
const VERSION = 2011;
const RELEASE = 1;
const PRIORITY_LOW = 5;
const PRIORITY_NORMAL = 3;
const PRIORITY_HIGH = 1;
const CONTENT_TRANSFER_ENCODING_TEXT = 1;
const CONTENT_TRANSFER_ENCODING_BASE64 = 2;
protected $mixedBoundary;
protected $altBoundary;
protected $returnPath;
protected $from;
protected $replyTo;
protected $to;
protected $cc;
protected $bcc;
protected $priority;
protected $contentTransferEncoding;
protected $subject;
protected $htmlMessage;
protected $textMessage;
protected $images;
protected $attachments;



protected function _generateRandomString()      { return md5(uniqid(rand(),true)); }
protected function _generateBoundary()          { return $this->_generateRandomString().(($this->from) && (preg_match('/(@.+)$/i',$this->from->address, $m) && is_array($m) && ($m = $m[0]))?($m):($this->_generateRandomString())); }
public function __construct(eMailUser $from = NULL, $to = NULL, $subject = NULL, $htmlMessage = NULL, $textMessage = NULL)
{
$this->From = $from;
$this->To = $to;
$this->priority = self::PRIORITY_NORMAL;
$this->contentTransferEncoding = self::CONTENT_TRANSFER_ENCODING_BASE64;
$this->Subject = $subject;
$this->HTMLMessage = $htmlMessage;
$this->TXTMessage = $textMessage;
$this->images = array();
$this->attachments = array();
$this->mixedBoundary = '--=_'.$this->_generateBoundary();
$this->altBoundary  = '--=_'.$this->_generateBoundary();
}
/*///////////////////////////////////////////////////////////////////////////////////////*/
public function __get($property)
{
switch(strtoupper($property))
	{
		case 'PRIORITY':
                        return $this->priority;
                case 'CONTENTTRANSFERENCODING': 
                        return $this->contentTransferEncoding;
		case 'RETURNPATH':
                        return $this->returnPath;
		case 'FROM':
                        return $this->from;
		case 'REPLYTO':
                        return $this->replyTo;
		case 'TO':
                        return $this->to;
		case 'CC':
                        return $this->cc;
		case 'BCC':
                        return $this->bcc;
		case 'SUBJECT':
                        return $this->subject;
		case 'HTMLMESSAGE':
                        return $this->htmlMessage;
                case 'TEXTMESSAGE':
                case 'TXTMESSAGE':
                        return $this->textMessage;                
                case 'RAWMESSAGE':
                        return $this->__toString();
		default:
                        return NULL;
	}

}
/*///////////////////////////////////////////////////////////////////////////////////////*/
protected function _set(&$property,&$value)
{
try
	{
	 if($value)
         	{ 
                 if($value instanceof eMailUser) { return $property = array($value); }
                 else if(is_array($value))
				{
				 $values = array();
				 array_walk_recursive($value, create_function('$value, $key, $obj', 'array_push($obj, $value);'), &$values);  
                                 foreach($values as $k=>$v) { if(!$v instanceof eMailUser) { unset($value[$k]); } }
                                 return $property = $values; 
                                }
         	}
	 else { if(empty($property)) { return $property = array(); } }
	}
catch(Exception $e) { return NULL; }
}
/*///////////////////////////////////////////////////////////////////////////////////////*/
public function __set($property, $value)
{
switch(strtoupper($property))
	{
		case 'PRIORITY':
                        return $this->priority = ((($value == self::PRIORITY_HIGH) || ($value == self::PRIORITY_LOW))?($value):(self::PRIORITY_NORMAL));
                case 'CONTENTTRANSFERENCODING':
                        return $this->contentTransferEncoding = (($value == self::CONTENT_TRANSFER_ENCODING_BASE64)?(self::CONTENT_TRANSFER_ENCODING_BASE64):(self::CONTENT_TRANSFER_ENCODING_TEXT));
		case 'RETURNPATH':
                        return ($value && ($value instanceof eMailUser))?($this->returnPath = $value):(NULL);
		case 'FROM':
                        return ($value && ($value instanceof eMailUser))?($this->from = $value):(NULL);
		case 'REPLYTO':
                        return ($value && ($value instanceof eMailUser))?($this->replyTo = $value):(NULL);
		case 'TO':
                        return $this->_set($this->to, $value);
		case 'CC':
                        return $this->_set($this->cc, $value);
		case 'BCC':
                        return $this->_set($this->bcc, $value);
		case 'SUBJECT':
                        return $this->subject = trim(strip_tags($value));
		case 'HTMLMESSAGE':
                        return $this->htmlMessage = trim($value);
                case 'TEXTMESSAGE':
                case 'TXTMESSAGE':
                        return $this->textMessage = preg_replace('/[\f\t ]{2,}/mS', ' ', trim(strip_tags($value)));
		default:
                        return NULL;
	}
}
/*///////////////////////////////////////////////////////////////////////////////////////*/
public function addImage($file)
{
try
        {
	 $info = getimagesize($file);         
	 $cid = $this->_generateRandomString();

         $msg  = '--'.$this->mixedBoundary.PHP_EOL;
         $msg .= 'Content-Location: "'.basename($file).'"'.PHP_EOL;
         $msg .= 'Content-Type: '.image_type_to_mime_type($info[2]).PHP_EOL; 
         $msg .= 'Content-Transfer-Encoding: base64'.PHP_EOL;
         $msg .= 'Content-ID: <'.$cid.'>'.PHP_EOL;
         $msg .= 'Content-Disposition: inline; filename="'.basename($file).'"'.PHP_EOL.PHP_EOL;

         $msg .= chunk_split(base64_encode(file_get_contents($file))).PHP_EOL;
         $this->images[$cid] = $msg;
         return 'cid:'.$cid;
        }
catch(Exception $e) { return NULL; }
}
/*///////////////////////////////////////////////////////////////////////////////////////*/
public function addAttachment($file)
{
try
        {
         $cid = $this->_generateRandomString();
         
         $msg  = '--'.$this->mixedBoundary.PHP_EOL;
         $msg .= 'Content-Type: binary/octet-stream'.PHP_EOL; 
         $msg .= 'Content-Transfer-Encoding: base64'.PHP_EOL;
         $msg .= 'Content-ID: <'.$cid.'>'.PHP_EOL;
         $msg .= 'Content-Disposition: attachment; filename="'.basename($file).'"'.PHP_EOL.PHP_EOL;
         
         $msg .= chunk_split(base64_encode(file_get_contents($file))).PHP_EOL;
         $this->attachments[$cid] = $msg;
         return $cid;
        }
catch(Exception $e) { return NULL; }
}
/*///////////////////////////////////////////////////////////////////////////////////////*/
public function __toString() 
{
try
        {
         $msg = '';
	 if($this->returnPath) { $msg .='Return-Path: <'.$this->returnPath->address.'>'.PHP_EOL; }
         if($this->replyTo)    { $msg .= 'Reply-To: '.$this->replyTo.PHP_EOL; }
         $msg .= 'From: '.$this->from.PHP_EOL; 
	 if(($this->to)  && is_array($this->to) && count($this->to))    { $msg .= 'To: '.implode(', ',$this->to).PHP_EOL; }
	 if(($this->cc)  && is_array($this->cc) && count($this->cc))    { $msg .= 'Cc: '.implode(', ',$this->cc).PHP_EOL; }
         $msg .= 'Subject: '.$this->subject.PHP_EOL;
         $msg .= 'X-Priority: '.$this->priority.PHP_EOL;				
         $msg .= 'X-MSMail-Priority: '.(($this->priority == self::PRIORITY_HIGH)?('High'):(($this->priority == self::PRIORITY_LOW)?('Low'):('Normal'))).PHP_EOL;
         $msg .= 'X-Mailer: PHP/'.phpversion().PHP_EOL;
         $msg .= 'MIME-Version: 1.0'.PHP_EOL;
         $msg .= 'Content-Type: multipart/mixed; boundary="'.$this->mixedBoundary.'"'.PHP_EOL; 
         $msg .= 'Date: '.date('r').PHP_EOL;
         //$msg .= 'Disposition-Notification-To: <'.$this->from->address.'>'.PHP_EOL;
	 $msg .= PHP_EOL;
         $msg .= '--'.$this->mixedBoundary.PHP_EOL;
         $msg .= 'Content-Type: multipart/alternative; boundary="'.$this->altBoundary.'"'.PHP_EOL.PHP_EOL;       
         $msg .= '--'.$this->altBoundary.PHP_EOL;
         /*/////////////////////////////////////////*/
         /* text message */
         /*/////////////////////////////////////////*/
         $msg .= 'Content-Type: text/plain; charset="iso-8859-1"'.PHP_EOL;
         if($this->contentTransferEncoding == self::CONTENT_TRANSFER_ENCODING_BASE64)
                {
                 $msg .= 'Content-Transfer-Encoding: base64'.PHP_EOL.PHP_EOL;
                 $msg .= chunk_split(base64_encode($this->textMessage));
                }
         else   {
                 $this->textMessage = preg_replace('/^\.$/imsSU','..',$this->textMessage);
                 $msg .= 'Content-Transfer-Encoding: 8bit'.PHP_EOL.PHP_EOL;
                 $msg .= $this->textMessage;
                }         
         $msg .= PHP_EOL.PHP_EOL;
         $msg .= '--'.$this->altBoundary.PHP_EOL;
         /*/////////////////////////////////////////*/         
         /* html message */
         /*/////////////////////////////////////////*/
         if(empty($this->htmlMessage))
                { $this->htmlMessage = nl2br($this->TXTMessage); }
         $msg .= 'Content-type: text/html; charset="iso-8859-1"'.PHP_EOL; 
         if($this->contentTransferEncoding == self::CONTENT_TRANSFER_ENCODING_BASE64)
                { $msg .= 'Content-Transfer-Encoding: base64'; }
         else   { $msg .= 'Content-Transfer-Encoding: 8bit'; }       
         $msg .= PHP_EOL.PHP_EOL;
         if(preg_match('/<\/{0,1}(html|head|body.*)>/imsSU',$this->htmlMessage))
                { 
                 $htmlMsg = $this->htmlMessage; 
                 if($this->contentTransferEncoding == self::CONTENT_TRANSFER_ENCODING_BASE64)
                        { $htmlMsg = chunk_split(base64_encode($htmlMsg));  }
                }
         else
                {
                 $htmlMsg  = '<html>'.PHP_EOL;
                 $htmlMsg .= '<head>'.PHP_EOL;
                 $htmlMsg .= '<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">'.PHP_EOL;
                 $htmlMsg .= '</head>'.PHP_EOL;
                 $htmlMsg .= '<body style="margin-top:0px; margin-bottom:0px; margin-right:0px; margin-left:0px;">'.PHP_EOL;
                 $htmlMsg .= $this->htmlMessage.PHP_EOL;
                 $htmlMsg .= '<br><br></body></html>'; 
                 if($this->contentTransferEncoding == self::CONTENT_TRANSFER_ENCODING_BASE64)
                        { $htmlMsg = chunk_split(base64_encode($htmlMsg));  }
                } 
         $msg .= $htmlMsg; unset($htmlMsg);         
         $msg .= PHP_EOL.PHP_EOL;
         $msg .= '--'.$this->altBoundary."--".PHP_EOL.PHP_EOL;
         /*/////////////////////////////////////////*/
         /* add images */
         /*/////////////////////////////////////////*/
         $msg .= implode('',$this->images); 
         /*/////////////////////////////////////////*/
         /* add attachments */
         /*/////////////////////////////////////////*/
         $msg .= implode('',$this->attachments); 
         $msg .= '--'.$this->mixedBoundary.'--'.PHP_EOL;
	 $msg .= '.'.PHP_EOL; 
         
         return $msg;
        } 
catch(Exception $e) { return NULL; }
}
}
/*///////////////////////////////////////////////////////////////////////////////////////*/
/*///////////////////////////////////////////////////////////////////////////////////////*/
/*///////////////////////////////////////////////////////////////////////////////////////*/
class SMTP
{
const VERSION = eMail::VERSION;

protected $SMTPlog;
protected $SMTPserver;
protected $SMTPport;
protected $SMTPconnectionTimeout;
protected $SMTPuser;
protected $SMTPpassword;



/*///////////////////////////////////////////////////////////////////////////////////////*/
public function __construct($SMTPserver = NULL, $SMTPport = NULL, $SMTPuser = NULL, $SMTPpassword = NULL)
{
$this->SMTPServer = $SMTPserver;
$this->SMTPPort = (($SMTPport)?($SMTPport):(25));
$this->SMTPUser = $SMTPuser;
$this->SMTPPassword = $SMTPpassword;
$this->SMTPConnectionTimeout = 30;
}
/*///////////////////////////////////////////////////////////////////////////////////////*/
public function __get($property)
{
switch(strtoupper($property))
	{
		case 'SERVER':
                case 'SMTPSERVER':
                        return $this->SMTPserver;
                case 'PORT':
                case 'SMTPPORT':
                        return $this->SMTPport;
                case 'CONNECTIONTIMEOUT':
                case 'SMTPCONNECTIONTIMEOUT':
                        return $this->SMTPconnectionTimeout;
                case 'USER':
                case 'SMTPUSER':
                        return $this->SMTPuser;
                case 'PASSWORD':
                case 'SMTPPASSWORD':
                        return $this->SMTPpassword;
		case 'LOG':
		case 'SMTPLOG':
                        return $this->SMTPlog;
		default:
                        return NULL;
	}
}
/*///////////////////////////////////////////////////////////////////////////////////////*/
public function __set($property, $value)
{
switch(strtoupper($property))
	{
		case 'SERVER':
                case 'SMTPSERVER':
                        return $this->SMTPserver = $value;
                case 'PORT':
                case 'SMTPPORT':
                        $value = abs(intval($value));
                        return $this->SMTPport = ($value)?($value):(25);
                case 'CONNECTIONTIMEOUT':                                
                case 'SMTPCONNECTIONTIMEOUT':
                        $value = abs(intval($value));
                        return $this->SMTPconnectionTimeout = ($value)?($value):(30);
                case 'USER':
                case 'SMTPUSER':
                        return $this->SMTPuser = $value;
                case 'PASSWORD':
                case 'SMTPPASSWORD':
                        return $this->SMTPpassword = $value;
		default:
                        return NULL;
	}
}
/*///////////////////////////////////////////////////////////////////////////////////////*/
public function send()
{ 
try
        {
         $functionArguments = func_get_args(); $emails = array();
	 array_walk_recursive($functionArguments, create_function('$value, $key, $obj', 'array_push($obj, $value);'), &$emails);  
	 unset($functionArguments);

         $this->SMTPlog = array();
         $smtpConnect = fsockopen($this->SMTPserver, $this->SMTPport, $errno, $errstr, $this->SMTPconnectionTimeout); 
         $this->SMTPlog[] = $smtpResponse = fgets($smtpConnect);
         if(empty($smtpConnect)) { throw new Exception('SMTP connection error!'.(smtpResponse)?(' ('.smtpResponse.')'):('')); }
         
         if($this->SMTPUser)
                {
                  $this->SMTPlog[] = $smtpCommand = 'EHLO '.$this->SMTPserver.PHP_EOL;
		  fputs($smtpConnect, $smtpCommand); 
                  $this->SMTPlog[] = $smtpResponse = fgets($smtpConnect);
                  if(!preg_match('/^250/S', $smtpResponse)) { throw new Exception('Unexpected SMTP error! (SMTP command: "'.$smtpCommand.'" SMTP response: "'.$smtpResponse.'")'); }
		  $this->SMTPlog[] = $smtpCommand = 'AUTH LOGIN'.PHP_EOL;
                  fputs($smtpConnect, $smtpCommand);
                  $this->SMTPlog[] = $smtpResponse = fgets($smtpConnect);
                  if(!preg_match('/^334/S', $smtpResponse)) { throw new Exception('Unexpected SMTP error! (SMTP command: "'.$smtpCommand.'" SMTP response: "'.$smtpResponse.'")'); }
		  $this->SMTPlog[] = $smtpCommand = base64_encode($this->SMTPuser).PHP_EOL;
		  fputs($smtpConnect, $smtpCommand);
                  $this->SMTPlog[] = $smtpResponse = fgets($smtpConnect);
                  if(!preg_match('/^334/S', $smtpResponse)) { throw new Exception('Unexpected SMTP error! (SMTP user: "'.$smtpCommand.'" SMTP response: "'.$smtpResponse.'")'); }
                  $this->SMTPlog[] = $smtpCommand = base64_encode($this->SMTPpassword).PHP_EOL;
		  fputs($smtpConnect, $smtpCommand);
                  $this->SMTPlog[] = $smtpResponse = fgets($smtpConnect);
                  if(!preg_match('/^235/S', $smtpResponse)) { throw new Exception('Unexpected SMTP error! (SMTP password: "'.$smtpCommand.'" SMTP response: "'.$smtpResponse.'")'); }
                }
         else   { 
		  $this->SMTPlog[] = $smtpCommand = 'HELO '.$this->SMTPserver.PHP_EOL;
                  fputs($smtpConnect, $smtpCommand);
                  $this->SMTPlog[] = $smtpResponse = fgets($smtpConnect);
                  if(!preg_match('/^250/S', $smtpResponse)) { throw new Exception('Unexpected SMTP error! (SMTP command: "'.$smtpCommand.'" SMTP response: "'.$smtpResponse.'")'); }
                }

         foreach($emails as $e)
		{
                 if($e instanceof eMail) 
			{ 
			 $this->SMTPlog[] = $smtpCommand = 'MAIL FROM: '.$e->from->address.PHP_EOL;
                         fputs($smtpConnect, $smtpCommand);
                         $this->SMTPlog[] = $smtpResponse = fgets($smtpConnect);
			 if(!preg_match('/^250/S', $smtpResponse)) 
				{ 
			 	 $this->SMTPlog[] = $smtpCommand = 'RSET'.PHP_EOL;
                         	 fputs($smtpConnect, $smtpCommand);
			 	 $this->SMTPlog[] = $smtpResponse = fgets($smtpConnect);
				 continue; 
				}
			 if(is_array($e->to))  
                                { 
                                 foreach($e->to as $rcpt)  
                                        { 
					 $this->SMTPlog[] = $smtpCommand = 'RCPT TO: '.$rcpt->address.PHP_EOL;
                                         fputs($smtpConnect, $smtpCommand);
                                         $this->SMTPlog[] = $smtpResponse = fgets($smtpConnect);
                                         if(!preg_match('/^250/S', $smtpResponse))
						{ 
			 	 		 $this->SMTPlog[] = $smtpCommand = 'RSET'.PHP_EOL;
                         	 		 fputs($smtpConnect, $smtpCommand);
			 	 		 $this->SMTPlog[] = $smtpResponse = fgets($smtpConnect);
				 		 continue; 
						}
                                        } 
                                }
			 if(is_array($e->cc))  
                                { 
                                 foreach($e->cc as $rcpt)  
                                        { 
					 $this->SMTPlog[] = $smtpCommand = 'RCPT TO: '.$rcpt->address.PHP_EOL;
                                         fputs($smtpConnect, $smtpCommand);
                                         $this->SMTPlog[] = $smtpResponse = fgets($smtpConnect);
                                         if(!preg_match('/^250/S', $smtpResponse))
						{ 
			 	 		 $this->SMTPlog[] = $smtpCommand = 'RSET'.PHP_EOL;
                         	 		 fputs($smtpConnect, $smtpCommand);
			 	 		 $this->SMTPlog[] = $smtpResponse = fgets($smtpConnect);
				 		 continue; 
						}
                                        } 
                                }                                
			 if(is_array($e->bcc))  
                                { 
                                 foreach($e->bcc as $rcpt)  
                                        { 
					 $this->SMTPlog[] = $smtpCommand = 'RCPT TO: '.$rcpt->address.PHP_EOL;
                                         fputs($smtpConnect, $smtpCommand);
                                         $this->SMTPlog[] = $smtpResponse = fgets($smtpConnect);
                                         if(!preg_match('/^250/S', $smtpResponse))
						{ 
			 	 		 $this->SMTPlog[] = $smtpCommand = 'RSET'.PHP_EOL;
                         	 		 fputs($smtpConnect, $smtpCommand);
			 	 		 $this->SMTPlog[] = $smtpResponse = fgets($smtpConnect);
				 		 continue; 
						}
                                        } 
                                }
			 $this->SMTPlog[] = $smtpCommand = 'DATA'.PHP_EOL;
                         fputs($smtpConnect, $smtpCommand);
                         $this->SMTPlog[] = $smtpResponse = fgets($smtpConnect);
                         if(!preg_match('/^354/', $smtpResponse))
				{ 
			 	 $this->SMTPlog[] = $smtpCommand = 'RSET'.PHP_EOL;
                         	 fputs($smtpConnect, $smtpCommand);
			 	 $this->SMTPlog[] = $smtpResponse = fgets($smtpConnect);
				 continue; 
				}

			 $this->SMTPlog[] = $smtpCommand = $e->RawMessage;  
                         fputs($smtpConnect, $smtpCommand);
                         $this->SMTPlog[] = $smtpResponse = fgets($smtpConnect);
                         /*Ex: 250 OK id=1QN7Vf-0000vB-8r*/
                         if(!preg_match('/^250/', $smtpResponse)) 
				{ 
			 	 $this->SMTPlog[] = $smtpCommand = 'RSET'.PHP_EOL;
                         	 fputs($smtpConnect, $smtpCommand);
			 	 $this->SMTPlog[] = $smtpResponse = fgets($smtpConnect);
				 continue; 
				}
			 $this->SMTPlog[] = $smtpCommand = 'NOOP'.PHP_EOL;
                         fputs($smtpConnect, $smtpCommand);
			 $this->SMTPlog[] = $smtpResponse = fgets($smtpConnect);
			} 
         	}
	 $this->SMTPlog[] = $smtpCommand = 'QUIT'.PHP_EOL;
         fputs($smtpConnect, $smtpCommand);
         $this->SMTPlog[] = $smtpResponse = fgets($smtpConnect);
         fclose($smtpConnect);
        }
catch(Exception $e)
        {
         if(!empty($smtpConnect)) { try { fclose($smtpConnect); } catch(Exception $ee) { } }
	 throw $e;
        }
}
}
/*///////////////////////////////////////////////////////////////////////////////////////*/
/*///////////////////////////////////////////////////////////////////////////////////////*/
/*///////////////////////////////////////////////////////////////////////////////////////*/

?>
Return current item: SMTP4PHP