用php发邮件的简单实现

  在两个月前的公司项目中,虽然没有涉及代码,但让我了解了php对于邮件的实现,知道了后台可以利用php来自动发送邮件。因为根本不会php,对于邮箱验证的过程,yy如下:首先在验证框中输入自己的邮箱地址,然后点击按钮,此时前端与后台开始交互,搜索了一下,前端将数据发送给后台,大概有三种方法,1可以直接POST,2用url传递,3用ajax,暂时觉得这个过程是个直接POST的过程,虽然我不知道是怎么实现的,貌似可以用form。此时后台php代码可以读到该邮箱地址,在数据库中判断是否注册,如没有则进行邮箱验证,那么问题来了,怎么自动给该邮箱发送验证邮件?

  php自带一个mail方法,看起来很简单,不过只能在linux下直接使用,windows下要配置smtp服务器,太麻烦了;然后继续查找发现可以用一些现成的类,其中很有名的一个叫做phpmailer的,功能看起来很强大,因为代码太多,再一找,找到个简单的类,叫做smtp.php,代码如下:

  1 <?php 
  2 class smtp 
  3 { 
  4     /* Public Variables */ 
  5     var $smtp_port; 
  6     var $time_out; 
  7     var $host_name; 
  8     var $log_file; 
  9     var $relay_host; 
 10     var $debug; 
 11     var $auth; 
 12     var $user; 
 13     var $pass; 
 14 
 15     /* Private Variables */  
 16     var $sock; 
 17 
 18     /* Constractor */ 
 19     function smtp($relay_host = "", $smtp_port = 25,$auth = false,$user,$pass) 
 20     { 
 21         $this->debug = FALSE; 
 22         $this->smtp_port = $smtp_port; 
 23         $this->relay_host = $relay_host; 
 24         $this->time_out = 30; //is used in fsockopen()  
 25         $this->auth = $auth;//auth 
 26         $this->user = $user; 
 27         $this->pass = $pass; 
 28         $this->host_name = "localhost"; //is used in HELO command  
 29         $this->log_file = ""; 
 30         $this->sock = FALSE; 
 31 } 
 32 
 33     /* Main Function */ 
 34     function sendmail($to, $from, $subject = "", $body = "", $mailtype, $cc = "", $bcc = "", $additional_headers = "") 
 35     { 
 36         $mail_from = $this->get_address($this->strip_comment($from)); 
 37         $body = ereg_replace("(^|(\r\n))(\.)", "\1.\3", $body); 
 38         $header .= "MIME-Version:1.0\r\n"; 
 39         if($mailtype=="HTML") 
 40         { 
 41             $header .= "Content-Type:text/html\r\n"; 
 42         } 
 43         $header .= "To: ".$to."\r\n"; 
 44         if ($cc != "")  
 45         { 
 46             $header .= "Cc: ".$cc."\r\n"; 
 47         } 
 48         $header .= "From: $from<".$from.">\r\n"; 
 49         $header .= "Subject: ".$subject."\r\n"; 
 50         $header .= $additional_headers; 
 51         $header .= "Date: ".date("r")."\r\n"; 
 52         $header .= "X-Mailer:By Redhat (PHP/".phpversion().")\r\n"; 
 53         list($msec, $sec) = explode(" ", microtime()); 
 54         $header .= "Message-ID: <".date("YmdHis", $sec).".".($msec*1000000).".".$mail_from.">\r\n"; 
 55         $TO = explode(",", $this->strip_comment($to)); 
 56 
 57         if ($cc != "")  
 58         { 
 59             $TO = array_merge($TO, explode(",", $this->strip_comment($cc))); 
 60             } 
 61         if ($bcc != "")  
 62         { 
 63             $TO = array_merge($TO, explode(",", $this->strip_comment($bcc))); 
 64         } 
 65         $sent = TRUE; 
 66         foreach ($TO as $rcpt_to)  
 67         { 
 68             $rcpt_to = $this->get_address($rcpt_to); 
 69             if (!$this->smtp_sockopen($rcpt_to))  
 70             { 
 71                 $this->log_write("Error: Cannot send email to ".$rcpt_to."\n"); 
 72                 $sent = FALSE; 
 73                 continue; 
 74             } 
 75             if ($this->smtp_send($this->host_name, $mail_from, $rcpt_to, $header, $body))  
 76             { 
 77                 $this->log_write("E-mail has been sent to <".$rcpt_to.">\n"); 
 78             }  
 79             else  
 80             { 
 81                 $this->log_write("Error: Cannot send email to <".$rcpt_to.">\n"); 
 82                 $sent = FALSE; 
 83             } 
 84             fclose($this->sock); 
 85             $this->log_write("Disconnected from remote host\n"); 
 86         } 
 87         return $sent; 
 88     } 
 89 
 90     /* Private Functions */ 
 91     function smtp_send($helo, $from, $to, $header, $body = "") 
 92     { 
 93         if (!$this->smtp_putcmd("HELO", $helo))  
 94         { 
 95             return $this->smtp_error("sending HELO command"); 
 96         } 
 97 
 98         #auth 
 99         if($this->auth) 
100         { 
101             if (!$this->smtp_putcmd("AUTH LOGIN", base64_encode($this->user)))  
102             { 
103                 return $this->smtp_error("sending HELO command"); 
104             } 
105             if (!$this->smtp_putcmd("", base64_encode($this->pass)))  
106             { 
107                 return $this->smtp_error("sending HELO command"); 
108             } 
109         } 
110         if (!$this->smtp_putcmd("MAIL", "FROM:<".$from.">"))  
111         { 
112             return $this->smtp_error("sending MAIL FROM command"); 
113         } 
114         if (!$this->smtp_putcmd("RCPT", "TO:<".$to.">"))  
115         { 
116             return $this->smtp_error("sending RCPT TO command"); 
117         } 
118         if (!$this->smtp_putcmd("DATA")) 
119         { 
120             return $this->smtp_error("sending DATA command"); 
121         } 
122         if (!$this->smtp_message($header, $body))  
123         { 
124             return $this->smtp_error("sending message"); 
125         } 
126         if (!$this->smtp_eom()) 
127         { 
128             return $this->smtp_error("sending <CR><LF>.<CR><LF> [EOM]"); 
129         } 
130         if (!$this->smtp_putcmd("QUIT"))  
131         { 
132             return $this->smtp_error("sending QUIT command"); 
133         } 
134         return TRUE; 
135     } 
136 
137     function smtp_sockopen($address) 
138     { 
139         if ($this->relay_host == "")  
140         { 
141             return $this->smtp_sockopen_mx($address); 
142         }  
143         else 
144         { 
145             return $this->smtp_sockopen_relay(); 
146         } 
147     } 
148 
149     function smtp_sockopen_relay() 
150     { 
151         $this->log_write("Trying to ".$this->relay_host.":".$this->smtp_port."\n"); 
152         $this->sock = @fsockopen($this->relay_host, $this->smtp_port, $errno, $errstr, $this->time_out); 
153         if (!($this->sock && $this->smtp_ok()))  
154         { 
155             $this->log_write("Error: Cannot connenct to relay host ".$this->relay_host."\n"); 
156             $this->log_write("Error: ".$errstr." (".$errno.")\n"); 
157             return FALSE; 
158         } 
159         $this->log_write("Connected to relay host ".$this->relay_host."\n"); 
160         return TRUE;; 
161     } 
162 
163     function smtp_sockopen_mx($address) 
164     { 
165         $domain = ereg_replace("^.+@([^@]+)$", "\1", $address); 
166         if (!@getmxrr($domain, $MXHOSTS))  
167         { 
168             $this->log_write("Error: Cannot resolve MX \"".$domain."\"\n"); 
169             return FALSE; 
170         } 
171         foreach ($MXHOSTS as $host)  
172         { 
173             $this->log_write("Trying to ".$host.":".$this->smtp_port."\n"); 
174             $this->sock = @fsockopen($host, $this->smtp_port, $errno, $errstr, $this->time_out); 
175             if (!($this->sock && $this->smtp_ok()))  
176             { 
177                 $this->log_write("Warning: Cannot connect to mx host ".$host."\n"); 
178                 $this->log_write("Error: ".$errstr." (".$errno.")\n"); 
179                 continue; 
180             } 
181             $this->log_write("Connected to mx host ".$host."\n"); 
182             return TRUE; 
183         } 
184         $this->log_write("Error: Cannot connect to any mx hosts (".implode(", ", $MXHOSTS).")\n"); 
185         return FALSE; 
186     } 
187 
188     function smtp_message($header, $body) 
189     { 
190         fputs($this->sock, $header."\r\n".$body); 
191         $this->smtp_debug("> ".str_replace("\r\n", "\n"."> ", $header."\n> ".$body."\n> ")); 
192         return TRUE; 
193     } 
194 
195     function smtp_eom() 
196     { 
197         fputs($this->sock, "\r\n.\r\n"); 
198         $this->smtp_debug(". [EOM]\n"); 
199         return $this->smtp_ok(); 
200     } 
201 
202     function smtp_ok() 
203     { 
204         $response = str_replace("\r\n", "", fgets($this->sock, 512)); 
205         $this->smtp_debug($response."\n"); 
206         if (!ereg("^[23]", $response))  
207         { 
208             fputs($this->sock, "QUIT\r\n"); 
209             fgets($this->sock, 512); 
210             $this->log_write("Error: Remote host returned \"".$response."\"\n"); 
211             return FALSE; 
212         } 
213         return TRUE; 
214     } 
215 
216     function smtp_putcmd($cmd, $arg = "") 
217     { 
218         if ($arg != "")  
219         { 
220             if($cmd=="")  
221             { 
222                 $cmd = $arg; 
223             } 
224             else 
225             { 
226                 $cmd = $cmd." ".$arg; 
227             } 
228         } 
229         fputs($this->sock, $cmd."\r\n"); 
230         $this->smtp_debug("> ".$cmd."\n"); 
231         return $this->smtp_ok(); 
232     } 
233 
234     function smtp_error($string) 
235     { 
236         $this->log_write("Error: Error occurred while ".$string.".\n"); 
237         return FALSE; 
238     } 
239 
240     function log_write($message) 
241     { 
242         $this->smtp_debug($message); 
243         if ($this->log_file == "") 
244         { 
245             return TRUE; 
246         } 
247         $message = date("M d H:i:s ").get_current_user()."[".getmypid()."]: ".$message; 
248         if (!@file_exists($this->log_file) || !($fp = @fopen($this->log_file, "a")))  
249         { 
250             $this->smtp_debug("Warning: Cannot open log file \"".$this->log_file."\"\n"); 
251             return FALSE;; 
252         } 
253         flock($fp, LOCK_EX); 
254         fputs($fp, $message); 
255         fclose($fp); 
256         return TRUE; 
257     } 
258 
259     function strip_comment($address) 
260     { 
261         $comment = "\([^()]*\)"; 
262         while (ereg($comment, $address))  
263         { 
264             $address = ereg_replace($comment, "", $address); 
265         } 
266         return $address; 
267     } 
268 
269     function get_address($address) 
270     { 
271         $address = ereg_replace("([ \t\r\n])+", "", $address); 
272         $address = ereg_replace("^.*<(.+)>.*$", "\1", $address); 
273         return $address; 
274     } 
275 
276     function smtp_debug($message) 
277     { 
278         if ($this->debug)  
279         { 
280             echo $message; 
281         } 
282     } 
283 
284 } 
285 ?>
View Code

  这是已经封装好的,我只在乎功能的实现,就暂时不鸟它了。然后进行sendmail代码的编写:

 1 <?php
 2   // 引入发送邮件类
 3   require("smtp.php"); 
 4   // 使用qq邮箱服务器
 5   $smtpserver = "smtp.qq.com";
 6   // qq邮箱服务器端口 
 7   $smtpserverport = 25;
 8   // 你的qq服务器邮箱账号
 9   $smtpusermail = "[email protected]";
