首页 > 代码库 > 用php发邮件的简单实现

用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 = "xxxxxxx@qq.com";10   // 收件人邮箱11   $smtpemailto = "bigbigsunrise@foxmail.com";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)的死循环,也只能执行一次!留待以后观察。

 

用php发邮件的简单实现