Location: PHPKode > scripts > Send messages via SMTP > send-messages-via-smtp/smtp.php
<?
/*
smtp PHP Class
Copyright (C) 2006 Nic Stevens.
-----------------------------------------------------------------------------
Send a message via SMTP with optional LOGIN authorization. 

Constructor:
   new smtp(<hostname>,	// string: hostname of mail server
            <port>,	// integer: port of smtp server on host, usually 25
	    <from>,	// address message is from
	    <recip>,	// string or array: list of recipients
	    <headers>,	// headers to be sent with message. (HINT = put
	    		// subject here)
	   <auth>,	// hash of auth data ('user' => user, 
	   		// 'pass' = password)
	   <message data>// text of message to be sent.
	   
     Throws Exception on error.
*/     
define('au_st_auth',0);
define('au_st_user',1);
define('au_st_pass',2);
define('au_st_done',3);

define('sm_st_helo',0);
define('sm_st_auth',1);
define('sm_st_mfrom',2);
define('sm_st_rcpto',3);
define('sm_st_data',4);
define('sm_st_cleanup',5);

require_once('sock.php');

class smtp extends sock { 
    var $errors;
    var $headers;
    var $data;
    var $host;
    var $state;
    var $recip;
    var $from;
    var $user;
    var $pass;
    
