Test_smtp.php
<?
Require ("smtp. php ");
$ Smtp = new smtp_class;
$ Smtp-> host_name = "mail.xiaocui.com ";
$ Smtp-> localhost = "localhost ";
$ From = "webmaster@xiaocui.com ";
$ To = "root@xiaocui.com ";
If ($ smtp-> SendMessage (
$ From,
Array (
$
),
Array (
"From: $ from ",
"To: $ ",
"Subject: Testing Manuel Lemos 'smtp class"
),
"Hello $ to, \ n \ nIt is just to let you know that your SMTP class is working just fine. \ n \ nBye. \ n "))
Echo "Message sent to $ to OK. \ n ";
Else
Echo "Cound not send the message to $ to. \ nError:". $ smtp-> error. "\ n"
?>
Smtp. php
<?
Class smtp_class
{
Var $ host_name = "";
Var $ host_port = 25;
Var $ localhost = "";
Var $ timeout = 0;
Var $ error = "";
Var $ debug = 1;
Var $ esmtp = 1;
Var $ esmtp_host = "";
Var $ esmtp_extensions = array ();
Var $ maximum_piped_recipients = 100;
/* Private variables-do not access */
Var $ state = "Disconnected ";
Var $ connection = 0;
Var $ pending_recipients = 0;
/* Private methods-do not call */
Function OutputDebug ($ message)
{
Echo $ message, "<br> \ n ";
}
Function GetLine ()
{
For ($ line = "";;)
{
If (feof ($ this-> connection ))
{
$ This-> error = "reached the end of stream while reading from socket ";
Return (0 );
}
If ($ data = fgets ($ this-> connection, 100) = false)
{
$ This-> error = "it was not possible to read line from socket ";
Return (0 );
}
$ Line. = $ data;
$ Length = strlen ($ line );
If ($ length> = 2
& Substr ($ line, $ length-2, 2) = "\ r \ n ")
{
$ Line = substr ($ line, 0, $ length-2 );
If ($ this-> debug)
$ This-> OutputDebug ("<$ line ");
Return ($ line );
}
}
}
Function PutLine ($ line)
{
If ($ this-> debug)
$ This-> OutputDebug ("> $ line ");
If (! Fputs ($ this-> connection, "$ line \ r \ n "))
{
$ This-> error = "it was not possible to write line to socket ";
Return (0 );
}
Return (1 );
}
Function PutData ($ data)
{
If (strlen ($ data ))
{
If ($ this-> debug)
$ This-> OutputDebug ("> $ data ");
If (! Fputs ($ this-> connection, $ data ))
{
$ This-> error = "it was not possible to write data to socket ";
Return (0 );
}
}
Return (1 );
}
Function VerifyResultLines ($ code, $ responses = "")
{
If (GetType ($ responses )! = "Array ")
$ Responses = array ();
Unset ($ match_code );
While ($ line = $ this-> GetLine ($ this-> connection )))
{
If (IsSet ($ match_code ))
{
If (strcmp (strtok ($ line, "-"), $ match_code ))
{
$ This-> error = $ line;
Return (0 );
}
}
Else
{
$ Match_code = strtok ($ line ,"-");
If (GetType ($ code) = "array ")
{
For ($ codes = 0; $ codes <count ($ code) & strcmp ($ match_code, $ code [$ codes]); $ codes ++ );
If ($ codes> = count ($ code ))
{
$ This-> error = $ line;
Return (0 );
}
}
Else
{
If (strcmp ($ match_code, $ code ))
{
$ This-> error = $ line;
Return (0 );
}
}
}
$ Responses [] = strtok ("");
If (! Strcmp ($ match_code, strtok ($ line ,"")))
Return (1 );
}
Return (-1 );
}
Function FlushRecipients ()
{
If ($ this-> pending_sender)
{
If ($ this-> VerifyResultLines ("250") <= 0)
Return (0 );
$ This-> pending_sender = 0;
}
For (; $ this-> pending_recipients --)
{
If ($ this-> VerifyResultLines (array ("250", "251") <= 0)
Return (0 );
}
Return (1 );
}
/* Public methods */
Function Connect ()
{
$ This-> error = $ error = "";
$ This-> esmtp_host = "";
$ This-> esmtp_extensions = array ();
If (! ($ This-> connection = ($ this-> timeout? Fsockopen ($ this-> host_name, $ this-> host_port, & $ errno, & $ error, $ this-> timeout): fsockopen ($ this-> host_name, $ this-> host_port ))))
{
Switch ($ error)
{
Case-3:
$ This-> error = "-3 socket cocould not be created ";
Return (0 );
Case-4:
$ This-> error = "-4 dns lookup on hostname \" ". $ host_name." \ "failed ";
Return (0 );
Case-5:
$ This-> error = "-5 connection refused or timed out ";
Return (0 );
Case-6:
$ This-> error = "-6 fdopen () call failed ";
Return (0 );
Case-7:
$ This-> error = "-7 setvbuf () call failed ";
Return (0 );
Default:
$ This-> error = $ error. "cocould not connect to the host \" ". $ this-> host_name ."\"";
Return (0 );
}
}
Else
{
If (! Strcmp ($ localhost = $ this-> localhost ,"")
&&! Strcmp ($ localhost = getenv ("SERVER_NAME "),"")
&&! Strcmp ($ localhost = getenv ("HOST "),""))
$ Localhost = "localhost ";
$ Success = 0;
If ($ this-> VerifyResultLines ("220")> 0)
{
If ($ this-> esmtp)
{
$ Responses = array ();
If ($ this-> PutLine ("EHLO $ localhost ")
& $ This-> VerifyResultLines ("250", & $ responses)> 0)
{
$ This-> esmtp_host = strtok ($ responses [0], "");
For ($ response = 1; $ response <count ($ responses); $ response ++)
{
$ Extension = strtoupper (strtok ($ responses [$ response], "");
$ This-> esmtp_extensions [$ extension] = strtok ("");
}
$ Success = 1;
}
}
If (! $ Success
& $ This-> PutLine ("HELO $ localhost ")
& Amp; $ this-& gt; VerifyResultLines ("250") & gt; 0)
$ Success = 1;
}
If ($ success)
{
$ This-> state = "Connected ";
Return (1 );
}
Else
{
Fclose ($ this-> connection );
$ This-> connection = 0;
$ This-> state = "Disconnected ";
Return (0 );
}
}
}
Function MailFrom ($ sender)
{
If (strcmp ($ this-> state, "Connected "))
{
$ This-> error = "connection is not in the initial state ";
Return (0 );
}
$ This-> error = "";
If (! $ This-> PutLine ("mail from: <". $ sender. "> "))
Return (0 );
If (! IsSet ($ this-> esmtp_extensions ["PIPELINING"])
& $ This-> VerifyResultLines ("250") <= 0)
Return (0 );
$ This-> state = "SenderSet ";
If (IsSet ($ this-> esmtp_extensions ["PIPELINING"])
$ This-> pending_sender = 1;
$ This-> pending_recipients = 0;
Return (1 );
}
Function SetRecipient ($ recipient)
{
Switch ($ this-> state)
{
Case "SenderSet ":
Case "RecipientSet ":
Break;
Default:
$ This-> error = "connection is not in the recipient setting state ";
Return (0 );
}
$ This-> error = "";
If (! $ This-> PutLine ("rcpt to: <". $ recipient. "> "))
Return (0 );
If (IsSet ($ this-> esmtp_extensions ["PIPELINING"])
{
$ This-> pending_recipients ++;
If ($ this-> pending_recipients >=$ this-> maximum_piped_recipients)
{
If (! $ This-> FlushRecipients ())
Return (0 );
}
}
Else
{
If ($ this-> VerifyResultLines (array ("250", "251") <= 0)
Return (0 );
}
$ This-> state = "RecipientSet ";
Return (1 );
}
Function StartData ()
{
If (strcmp ($ this-> state, "RecipientSet "))
{
$ This-> error = "connection is not in the start sending data state ";
Return (0 );
}
$ This-> error = "";
If (! $ This-> PutLine ("DATA "))
Return (0 );
If ($ this-> pending_recipients)
{
If (! $ This-> FlushRecipients ())
Return (0 );
}
If ($ this-> VerifyResultLines ("354") <= 0)
Return (0 );
$ This-> state = "SendingData ";
Return (1 );
}
Function PrepareData ($ data, & $ output)
{
$ Length = strlen (& $ data );
For ($ output = "", $ position = 0; $ position <$ length ;)
{
$ Next_position = $ length;
For ($ current = $ position; $ current <$ length; $ current ++)
{
Switch ($ data [$ current])
{
Case "\ n ":
$ Next_position = $ current + 1;
Break 2;
Case "\ r ":
$ Next_position = $ current + 1;
If ($ data [$ next_position] = "\ n ")
$ Next_position ++;
Break 2;
}
}
If ($ data [$ position] = ".")
$ Output. = ".";
$ Output. = substr (& $ data, $ position, $ current-$ position). "\ r \ n ";
$ Position = $ next_position;
}
}
Function SendData ($ data)
{
If (strcmp ($ this-> state, "SendingData "))
{
$ This-> error = "connection is not in the sending data state ";
Return (0 );
}
$ This-> error = "";
Return ($ this-> PutData (& $ data ));
}
Function EndSendingData ()
{
If (strcmp ($ this-> state, "SendingData "))
{
$ This-> error = "connection is not in the sending data state ";
Return (0 );
}
$ This-> error = "";
If (! $ This-> PutLine ("\ r \ n .")
| $ This-& gt; VerifyResultLines ("250") <= 0)
Return (0 );
$ This-> state = "Connected ";
Return (1 );
}
Function ResetConnection ()
{
Switch ($ this-> state)
{
Case "Connected ":
Return (1 );
Case "SendingData ":
$ This-> error = "can not reset the connection while sending data ";
Return (0 );
Case "Disconnected ":
$ This-> error = "can not reset the connection before it is established ";
Return (0 );
}
$ This-> error = "";
If (! $ This-> PutLine ("RSET ")
| $ This-& gt; VerifyResultLines ("250") <= 0)
Return (0 );
$ This-> state = "Connected ";
Return (1 );
}
Function Disconnect ($ quit = 1)
{
If (! Strcmp ($ this-> state, "Disconnected "))
{
$ This-> error = "it was not previusly established a SMTP connection ";
Return (0 );
}
$ This-> error = "";
If (! Strcmp ($ this-> state, "Connected ")
& $ Quit
&&(! $ This-> PutLine ("QUIT ")
| $ This-> VerifyResultLines ("221") <= 0 ))
Return (0 );
Fclose ($ this-> connection );
$ This-> connection = 0;
$ This-> state = "Disconnected ";
Return (1 );
}
Function SendMessage ($ sender, $ recipients, $ headers, $ body)
{
If ($ success = $ this-> Connect ()))
{
If ($ success = $ this-> MailFrom ($ sender )))
{
For ($ recipient = 0; $ recipient <count ($ recipients); $ recipient ++)
{
If (! ($ Success = $ this-> SetRecipient ($ recipients [$ recipient])
Break;
}
If ($ success
& ($ Success = $ this-> StartData ()))
{
For ($ header_data = "", $ header = 0; $ header <count ($ headers); $ header ++)
$ Header_data. = $ headers [$ header]. "\ r \ n ";
If ($ success = $ this-> SendData ($ header_data. "\ r \ n ")))
{
$ This-> PrepareData ($ body, & $ body_data );
$ Success = $ this-> SendData ($ body_data );
}
If ($ success)
$ Success = $ this-> EndSendingData ();
}
}
$ Disconnect_success = $ this-> Disconnect ($ success );
If ($ success)
$ Success = $ disconnect_success;
}
Return ($ success );
}
};
?>