#native_company# #native_desc#
#native_cta#

Send email messages through SMTP servers

By Kevin McDermott
on May 10, 2001

Version: 0.3

Type: Class

Category: Networking

License: GNU General Public License

Description: This class will allow you to connect to remote SMTP servers and send email. It currently allows for one MIME encoded attachment.

# A SMTP class allowing you to send email messages from SMTP servers with
# only one attachment (currently).

# This was written by someone else, but modified and posted by me,
# Kevin McDermott [email protected]

class Smtp {

	var $Subject;         	// string the email's subject 
	var $FromName;                // string sender's name (opt) 
	var $Body;                    // string body copy 
	var $Cc;
	var $Attachment;		// attachment (optional)
	var $AttachmentType;
	var $Socket;
	var $Line;
	var $Status;

	function Smtp($Server = "localhost",$Port = SmtpPort)
	{    
		if (!$this->Open($Server, $Port)) {
			$this->Status["Connection"] ="Could not connect to SMTP Server '$Server'";
			return;
		}
	}

	# This is self explanitory except for,
	#	$domain is the domain name of the machine connecting to the SMTP server
	#	this must be what a reverse name lookup will show (your IP will resolve
	#	to) or else, when we say "HELO" it won't like us, and print a warning
	#	message in the header 
	function SmtpMail($FromEmail, $ToEmail, $Cc, $Bcc, $Subject, $Body, $domain, $Attachment=null, $AttachmentType="text/plain", $AttachmentName=null)
	{
		$this->Subject   = $Subject;
		$this->Body      = $Body;
		$this->Cc      = $Cc;
		$this->Bcc      = $Bcc;
		$this->ToEmail = $ToEmail;
		$this->FromEmail = $FromEmail;

		$this->Attachment = $Attachment;
		$this->AttachmentType = $AttachmentType;
		$this->AttachmentName = $AttachmentName;

		if ($this->Helo($domain) == false){
			return false;
		}
		if ($this->MailFrom($FromEmail) == false){
			return false;
		}
		foreach (split(",", $ToEmail) as $address) {
			if ($this->RcptTo($address) == false){
				return false;
			}
		}

		if ($Cc) foreach (split(",", $Cc) as $address) {
			if ($this->RcptTo($address) == false){
				return false;
			}
		}

		if ($Bcc) foreach (split(",", $Bcc) as $address) {
			if ($this->RcptTo($address) == false){
				return false;
			}
		}

		if ($this->Body() == false){
			return false;
		}
		if ($this->Quit() == false){
			return false;
		}
		return true;
	}

	function Open($Server, $Port)
	{
	 $this->Socket = fsockopen($Server, $Port);
	 if ($this->Socket <= 0) { return false; }
	 $this->Line = fgets($this->Socket, 1024);

	 $this->Status["LASTRESULT"] = substr($this->Line, 0, 1);
	 $this->Status["LASTRESULTTXT"] = substr($this->Line, 0, 1024);

	 if ($this->Status["LASTRESULT"] <> "2") return false;

	 return true;
	}

 
	function Helo($domain)
	{
		if (fputs($this->Socket, "helo $domainrn") < 0 ){
			return false;
		}
		$this->Line = fgets($this->Socket, 1024);

		$this->Status["LASTRESULT"] = substr($this->Line, 0, 1);
		$this->Status["LASTRESULTTXT"] = substr($this->Line, 0, 1024);
		if ($this->Status["LASTRESULT"] <> "2") return false;

		return true;  
	}
 
	function Ehlo()
	{

		/* Well, let's use "helo" for now.. Until we need the
		extra func's   [Unk]
		*/
		if(fputs($this->Socket, "helo localhostrn")<0){
			return false;
		}
		$this->Line = fgets($this->Socket, 1024);

		$this->Status["LASTRESULT"] = substr($this->Line, 0, 1);
		$this->Status["LASTRESULTTXT"] = substr($this->Line, 0, 1024);

		if ($this->Status["LASTRESULT"] <> "2") return false;

		return true;
	}

	function MailFrom($FromEmail)
	{

		if (fputs($this->Socket, "MAIL FROM: <$FromEmail>rn")<0){
			return false;
		}
		$this->Line = fgets($this->Socket, 1024);

		$this->Status["LASTRESULT"] = substr($this->Line, 0, 1);
		$this->Status["LASTRESULTTXT"] = substr($this->Line, 0, 1024);

		if ($this->Status["LASTRESULT"] <> "2") return false;

		return true;
	}
 