    function __construct($server, $port = -1, $from = "", $recip = "", $headers = "", $authdata = "", $data = "") {
	$this->errors = array();
	if($port == -1)
	  $port = 25;
	$cdata = array('address' => $server,
		       'port' => $port);
	try { 
	    parent::__construct($cdata);
	} catch(Exception $e) {
	    throw($e);
	}
	$this->get_data($junkdata);
	$this->from = $from;
	$this->recip = $recip;
	$this->headers = $headers;
	$this->authdata = $authdata;
	$this->data = $data;
	
	if($this->from == "" || $this->recip == "" || $this->data == "") { 
	    ob_start();
	    print_r($this);
	    $xxx = ob_get_contents();
	    ob_end_clean();
	    throw new Exception("! NOT ENOUGH INFO TO BUILD MESSAGE: OBJ Data: $xxx\n");
	}
	$state = sm_st_helo;
	while($state <= sm_st_cleanup) {
	    $prevstate = $state;
	    $state = $this->sendMessage($state);
	    if($state === false) {
		$x = $this->errors[count($this->errors)-1];
		throw new exception($x['text'],$x['code']);
	    }
	}
    }
    function sendMessage($state) {
	switch($state) {
	 case sm_st_helo:
	    if($this->helo())
	      break;
	    return false;
	 case sm_st_auth:
	    if(is_array($this->authdata)) {
		$this->user = $this->authdata['user'];
		$this->pass = $this->authdata['pass'];
		if($this->auth())
		  break;
		return false;
	    }
	    break;
	 case sm_st_mfrom:
	    if($this->mailfrom()) 
	      break;
	    return false;
	 case sm_st_rcpto:
	    if($this->rcpto())
	      break;
	    return false;
	 case sm_st_data:
	    if($this->send_msgdata())
	      break;
	    return false;
	 case sm_st_cleanup:
	    $this->cleanup();
	    break;
	 default: 
	    $msg="fsm: Unknown state $state";
	    $this->errors[] = array('code' => -1, 'text' => $msg);
	    return false;
	}
	$state ++ ;
	return $state;
    }
    function helo() {
	if(!isset($host) || $host == "") {
	    $host = exec('hostname');
	}
	$this->send_data("HELO $host\n");
	if($this->get_data($data)) {
	    list($code,$text) = explode(' ',trim($data),2);
	    if($code > 250) {
		$this->errors[] = array('code' => $code, 'text' => $text);
		return false;
	    }
	} else {
	    $this->errors[] = array('code' => -1, 'text' => 'cannot send command');
	    return false;
	}
	return true;
    }
    function rcpto() {
	if(!is_array($this->recip)) {
	    $recip = array();
	    foreach(explode(',',$this->recip) as $r)
	      $recip[] = trim($r);
	    $this->recip = $recip;
	}
	foreach($this->recip as $r) {
	    if($this->send_data("RCPT TO: $r\n")) {
		if($this->get_data($data)) {
		    list($code,$text) = explode(' ',trim($data),2);
		    if($code != 250) {
			$this->errors[] = array('code' => $code, 'text' => $text);
			return false;
		    }
		} else {
		    $this->errors[] = array('code' => -1, 'text' => 'cannot send command');
		    return false;
		}
	    }
	}
	return true;
    }
    function mailfrom() {
	if($this->send_data("MAIL FROM: $this->from\n")) {
	    if(!$this->get_data($data)) {
		$this->errors[] = array('code' => -1, 'text' => 'cannot read command response');
		return false;
	    }
	    list($code,$text) = explode(' ',trim($data),2);
	    if($code > 250) {
		$this->errors[] = array('code' => $code, 'text' => $text);
		return false;
	    }
	} else {
	    $this->errors[] = array('code' => -1, 'text' => 'cannot send command');
	    return false;
	}
	return true;
    }
    /*
     * auth is a mini-finite-state-machine which sends the AUTH LOGIN commands
     * in succession until the appropriate state (au_st_done) is reached.
     */
    function auth() {
	$codes = array(334,334,235,0);
	$state = au_st_auth;
	while($state != au_st_done) {
	    switch($state) {
	     case au_st_auth:
		$r = $this->send_data("AUTH LOGIN\n");
		break;
	     case au_st_user:
		$r = $this->send_data(base64_encode($this->user) . "\n");
		break;
	     case au_st_pass:
		$r = $this->send_data(base64_encode($this->pass) . "\n");
		break;
	     case au_st_done:
		break;
	    }
	    if(!$r) {
		$this->errors[] = array('code' => -1, 'text' => 'cannot send command');
		return false;
	    }
	    if(!$this->get_data($data)) {
		$this->errors[] = array('code' => -1, 'text' => 'cannot read command response');
		return false;
	    }
	    list($code,$text) = explode(' ',trim($data),2);
	    if($code != $codes[$state]) {
		$this->errors[] = array('code' => $code, 'text' => $text . "(expected code: " . $codes[$state] . ")");
		return false;
	    }
	    $state ++;
	}
	return true;
    }
    function send_msgdata() {
	if(is_array($this->headers)) {
	    $headers = "";
	    foreach($this->headers as $h) 
	      $headers .= str_replace("\n.\n","\n..\n",trim($h)) . "\n"; // Transparency
	} else 
	  $headers = str_replace("\n.\n","\n..\n",trim($this->headers));

	$data = str_replace("\n.\n","\n..\n",$this->data); // Transparency
	if(!$this->send_data("DATA\n")) {
	    $this->errors[] = array('code' => -1,'text' => 'Cannot send command');
	    return false;
	}
	if(!$this->get_data($data)) {
	    $this->errors[] = array('code' => -1,'text' => 'Cannot get command response');
	    return false;
	}
	list($code,$text) = explode(' ',trim($data),2);
	if($code != 354) {
	    $this->errors[] = array('code' => $code, 'text' => $text);
	    return false;
	}
	if($this->send_data($headers . "\n\n" . $this->data . "\n.\n")) {
	    if(!$this->get_data($data)) {
		$this->errors[] = array('code' => -1,'text' => 'Cannot get command response');
		return false;
	    }
	    list($code,$text) = explode(' ',trim($data),2);
	    if($code != 250) {
		$this->errors[] = array('code' => $code, 'text' => $text);
		return false;
	    }
	    return true;
	}
	$this->errors[] = array('code' => -1,'text' => 'Cannot get command response');
	return false;
    }
    function cleanup() {
	$this->send_data("QUIT\n");
	$this->disconnect();
    }
}
?>
Return current item: Send messages via SMTP