因为一个项目中需要用邮件通知的功能,在网上搜了别人写的发邮件函数,要么太长,要么根本用不了。。索性自己写了一个,实现了基本的邮箱发送功能,并且可以发送多个附件。
完整的代码和使用方法如下,因为暂时不需要用到向多方发送、抄送、密送功能,所以这里面并没有写这些,不过这些都很简单,后面如果用到我会更新这篇文章的代码。
<?php
/***********************************
* PHP使用SMTP发送邮件
* Author: treemonster
* 使用中有任何问题可在下面留言
------------------------------------
* 使用方式:
try{
new sendmail(
'xxxx@qq.com', // 接收者邮箱
'yyyy@qq.com', // 发送者邮箱
'xxxx', // 发送者邮箱的密码
'xxxx', // 邮件标题
'helo<h1>sb</h1>', // 邮件html内容
array('a.php','b.jpg','c.rar') // 附件地址,可以多个,大小没有要求
);
}catch(Exception $e){
// 如果发送失败会报错,然后你可以随便怎么搞了
echo $e->getMessage();
}
************************************/
class sendmail{
private $cli;
private function read(){
$r=fgets($this->cli);
// 除了1,2,3开头的状态码均为错误码
if(false===strpos('123',$r[0]))throw new Exception('Error: '.$r);
return $r;
}
private function send($data){
fwrite($this->cli,$data);
}
function __construct($to,$from,$password,$subject,$htmlbody,$attachment=null){
$f=explode('@',$from);
$user=$f[0];
$host='smtp.'.$f[1];
$subject=str_replace("\r\n",' ',$subject);
// 连接smtp服务器
$cli=fsockopen($host,25);
$this->cli=&$cli;
// boundary
$boundary='----='.uniqid();
// 基本应答命令
foreach(array(
'HELO SB',
'AUTH LOGIN',
base64_encode($user),
base64_encode($password),
'MAIL FROM:<'.$from.'>',
'RCPT TO: <'.$to.'>',
'DATA'
) as $c){
$this->read();
$this->send($c."\r\n");
} $this->read();
// 发送邮件头部
$this->send(
'From: '.$from."\r\n".
'To: '.$to."\r\n".
'Subject: '.$subject."\r\n".
'Content-Type: multipart/mixed;boundary="'.$boundary.'"'."\r\n".
'MIME-Version: 1.0'."\r\n\r\n\r\n");
// 内容里的boundary比头部的多两个横线
$boundary='--'.$boundary;
// 发送邮件内容
$this->send(
$boundary."\r\n".
'Content-Transfer-Encoding: base64'."\r\n".
'Content-Type: text/html; charset=utf-8'."\r\n".
"\r\n\r\n".
base64_encode($htmlbody)."\r\n".
$boundary."\r\n");
// 发送附件
if($attachment===null);else for($i=0;$i<count($attachment);$i++){
$filename=$attachment[$i];
$this->send(
$boundary."\r\n".
'Content-Transfer-Encoding: base64'."\r\n".
'Content-Type: application/octet-stream;'."\r\n".
'Content-Disposition: attachment; filename="'.str_replace(dirname($filename).'/','',$filename).'"'."\r\n".
"\r\n\r\n");
// 不使用file_get_contents,因为有时候附件会很大
$f=fopen($filename,'rb');
while(!feof($f))
// 每次读取长度为3的整数倍,因为base64编码是以3为单位分段的
$this->send(base64_encode(fread($f,5130)));
$this->send("\r\n".$boundary."\r\n");
}
// 发送内容结束标志
$this->send(".\r\n");
$this->read();
fclose($cli);
}
}
大部分原理在代码的注释中都写了。发邮件协议比较简单,全局是一问一答的模式。实现功能主要是注意规定的格式,应答完成要发送\r\n,需要base64编码的内容不能发原文,boundary中间数据的\r\n不能漏掉等。
相关文档
暂无
随便看看
畅言模块加载中