当前位置: 首页 > 文章教程  > 计算机与互联网 > 网络编程

22.2功能设计和实现

9/17/2020 9:31:19 PM 人评论

22.2功能设计和实现

22.2 功能设计和实现

本节开始实现用PHP发送邮件的程序。该程序的基本功能是,通过PHP程序,向SMTP发起请求,待SMTP服务器验证通过后,向PHP程序指定的邮箱发送邮件。使用mail函数也可以发送邮件,但其功能比较弱,不便于调试,而且在Windows下需要配置SMTP服务器,所以本章将通过Socket实现发送邮件的PHP程序。本节将设计一个发送邮件的PHP类,通过这个类完成向SMTP服务器发起请求以及发送邮件的功能。

22.2.1 设计一个发送邮件的类

有了22.1节的理论基础,实现发送邮件的类并不是一件困难的事。首先,确定该类应该有以下成员变量。

·$lastmessage:改变量记录服务器最后返回的响应信息。

·$lastact:最近一次要执行的操作,即是HELLO还是MAIL FROM请求等。

·$welcome:用在HELLO命令后面的字符串。

·$debug:是否显示调试信息。

·$smtp:smtp服务器。

·$port:smtp端口号。

·$fp:socket句柄。

需要实现的函数包括类的构造函数,显示调试信息的函数,处理Socket的函数以及发送邮件的函数。其中发送邮件的函数其实就是用来向Socket发送执行SMTP请求的命令。代码22-1是这个类的完整实现。

代码22-1 发送邮件的PHP类mail.php


     01 <?php
     02 class smtp_mail
     03 {
     04     var $lastmessage;                                   //
记录最后返回的响应信息
     05     var $lastact;                                       //
最近一次要执行的操作
     06     var $welcome;                                       //
用在HELLO
命令后面的字符串
     07     var $debug;                                         //
是否显示调试信息
     08     var $smtp;                                          //smtp
服务器
     09     var $port;                                          //smtp
端口号
     10     var $fp;                                            //socket
句柄
     11 
     12     function smtp_mail($smtp, $welcome="", $debug=false)
     13     {
     14         if(empty($smtp)) die("SMTP cann't be NULL!");
     15         
     16         $this->smtp=$smtp;
     17         if(empty($welcome))
     18         {
     19             $this->welcome=gethostbyaddr("localhost");
     20         }
     21         else
     22             $this->welcome=$welcome;
     23         $this->debug=$debug;
     24         
     25         $this->lastmessage="";
     26         $this->lastact="";
     27         $this->port="25";
     28     }
     29 
     30     function show_debug($message, $inout)
     31     {
     32         $b = false;
     33         if ($this->debug)
     34         {  
     35             if($inout=="in")                            //
响应信息
     36             {
     37                 $m='<< ';
     38                 $b = true;
     39             }
     40             else                                        //
请求指令
     41                 $m='>> ';
     42             if(!ereg("\n$", $message))
     43                 $message .= "";
     44             $message=nl2br($message);
     45             if($b)
     46                 echo "<b>${m}${message}</b>";
     47             else
     48                 echo "${m}${message}";
     49         }
     50     }
     51 
     52     function do_command($command, $code)                //
处理Socket
     53     {
     54         $this->lastact=$command;
     55         $this->show_debug($this->lastact, "out");
     56         fputs ( $this->fp, $this->lastact );
     57         
     58         $this->lastmessage = fgets ( $this->fp, 512 );
     59         $this->show_debug($this->lastmessage, "in");
     60         
     61         if(!ereg("^$code", $this->lastmessage))
     62         {
     63             return false;
     64         }
     65         else
     66             return true;
     67     }
     68 
     69     function send($from,$to,$subject,$message)         //
发送邮件
     70     {
     71         $this->show_debug("Connect to SMTP server : ".$this->smtp."\n", "out");
     72         $this->fp = fsockopen ( $this->smtp, $this->port );
     73         if ( $this->fp )
     74         {
     75             set_socket_blocking( $this->fp, true );
     76             $this->lastmessage=fgets($this->fp,512);
     77             $this->show_debug($this->lastmessage, "in");
     78             
     79             if (! ereg ( "^220", $this->lastmessage ) ) 
     80             {
     81                 return false;
     82             } 
     83             else 
     84             {
     85                 $this->lastact="HELLO " . $this->welcome . "\n";
     86                 if(!$this->do_command($this->lastact, "250"))
     87                 {
     88                     fclose($this->fp);
     89                     return false;
     90                 }
     91                 
     92                 $this->lastact="MAIL FROM:<$from>". "\n";
     93                 if(!$this->do_command($this->lastact, "250"))
     94                 {
     95                     fclose($this->fp);
     96                     return false;
     97                 }
     98 
     99                 $this->lastact="RCPT TO:<$to>" . "\n";
     100                if(!$this->do_command($this->lastact, "250"))
     101                {
     102                    fclose($this->fp);
     103                    return false;
     104                }
     105
     106                $this->lastact="DATA\n";          //
发送正文
     107                if(!$this->do_command($this->lastact, "354"))
     108                {
     109                    fclose($this->fp);
     110                    return false;
     111                }
     112
     113                $head="Subject: $subject\n";      //
处理Subject
     114                if(!empty($subject) && !ereg($head, $message))
     115                {
     116                    $message = $head.$message;
     117                }
     118
     119                
     120                $head="From: $from\n";            //
处理From 
     121                if(!empty($from) && !ereg($head, $message))
     122                {
     123                    $message = $head.$message;
     124                }
     125
     126                $head="To: $to\n";                //
处理To
     127                if(!empty($to) && !ereg($head, $message))
     128                {
     129                    $message = $head.$message;
     130                }
     131
     132                if(!ereg("\n\.\n", $message))     //
加上结束串
     133                    $message .= "\n.\n";
     134                $this->show_debug($message, "out");
     135                fputs($this->fp, $message);
     136
     137                $this->lastact="QUIT\n";
     138                if(!$this->do_command($this->lastact, "250"))
     139                {
     140                    fclose($this->fp);
     141                    return false;
     142                }
     143            }
     144            return true;
     145        }
     146        else
     147        {
     148            $this->show_debug("Connect failed!", "in");
     149            return false;
     150        }
     151    }
     152 }
     153 ?>

