展开目录
PHP使用SMTP发送邮件
phpsmtp邮件
X
陈尼玛的博客
记录开发生涯的踩坑经历,用时间来验证成长
加载中

因为一个项目中需要用邮件通知的功能,在网上搜了别人写的发邮件函数,要么太长,要么根本用不了。。索性自己写了一个,实现了基本的邮箱发送功能,并且可以发送多个附件。

完整的代码和使用方法如下,因为暂时不需要用到向多方发送、抄送、密送功能,所以这里面并没有写这些,不过这些都很简单,后面如果用到我会更新这篇文章的代码。

<?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不能漏掉等。

相关文档

暂无

随便看看

  1. 记一次nodejs内存泄漏的排查经历

  2. css3自定义滚动条样式

  3. mac ssh透过代理连接

  4. sass变量和继承类写法

  5. 树莓派实现用pi用户自动登录

  6. html5 全屏代码

  7. mongodb 批量修改字段语句

  8. 单页应用的单向数据流的流程图

  9. cdn资源列表

  10. webpack使用外部资源

  11. putty使用http代理连接服务器

  12. git配置服务端支持http认证

  13. git记住/删除账号密码

  14. ssl 证书生成方式

  15. 把树莓派的存储空间拓展到整张TF卡中

  16. centos查看最近一次的开机时间

  17. 树莓派配置收发邮件

  18. 感谢beego陪伴我度过那不靠谱的半年

畅言模块加载中