	function RcptTo($ToEmail)
	{

		if(fputs($this->Socket, "RCPT TO: <$ToEmail>rn")<0){
			return false;
		}
		$this->Line = fgets($this->Socket, 1024);

		$this->Status["LASTRESULT"] = substr($this->Line, 0, 1);
		$this->Status["LASTRESULTTXT"] = substr($this->Line, 0, 1024);

		if ($this->Status["LASTRESULT"] <> "2") return false;
			return true;
	}

	function Body()
	{
		$FileSize = 0;
		$Attachment = null;
		$fp = null;

		$buffer = "From: $this->FromEmailrnTo:$this->ToEmailrn".
		(($this->Cc)?("Cc:$this->Ccrn"):(""))."Subject:$this->Subjectrn";
	
		if(fputs($this->Socket, "DATArn")<0){
			return false;
		}
		$this->Line = fgets($this->Socket, 1024);

		$this->Status["LASTRESULT"] = substr($this->Line, 0, 1);
		$this->Status["LASTRESULTTXT"] = substr($this->Line, 0, 1024);

		if ($this->Status["LASTRESULT"] <> "3") return false;
		
		if(fputs($this->Socket, $buffer)<0){
			return false;
		}


		# php puts 'none' as the temp filename when nothing sent
		if ( !strcmp($this->Attachment, "none") ){

			if(fputs($this->Socket, "MIME-Version: 1.0rnContent-Type: text/plain; charset=ISO-8859-1rnContent-Transfer-Encoding: 7bitrnrn")<0){
				return false;
			}
			if(fputs($this->Socket, wordwrap($this->Body)."rnrn")<0){
				return false;
			}
	
			if(fputs($this->Socket, ".rn")<0){
				return false;
			}

			$this->Line = fgets($this->Socket, 1024);
			if (substr($this->Line, 0, 1) <> "2"){
				return false; 
			}else{
				return true;
			}
		}else{
			if(fputs($this->Socket,"MIME-Version: 1.0rnContent-Type: multipart/mixed; boundary="----=_NextPart_000_01BCFA61.A3697360"rn".
				"Content-Transfer-Encoding: 7bitrnrn".
				"This is a multi-part message in MIME format.rn".
				"rn------=_NextPart_000_01BCFA61.A3697360rn".
				"Content-Type: text/plain; charset=ISO-8859-1rn".
				"Content-Transfer-Encoding: 7bitrn".
				"rn")<0){
				return false;
			}
	

			/* output the body file */
			if(fputs($this->Socket, wordwrap($this->Body)."rnrn")<0){
				return false;
			}

			if ( fputs($this->Socket,"rn------=_NextPart_000_01BCFA61.A3697360rn")<0){
				return false;
			}
			$FileSize = filesize($this->Attachment);
			if ($FileSize == false){
				return false;
			}
			if (($fp = fopen($this->Attachment,"r"))== false) {
				return false;
			}else{
				$Attachment = fread($fp,$FileSize);	
			}


			if( fputs($this->Socket,
				"Content-Type: ".trim($this->AttachmentType).";rn name="".trim($this->AttachmentName).""rn".
				"Content-Transfer-Encoding: base64rn".
				"Content-Description: ".trim($this->AttachmentName)."rn".
				"Content-Disposition: attachment; rntfilename="".trim($this->AttachmentName).""rn".
				"rn")<0){
				return false;
			}
	
			/* output the attachment file */
			if( fputs($this->Socket, chunk_split(base64_encode($Attachment)))<0){
				return false;
			}
			if ( fputs($this->Socket,"rnrn------=_NextPart_000_01BCFA61.A3697360--rn")<0){
				return false;
			}

			if( fputs($this->Socket,".rn")<0){
				return false;
			}

			$this->Line = fgets($this->Socket, 1024);
			if (substr($this->Line, 0, 1) <> "2")
				return false; 

			return true;

		}
	}
 
	function Quit()
	{

		if(fputs($this->Socket, "QUITrn")<0){
			return false;
		}
		$this->Line = fgets($this->Socket, 1024);

		$this->Status["LASTRESULT"] = substr($this->Line, 0, 1);
		$this->Status["LASTRESULTTXT"] = substr($this->Line, 0, 1024);

		if ($this->Status["LASTRESULT"] <> "2") return 0;

		return 1;
	} 
	function Close()
	{
		fclose($this->Socket);
	}
}