【代码解析】构造函数smtp_mail()完成一些初始值的判定及设置。参数$welcome用于HELLO指令中,告诉服务器用户的名字或者直接填写服务器的名称,表示向服务器打招呼。如果用户没有给出$welcome,则自动查找本地的机器名,如代码第19行所示。

函数show_debug()用来显示调试信息,可以在参数$inout中指定是请求指令还是返回的响应。如果为请求指令,则使用“out”;如果为返回的响应,则使用“in”。代码第35行判断是否为响应信息,如果是,将信息的前面加上“<<”来区别响应指令,加上“>>”来区别请求指令。同时将响应信息的字符串字体加粗显示,如代码第46行和第48行所示。

函数do_command()用来处理Socket部分,通过Socket处理参数$command所表示的指令,对于HELLO、MAIL FROM、RCPT TO、QUIT和DATA指令,都要求根据是否显示调试信息将相关内容显示出来,并且根据参数$code所表示的服务器响应码,决定是否中断处理。代码第56行使用fputs向服务器发送请求指令。该函数一方面完成指令及信息的发送、显示功能,另一方面根据返回的响应判断是否成功。

函数send()用来发送邮件的函数,它共有4个参数,分别是:$from是发信邮件地址;$to是收信人邮件地址;$subject是邮件的主题;$message是邮件体,也就是邮件正文。如果处理成功,该函数返回true,否则返回false。其中的代码$this->fp=fsockopen($this->smtp,$this->port),作用是使用函数fsockopen()打开一个网络链接,其第一个参数是表示此socket链接的标识符,第2个参数标识在哪个端口打开此链接。

22.2.2 测试发送邮件功能

22.2.1小节实现了发送邮件的PHP类,本小节对这个类的功能加以测试。首先编写一个测试程序,代码22-2是一个测试程序。

代码22-2 测试smtp_mail类的PHP程序testmail.php


     01 <?php
     02 include "mail.php";
     03 echo "<b>start....</b><br/>";
     04 
     05 $email="Hello, this is a test mail!";
     06 $sendmail=new smtp_mail("smtp.sina.com", "sina", true);//
实例化一个smtp_mail
类的对象
     07 if($sendmail->send("macbooks@domain", " macbooks@domain", "test", $email))
                                                               //
发送邮件
     08 {
     09     echo "
发送成功!";
     10 }
     11 else
     12 {
     13     echo "
发送失败!";
     14 }
     15 
     16 echo "<br/><b>end....</b><br/>";
     17 ?>

【代码解析】这是一个很简单的测试程序。代码第02行将smtp_mail类的定义包含进该程序,然后在第05行定义了一个字符串变量$email表示邮件的正文。在第06行实例化一个smtp_mail类的对象,第07行就是调用该对象的send()方法发送邮件了,其中该函数的发送地址参数和接收地址参数都为macbooks@sina.com,读者调试时,需要使用自己真实的地址。第05行初始化对象时,所使用的SMTP服务器地址smtp.sina.com也仅仅是个示例,读者可以根据实际情况替换成其他的SMTP服务器地址。设定好SMTP服务器地址、发件人地址和收件人地址,执行程序testmail.php,如果一切正常,会看到类似图22-1所示的结果;如果有错误,也可以看到相关的服务器响应信息和错误代码。

