smtp.php
<?php
class smtp
{
/* Public Variables */
var $smtp_port;
var $time_out;
var $host_name;
var $log_file;
var $relay_host;
var $debug;
var $auth;
var $user;
var $pass;
/* Private Variables */
var $sock;
/* Constractor */
function smtp($relay_host = "", $smtp_port = 25,$auth = false,$user,$pass)
{
$this->debug = FALSE;
$this->smtp_port = $smtp_port;
$this->relay_host = $relay_host;
$this->time_out = 30; //is used in fsockopen()
#
$this->auth = $auth;//auth
$this->user = $user;
$this->pass = $pass;
#
$this->host_name = "localhost"; //is used in HELO command
$this->log_file = "";
$this->sock = FALSE;
}
/* Main Function */
function sendmail($to, $from, $subject = "", $body = "", $mailtype, $cc = "", $bcc = "", $additional_headers = "")
{
$mail_from = $this->get_address($this->strip_comment($from));
$body = ereg_replace("(^|(\r\n))(\.)", "\1.\3", $body);
$header .= "MIME-Version:1.0\r\n";
if($mailtype=="HTML"){
$header .= "Content-Type:text/html\r\n";
}
$header .= "To: ".$to."\r\n";
if ($cc != "") {
$header .= "Cc: ".$cc."\r\n";
}
$header .= "From: $from<".$from.">\r\n";
$header .= "Subject: ".$subject."\r\n";
$header .= $additional_headers;
$header .= "Date: ".date("r")."\r\n";
$header .= "X-Mailer:By Redhat (PHP/".phpversion().")\r\n";
list($msec, $sec) = explode(" ", microtime());
$header .= "Message-ID: <".date("YmdHis", $sec).".".($msec*1000000).".".$mail_from.">\r\n";
$TO = explode(",", $this->strip_comment($to));
if ($cc != "") {
$TO = array_merge($TO, explode(",", $this->strip_comment($cc)));
}
if ($bcc != "") {
$TO = array_merge($TO, explode(",", $this->strip_comment($bcc)));
}
$sent = TRUE;
foreach ($TO as $rcpt_to) {
$rcpt_to = $this->get_address($rcpt_to);
if (!$this->smtp_sockopen($rcpt_to)) {
$this->log_write("Error: Cannot send email to ".$rcpt_to."\n");
$sent = FALSE;
continue;
}
if ($this->smtp_send($this->host_name, $mail_from, $rcpt_to, $header, $body)) {
$this->log_write("E-mail has been sent to <".$rcpt_to.">\n");
} else {
$this->log_write("Error: Cannot send email to <".$rcpt_to.">\n");
$sent = FALSE;
}
fclose($this->sock);
$this->log_write("Disconnected from remote host\n");
}
return $sent;
}
/* Private Functions */
function smtp_send($helo, $from, $to, $header, $body = "")
{
if (!$this->smtp_putcmd("HELO", $helo)) {
return $this->smtp_error("sending HELO command");
}
#auth
if($this->auth){
if (!$this->smtp_putcmd("AUTH LOGIN", base64_encode($this->user))) {
return $this->smtp_error("sending HELO command");
}
if (!$this->smtp_putcmd("", base64_encode($this->pass))) {
return $this->smtp_error("sending HELO command");
}
}
#
if (!$this->smtp_putcmd("MAIL", "FROM:<".$from.">")) {
return $this->smtp_error("sending MAIL FROM command");
}
if (!$this->smtp_putcmd("RCPT", "TO:<".$to.">")) {
return $this->smtp_error("sending RCPT TO command");
}
if (!$this->smtp_putcmd("DATA")) {
return $this->smtp_error("sending DATA command");
}
if (!$this->smtp_message($header, $body)) {
return $this->smtp_error("sending message");
}
if (!$this->smtp_eom()) {
return $this->smtp_error("sending <CR><LF>.<CR><LF> [EOM]");
}
if (!$this->smtp_putcmd("QUIT")) {
return $this->smtp_error("sending QUIT command");
}
return TRUE;
}
function smtp_sockopen($address)
{
if ($this->relay_host == "") {
return $this->smtp_sockopen_mx($address);
} else {
return $this->smtp_sockopen_relay();
}
}
function smtp_sockopen_relay()
{
$this->log_write("Trying to ".$this->relay_host.":".$this->smtp_port."\n");
$this->sock = @fsockopen($this->relay_host, $this->smtp_port, $errno, $errstr, $this->time_out);
if (!($this->sock && $this->smtp_ok())) {
$this->log_write("Error: Cannot connenct to relay host ".$this->relay_host."\n");
$this->log_write("Error: ".$errstr." (".$errno.")\n");
return FALSE;
}
$this->log_write("Connected to relay host ".$this->relay_host."\n");
return TRUE;;
}
function smtp_sockopen_mx($address)
{
$domain = ereg_replace("^.+@([^@]+)$", "\1", $address);
if (!@getmxrr($domain, $MXHOSTS)) {
$this->log_write("Error: Cannot resolve MX \"".$domain."\"\n");
return FALSE;
}
foreach ($MXHOSTS as $host) {
$this->log_write("Trying to ".$host.":".$this->smtp_port."\n");
$this->sock = @fsockopen($host, $this->smtp_port, $errno, $errstr, $this->time_out);
if (!($this->sock && $this->smtp_ok())) {
$this->log_write("Warning: Cannot connect to mx host ".$host."\n");
$this->log_write("Error: ".$errstr." (".$errno.")\n");
continue;
}
$this->log_write("Connected to mx host ".$host."\n");
return TRUE;
}
$this->log_write("Error: Cannot connect to any mx hosts (".implode(", ", $MXHOSTS).")\n");
return FALSE;
}
function smtp_message($header, $body)
{
fputs($this->sock, $header."\r\n".$body);
$this->smtp_debug("> ".str_replace("\r\n", "\n"."> ", $header."\n> ".$body."\n> "));
return TRUE;
}
function smtp_eom()
{
fputs($this->sock, "\r\n.\r\n");
$this->smtp_debug(". [EOM]\n");
return $this->smtp_ok();
}
function smtp_ok()
{
$response = str_replace("\r\n", "", fgets($this->sock, 512));
$this->smtp_debug($response."\n");
if (!ereg("^[23]", $response)) {
fputs($this->sock, "QUIT\r\n");
fgets($this->sock, 512);
$this->log_write("Error: Remote host returned \"".$response."\"\n");
return FALSE;
}
return TRUE;
}
function smtp_putcmd($cmd, $arg = "")
{
if ($arg != "") {
if($cmd=="") $cmd = $arg;
else $cmd = $cmd." ".$arg;
}
fputs($this->sock, $cmd."\r\n");
$this->smtp_debug("> ".$cmd."\n");
return $this->smtp_ok();
}
function smtp_error($string)
{
$this->log_write("Error: Error occurred while ".$string.".\n");
return FALSE;
}
function log_write($message)
{
$this->smtp_debug($message);
if ($this->log_file == "") {
return TRUE;
}
$message = date("M d H:i:s ").get_current_user()."[".getmypid()."]: ".$message;
if (log_file">!@file_exists($this->log_file) || !($fp = @fopen($this->log_file, "a"))) {
$this->smtp_debug("Warning: Cannot open log file \"".$this->log_file."\"\n");
return FALSE;;
}
flock($fp, LOCK_EX);
fputs($fp, $message);
fclose($fp);
return TRUE;
}
function strip_comment($address)
{
$comment = "\([^()]*\)";
while (ereg($comment, $address)) {
$address = ereg_replace($comment, "", $address);
}
return $address;
}
function get_address($address)
{
$address = ereg_replace("([ \t\r\n])+", "", $address);
$address = ereg_replace("^.*<(.+)>.*$", "\1", $address);
return $address;
}
function smtp_debug($message)
{
if ($this->debug) {
echo $message;
}
}
}
?>
test.php
<?php
/*
这是一个测试程序!!!
请按照说明设置好以下的参数,以下是以tom.com的用户为例设置好的.
*/
require("sm.php");
##########################################
$smtpserver = "smtp.tom.com";//SMTP服务器
$smtpserverport =25;//SMTP服务器端口
$smtpusermail = "someone@tom.com";//SMTP服务器的用户邮箱
$smtpemailto = "jack@knowsky.com";//发送给谁
$smtpuser = "someone";//SMTP服务器的用户帐号
$smtppass = "someonepass";//SMTP服务器的用户密码
$mailsubject = "Test Subject";//邮件主题
$mailbody = "<h1>This is a test mail</h1>";//邮件内容
$mailtype = "HTML";//邮件格式(HTML/TXT),TXT为文本邮件
##########################################
$smtp = new smtp($smtpserver,$smtpserverport,true,$smtpuser,$smtppass);//这里面的一个true是表示使用身份验证,否则不使用身份验证.
$smtp->debug = TRUE;//是否显示发送的调试信息
$smtp->sendmail($smtpemailto, $smtpusermail, $mailsubject, $mailbody, $mailtype);
?>
期待已久的PHP5终于在当地时间7月13日正式发布了。无论对于PHP语言本身还是PHP的用户来讲,PHP5发布都算的上是一个里程碑式的版本。在PHP5发布之前的各个PHP版本就以简单的语法、丰富的库函数以及极快的脚本解释执行速度,赢得了许多开发者的青睐,几乎成了*NIX平台上首选的WEB开发语言。然而,站在语言本身角度,PHP的语法,特别是OO方面的语法设计并不完善,当然这和PHP语言的作者一开始的设计目的有关。
众所周知,PHP最开始只是一个用Perl写成的一个模板系统,其后的发展思路也是尽可能为快速开发WEB程序提供方便。大量的库函数加入其中,而语言模型的发展则相对缓慢。虽然在PHP4中加入了面向对象的设计,但其语言模型并不完善,缺乏诸如构造函数、析构函数、抽象类(接口)、异常处理等基本元素。这极大限制了利用PHP来完成大规模应用程序的能力。
而PHP5的诞生,则从根本上改变了PHP的上述弊端。Zend II 引擎的采用,完备对象模型、改进的语法设计。终使得PHP成为一个设计完备、真正具有面向对象能力的脚本语言。我们预计,PHP5的出现,将会给整个PHP社区带来新的一轮各种库、应用开发改进的高峰。
PHP5.0版本强化了以下功能。首先,完全实现面向对象。PHP4版本中以深拷贝为缺省值的对象代入,在PHP5中变为以浅拷贝为缺省值。因此,PHP5并非与PHP4完全兼容,不过,提供名为PHP兼容模式的功能。其次是XML功能,PHP5.0版本支持可直观地访问XML数据、名为SimpleXML的XML处理用界面。同时还强化了XML Web服务支持,而且标准支持SOAP扩展模块。
数据库方面,PHP新版本提供旨在访问MySQL的新界面--MySQLi。除此前的界面外,还可以使用面向对象界面和预处理语句(Prepared Statement)等MySQL的新功能。另外,PHP5.0上还捆绑有小容量RDBMS--SQLite。
这是一个经常被提出的问题,并且它很容易把人们带入争论Linux还是Windows的歧途。这样的争论事实上反映出了对于相互竞争的Web开发技术要进行并行分析是多么困难的一件事情,而这一难度同时因为开发人员对任何可比较操作系统的不同意见而大大增加。
所以与其继续参与到这样的争论中,我们还不如来看看每一项技术对于特定Web开发以及运行环境所表现出的优势。尽管ASP和PHP的相似程度大于其中任意一种与ASP.NET的相似程度,我们还是要讨论ASP.NET。原因是开发人员常常将其与ASP相混淆,并且在微软的努力下ASP.NET的确会在将来完全取代ASP。
基本理论——特点概述
PHP——超文本预处理器(Hypertext Pre-processor)
PHP是开放源代码服务器端的脚本语言,在语法上同C语言非常类似。尽管最初是被设计用于基于Linux的Apache Web 服务器系统,现在的PHP已经被移植到了任何操作系统并兼容任何标准Web服务器软件。由此也可以得出PHP的三大主要优势。首先它是跨平台的技术,因此PHP应用程序可以被方便的移植——当然这还要取决于诸如厂商特定数据库等需要集成的额外组件。这样的可移植性还带来了另一方面的优势,即绝大部分的Web主机提供商都会支持PHP,因此根据需要更改主机将会非常方便。
第二点,由于PHP同C编程语言有很多相似之处,对于熟悉相关语法的开发人员来说,PHP则非常容易上手——这种语法同样在Java、JavaScript以及Perl中得到应用。第三,由于是开放源代码产品,PHP将继续快速发展,更为重要的是相关漏洞补丁将免费的定期植入到核心库中。
此外,在一些特定的编程需求下,PHP对于开发人员显示出了更为诱人的吸引力。首先,PHP有内建库支持对于图片及PDF文档的直接创建和相关操作。这意味着当一个应用程序调用包含有anti-aliased类型文本的动态创建菜单图像,或者是需要导出Acrobat格式页面时,PHP都将是解决此类问题的理想技术。尽管这些功能在理论上也可以通过其他与PHP相竞争的技术获得,但往往其他技术需要安装第三方自定义组件才能实现。
另一点使得PHP成为编写服务器脚本最佳选择的是在处理连接mySOL或者Postgres数据库一类的问题时PHP的良好表现。尽管对于mySOL或者Postgres数据库的访问可以通过ASP技术借助ODBC连接来实现,但这常常需要系统管理员进行额外的配置。幸运的是,这点限制在ASP.NET中得到了改正,当需要建立类似于使用MS SQL Server的直接数据库连接时可以通过mySQL提供数据。
ASP——动态服务页面(Active Server Pages)
微软将ASP引入Windows NT Server 4并将其作为IIS Web服务器下的动态Web应用程序的默认使用平台。由于它使用VBScript(Visual Basic语言的一个分支),ASP立即被熟悉Microsoft IDE——Visual Studio编程的开发人员所追捧。随着脚本语言的不断发展,研究人员对ASP并没有引入太多功能使之加入到技术竞争的行列。因此,在PHP中可以看到的诸如图像操作等功能没有集成到ASP中。但开发人员仍然可以通过DLL文件的形式编写(或者安装)第三方COM对象来完成类似的工作。在服务器自身允许的情况下,通过这种方式可以编写代码来完成任何动作。当然,造成的缺陷是这将导致为了配置这些服务开发人员不得不与桌面系统进行交互——对于Web开发人员来说这项功能并不是必须的。
ASP的优势是在企业环境中微软服务器几乎无处不在。此外,MS SQL Server同样具有广泛的市场,并且能很好的支持ASP(这并不会让人感到惊奇)。尽管事实上通过ODBC可以兼容任何数据来源,但SQL Server以及文件DSN访问(file DSN access)可以在代码一级得到实现。
ASP.NET
是选择ASP还是PHP的争论正在随着.NET的崛起而越来越显得多余。的确,过去长达数年的争论将随着是选择Java还是.NET技术(或是两者)答案的揭晓而终结。ASP以及ASP.NET的唯一联系是二者都使用VBScript。而单独就.NET而言,它可以使用VBScript以及其他大约20种语言。
对于ASP以及PHP来说,将ASP.NET看作是另外一种语言的原因是它运行在完全不同的构架之上。前者是翻译脚本语言,而.NET则是经过编译的framework。这就意味着首先Web页面的运行速度将会有极大提高。同时,源代码更加安全且更为健壮。此外,ASP.NET给Web编程带来了新的理念——即“code-behind页面”的思想。按照code-behind思想,每一个HTML页面都是由自身经过编译的程序化指令进行驱动。因此,HTML——或称之为表现层——很大程度上脱离了应用程序的商业逻辑。尽管这样的分离也可以通过PHP和ASP来实现,但这并非同ASP.NET一样属于自身技术的主要部分。
ASP.NET的另一好处是它完整的集成了对XML以及Web服务的各种支持。对.NET而言可以使用非常广泛的安全以及密码系统库,这对于金融机构和企业数据应用程序尤为有用。就缺陷而言,即使是具备丰富经验的开发人员也会发现使用.NET可能把自己搞糊涂。不考虑开发者对于所使用的编程语言的熟悉程度,对于Web开发人员来说,在程序范例方面难度的大幅提升可能会成为他们融入ASP.NET的主要障碍。对ASP.NET应用程序来说主机同样是个问题,ASP.NET并未同ASP或者PHP一样获得了主机提供商的广泛支持,无法在同一级别上展开竞争。
实践——语言比较
变量声明
在VBScript中(ASP和ASP.NET都使用VBScript),在使用变量之前并不一定要对其进行声明,尽管技术文档通常建议这么做。使用Option Explicit声明,开发人员可以通过程序强制进行变量声明。在PHP中,变量可以被声明,尽管没有办法强制开发人员做到这点。的确,在使用之前变量都自动进行声明。PHP变量的优点在于变量可以被设置成为其他变量的引用(references),而在VBScript中变量只能通过值来定义。
<%
' VBScript Example
Option Explicit
myVar = 1
myOtherVar = myVar
myVar = 2
' myResult will be 3
myResult = myVar + myOtherVar
%>
<?
// PHP Example
$myVar = 1;
'Use the ampersand to make a reference
$myOtherVar = &$myVar;
$myVar = 2;
// $myResult will be 4
$myResult = $myVar + $myOtherVar;
?>
变量收集
在PHP以及ASP中使用表单以及query string变量的方法非常相似。有很多办法可以访问表单以及query string变量的集合,例如通过name或者将其作为数组。在ASP.NET中情况则有很多不同,尤其是对于表单域。不同于盲目的寻找提交过的表单变量,code-behind可以对HTML页面中的每一个表单域了如指掌,并可以按照任何已知事件的执行为条件触发对这些表单域的值进行检查。其中一个事件是“postback”,当表单被用户提交时此事件被触发。其他的事件可以是客户端的程序,并且可以通过JavaScript来触发。在ASP.NET中,二者没有性质上的区别。
<%
' ASP Example
myFormVal = request.form("myInputField")
myQSval = request.querystring("myQSitem")
myVal = request.item("myFormOrQSitem")
%>
<?
// PHP 4.1+ Example
$myFormVal = $_POST['myInputField'];
$myQSval = $_REQUEST['myQSitem'];
// PHP 3+ Example
$myFormVal = $HTTP_POST_VARS['myInputField'];
// If register_globals = on
$myVal = $myFormOrQSitem;
?>
<!-- ASP.NET example -->
<html>
<script language="VB" runat=server>
Sub SubmitBtn_Click(Sender As Object, E As EventArgs)
Message.Text = "Hello " & Name.Text
End Sub
</script>
<body>
<form action="/blog_article/action.html" method="post" runat="server">
Name: <asp:textbox id="Name" runat="server"/>
<asp:button text="OK" OnClick="SubmitBtn_Click"
runat="server"/>
<asp:label id="Message" runat="server"/>
</form>
</body>
</html>
字符串连接(String Concatenation)
PHP似乎对此问题给予了足够的重视,它允许将变量插入到字符串中而无需考虑通常的串连(Concatenation)问题。ASP.NET则把整个过程弄得比较麻烦,需要借助其StringBuilder类,但由此ASP.NET的运行速度也会快很多。
<?
// PHP Example
$link = mysql_connect("host", "user", "password")or die("mysql_error());
mysql_select_db("database") or die("Could not select database");
$query = "SELECT * FROM Table";
$result = mysql_query($query) or die(mysql_error());
while ($line = mysql_fetch_array($result, MYSQL_ASSOC)) {
foreach ($line as $col_value) {
//do something
}
}
?>
连接数据库
对于数据库的连接问题,每种技术都表现出了各自突出的规范性。首先,每种情况都要建立到数据库的连接。对于PHP,在建立之后选择数据库(对于ASP以及ASP.NET则将在连接阶段完成)。随后将建立一个询问,并将其传送给数据库,由此可能产生也可能不会产生一条返回记录。
由于在本质上ASP.NET更为以对象为导向,并且支持复杂的错误处理(error handling),因此无论是相对于PHP还是ASP,在完成简单任务方面ASP.NET可能会需要编写更多的代码。但在优势方面,ASP.NET完成显示数据功能所需要的代码则大大少于PHP以及ASP——尤其如果使用内建的datagrid控制来自动创建HTML输出。
<%
'ASP Example
Set objConn = Server.CreateObject("ADODB.Connection")
objConn.Open "Driver={SQL Server};Server=MyServerName;" & _
"Database=myDatabaseName;Uid=;Pwd="
const strSQL = "SELECT * FROM Table" Set objRS = Server.CreateObject("ADODB.Recordset")
objRS.OpenstrSQL, objConn
Do While Not objRS.EOF
'do something
objRS.MoveNext
Loop
%>
' ASP.NET Example
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<html>
<script language="VB" runat="server">
Sub Page_Load(Sender As Object, E As EventArgs)
Dim MyConn As SqlConnection = New SqlConnection("server=(local). . . ")
Dim MyComm As SqlCommand = New SqlCommand("select * from Table", MyConn)
MyConn.Open()
Dim dr As SqlDataReader = MyComm.ExecuteReader()
MyDataGrid.DataSource = dr
MyDataGrid.DataBind()
MyConn.Close()
End Sub
</script>
<body>
<ASP:DataGrid id="MyDataGrid" runat="server"
Width="600"
BackColor="#FFFFFF"
BorderColor="#000000"
ShowFooter="false"
CellPadding=2
CellSpacing="0"
Font-Name="Verdana"
Font-Size="8pt"
HeaderStyle-BackColor="#EEEEEE"
EnableViewState="false"
/>
</body>
</html>
结论
选择ASP、PHP还是ASP.NET将最终取决于应用程序的需要,以及运行程序的系统环境。开发人员对于相似编程语言或范例的熟悉程度同样可以作为选择的因素。记住没有完美的方法和个人实际情况可以表明哪种技术是最佳选择。比如,使用ASP.NET为一个Windows服务器创建一个单页面的表单邮件应用程序似乎有些大材小用,但对于ASP来说这是极佳的应用环境。如果一个站点需要同Linux Apache服务器上的mySQL数据库连接,那么使用ASP或者ASP.NET则会显得力不从心。如果能够提前详细考虑用户的个人要求,那么开发人员在这些相互竞争的技术中进行选择的过程则已成功了一半。