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

21.2功能设计和实现

9/17/2020 9:26:54 PM 人评论

21.2功能设计和实现

21.2 功能设计和实现

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

21.2.1 设计一个发送邮件的类

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

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

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

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

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

❑$smtp:smtp服务器。

❑$port:smtp端口号。

❑$fp:socket句柄。

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

代码21-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 ?>


【代码解析】

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

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

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

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

相关教程

共有条评论 网友评论

验证码: 看不清楚?