22.2.3 发送邮件的表单及程序实现

有了可以发送电子邮件的PHP类之后,最后制作一个发送邮件的简易界面和执行发送的PHP程序。

(1)发送电子邮件的用户界面使用HTML编写,可以参考代码22-3。

代码22-3 发送邮件的用户界面user.htm


     01 <html>
     02 <head>
     03 <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
     04 <title>
使用PHP
发送电子邮件</title>
     05 <style type="text/css">
     06 <!--
     07 .STYLE1 {font-size: 12px}
     08 .STYLE2 {
     09         font-size: 24px;
     10         font-weight: bold;
     11 }
     12 -->
     13 </style>
     14 </head>
     15 
     16 <body>
     17 <p  class="STYLE2">
使用PHP
发电子邮件</p>
     18 <form name="form1" method="post" action="send_mail.php">
     19 <table width="444" height="347" border="0" >
     20     <tr>
     21         <td width="71" height="23" bgcolor="#D6B1E9">
     22         <div  class="STYLE1">
     23             <div >&nbsp;
收件人</div>
     24         </div>
     25         </td>
     26         <td width="363">
     27             <label>&nbsp;<input type="text" name="sendto"></label>
     28         </td>
     29     </tr>
     30     <tr>
     31         <td height="27" bgcolor="#D6B1E9">
     32         <div  class="STYLE1">
     33             <div >&nbsp;
邮件标题</div>
     34         </div></td>
     35         <td>
     36             <label>&nbsp;<input type="text" name="subject"></label>
     37         </td>
     38     </tr>
     39     <tr>
     40         <td height="23" colspan="2" bgcolor="#D6B1E9">
     41         <div  class="STYLE1">
     42             <div >&nbsp;
邮件正文</div>
     43         </div>
     44         </td>
     45     </tr>
     46     <tr>
     47         <td colspan="2" bgcolor="#D6B1E9">
     48         <div >
     49             <label>
     50             <div >
     51                 <textarea name="emailcontent" cols="60" rows="18"></textarea>
     52             </div>
     53             </label>
     54         </div>
     55           <div ></div>
     56         <div ></div>
     57         </td>
     58     </tr>
     59     <tr>
     60         <td colspan="2">
     61             <label><input type="submit" name="Submit" value="
提交"></label>
     62         </td>
     63     </tr>
     64 </table>
     65 </form>
     66 
     67 </body>
     68 </html>

【代码解析】 这是一个常见的邮件发送界面,包含收件人、标题和邮件内容,使用了<table>标签实现界面对齐。

(2)该HTML页面会将收件人、邮件标题等信息提交至程序send_mail.php做处理。该页面显示效果如图22-2所示。

图22-1 发送邮件测试程序的执行结果

图22-2 发送邮件的简单界面

(3)接下来完成发送电子邮件的PHP程序,该程序将使用22.2.1小节创建的smtp_mail类完成发送邮件的功能。这个程序并不复杂,只需对22.2.2小节编写的testmail.php稍做修改即可,如代码22-4所示。

代码22-4 发送邮件的程序send_mail.php


     01 <?php
     02 include "mail.php";                                     //
将指定的文件包含进来
     03 
     04 if(isset($_POST['sendto']))                             //
判断收信人
     05     $sendto = $_POST['sendto'];
     06 else
     07     $sendto = '';
     08 
     09 if(isset($_POST['subject']))                            //
判断主题
     10     $subject = $_POST['subject'];
     11 else
     12     $subject = '';
     13 
     14 if(isset($_POST['emailcontent']))                       //
判断邮件内容
     15     $emailcontent = $_POST['emailcontent'];
     16 else
     17     $emailcontent = '';
     18 
     19 if(empty($sendto) || empty($subject) || empty($emailcontent))
     20 {
     21     echo '<b>
请填写收件人email
地址、邮件主题和邮件正文。</b><br/>';
     22     exit;
     23 }
     24 
     25 $sendmail=new smtp_mail("smtp.sina.com", "sina", false);
     26 if($sendmail->send("macbooks@sina.com", $sendto, $subject, $emailcontent))//
发信
     27 {
     28     echo "
发送成功!";
     29 }
     30 else
     31 {
     32     echo "
发送失败!";
     33 }
     34 ?>

【代码解析】程序send_mail.php通过使用类smtp_mail完成邮件的发送。代码第26行发送邮件所使用的邮件地址是个例子,读者需要根据实际情况加以替换。

上一篇:22.1mail()函数和SMTP简介

下一篇:22.3小结

相关教程

共有条评论 网友评论

验证码: 看不清楚?