10   // 收件人邮箱
11   $smtpemailto = "[email protected]";
12   // 你的邮箱账号(去掉@qq.com) SMTP服务器的用户帐号 
13   $smtpuser = "xxxxxxx"; 
14   // 你的邮箱密码 SMTP服务器的用户密码 
15   $smtppass = "xxxxxxx"; 
16   
17   // 邮件主题 
18   $mailsubject = "测试邮件发送";
19   // 邮件内容 
20   $mailbody = ‘test‘;
21   // 邮件格式(HTML/TXT,TXT为文本邮件 
22   $mailtype = "TXT";
23   // 这里面的一个true是表示使用身份验证,否则不使用身份验证. 
24   $smtp = new smtp($smtpserver, $smtpserverport, true, $smtpuser, $smtppass);
25   // 是否显示发送的调试信息 
26   $smtp->debug = TRUE;
27   //发送邮件
28   $smtp->sendmail($smtpemailto, $smtpusermail, $mailsubject, $mailbody, $mailtype); 
29 ?>

  这样就大功告成了,几乎几秒内就可以收到邮件,但是会输出一些错误信息,因为不影响功能的使用,暂时先抛之一边。窥了下smtp.php,发现里面尽是socket的函数,也难怪,smtp本来就是协议类的内容,只怪自己上学根本没学到网络tcp/ip一点内容,惭愧。


  本来暂时就这样了,but我是个很喜欢研究“实际应用"的人,首先想到的自然是大量发送垃圾邮件。还是因为不懂php,首先想到的是php中有没有如js的setTimeout函数,发现木有,只有个sleep函数,貌似是挂起服务器,不行。直接for循环呢?

 

