首页 > 代码库 > 用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 ?>
这是已经封装好的,我只在乎功能的实现,就暂时不鸟它了。然后进行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发邮件的简单实现