1 for($i=0; $i<1000; $i++) {
2   sendmail();
3 }

 

but只能收到一封!为什么会这样,不造...

  直接在服务端对于现在的我看来是很难操作了,可以在客户端直接做循环向后台POST数据,应该是可行的,可是我不知道怎么POST,再想了下决定用ajax实现,循环做ajax向后台POST数据,其实就是邮件的内容,然后进行发送,ajax部分代码如下:

 

 1 <html>
 2   <head>
 3     <script src=‘http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.0.js‘></script>
 4     <script type="text/javascript">
 5       var a = [test1, test2, test3, test4, test5];
 6       for(var i=0; i<5; i++) {
 7         $.ajax({
 8           type: POST,
 9           url: http://127.0.0.1/test/test.php,
10           // dataType: ‘‘,
11           async: false,
12           data: {content:a[i]},
13           success: function(msg) {
14             alert(msg);
15           }
16         });
17       }
18     </script>
19   </head>
20   <body>
21   </body>
22 </html>

 

  直接运行这个html文件就行了,php部分通过$_POST[‘content‘]获取参数内容。貌似这里的回调就没什么用了,所以应该能直接用POST实现,这里的ajax貌似大材小用了,暂时还不知道如何直接POST实现。

  其实要实现大量发送垃圾邮件,还有个更简便的方法,直接写个用户脚本,直接定时重载即可~

 


 

  后续:我不明白为什么不能直接在后台循环发送,将sendmail写成了一个方法,写了如下脚本:

 

1 for($i=0; $i<10; $i++) {
2   echo "<script>console.log($i)</script>";
3   sendmail();
4 }

 

控制台输出0和1,并成功发送一封邮件。太诡异了,为什么发送一封邮件后不会往下执行?将for改成while(true)的死循环,也只能执行一次!留待以后观察。

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。