iamrwang 发表于 2018-2-22 18:36:47

ci集成阿里云邮件推送

本帖最后由 iamrwang 于 2018-2-23 08:26 编辑

项目需求为客户发送电子邮件。于是申请阿里云邮件推送。阿里云邮件推送有三种邮件发送方式。这里使用api接口发送。于是根据阿里文档编写此发送类,与大家分享。(在使用前请正确配置阿里邮件推送)

libraries\alidm.php

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

/**
* @desc: 阿里云邮件推送Api
* @copyright 2018.02
*/

class Alidm {
   
    // 常量定义
    // DirectMail API 的服务接入地址
    const URL_DM = 'https://dm.aliyuncs.com';
    // const URL_DM = 'http://dm.aliyuncs.com';
    private $akeyid;
    private $keysecret;
    private $accountname;
   
    private $method = 'POST';
    private $signatureversion = '1.0';
    private $regionid = 'cn-hangzhou';
    private $version = '2015-11-23';
    private $signaturemethod= 'HMAC-SHA1';
    private $replytoaddress = 'true';
    private $addresstype = 1;
    private $clicktrace = 0;
   
    public function __construct($config='')
    {
      if (!empty($config))
      {
            $this->initialize($config);
      }
    }
   
    /**
   * @desc 初始化
   * @access public
   * @param $config array
    **/
    public function initialize($config = array())
    {
      if(isset($config['AccessKeyId']))
      {
            $this->akeyid = $config['AccessKeyId'];
      }
      if(isset($config['AccessKeySecret']))
      {
            $this->keysecret = $config['AccessKeySecret'];
      }
      if(isset($config['method']))
      {
            $this->method = $config['method'];
      }
      if(isset($config['AccountName']))
      {
            $this->accountname = $config['AccountName'];
            $this->addresstype = 1;
      }else{
            $this->accountname = '';
            $this->addresstype = 0;
      }
      if(isset($config['ReplyToAddress']))
      {
            $this->replytoaddress = $config['ReplyToAddress'];
      }
      if(isset($config['ClickTrace']))
      {
            $this->clicktrace = $config['ClickTrace'];
      }
    }
   
    /**
   * @desc 编码
   * @access private
   * @param $string 要编码的字符串
   * @param return string
    **/
    private function percentencode($string)
    {
      $string = urlencode($string);
      $string = preg_replace('/\+/', '%20', $string);
      $string = preg_replace('/\*/', '%2A', $string);
      $string = preg_replace('/%7E/', '~', $string);
      return $string;
    }
   
    /**
   * @desc 计算签名
   * @access private
   * @param $params 要计算签名的参数
   * @return string
    **/
    private function signature($params)
    {
      ksort($params);
      $queryString = '';
      foreach($params as $key => $value)
      {
            $queryString .= '&'.$this->percentencode($key).'='.$this->percentencode($value);
      }
      
      $stringToSign = $this->method.'&%2F&'.$this->percentencode(substr($queryString,1));
      $sign = base64_encode(hash_hmac('sha1', $stringToSign, $this->keysecret.'&', true));
      return $sign;
    }
   
    /**
   * @desc POST 请求
   * @access public
   * @param $params array post数据
   * @param $url string
   * @return array()
    **/
    public function curlpost($params,$url=self::URL_DM)
    {
      $headers = array(
            'Host'=>'dm.aliyuncs.com',
            'Content-Type'=>'application/x-www-form-urlencoded'
      );
      
      $ch = curl_init();
      curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
      //https request
      if (strlen($url) > 5 && strtolower(substr($url, 0, 5)) == "https")
      {
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
      }
      curl_setopt($ch, CURLOPT_URL, $url);
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
      curl_setopt($ch, CURLOPT_POST, true);
      curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
      curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
      curl_setopt($ch, CURLOPT_TIMEOUT, 5);

      $content = curl_exec($ch);
      curl_close($ch);
      $array = $this->xml2array($content);
      return $array;
    }
   
    /**
   * @desc 生成随机数
   * @access public
   * @param $len 长度
   * @return string
    **/
    public function get_nonce_string($len=32)
    {
      return substr(str_shuffle('abcdefghijklmnopqrstuvwxyz0123456789'),0,$len);
    }

    // 单一发信(触发邮件)接口
    public function single_send($to,$cont,$subject='',$alias='')
    {
      $params = array();
      // 公共请求参数
      // 返回值的类型,支持 JSON 与 XML.默认为 XML
      // $data['Format'] = 'JSON';
      // API 版本号, cn-hangzhou,则版本对应为 2015-11-23
      $params['Version'] = $this->version;
      // 阿里云颁发给用户的访问服务所用的密钥 ID
      $params['AccessKeyId'] = $this->akeyid;
      // 签名方式
      $params['SignatureMethod'] = $this->signaturemethod;
      // 请求的时间戳
      $params['Timestamp'] = gmdate('Y-m-d\TH:i:s\Z');
      // 签名算法版本
      $params['SignatureVersion'] = $this->signatureversion;
      // 唯一随机数
      $params['SignatureNonce'] = $this->get_nonce_string(8);
      // 机房信息
      $params['RegionId'] = $this->regionid;
      
      // 单一发信接口请求参数
      // 操作接口名
      $params['Action'] = 'SingleSendMail';
      // 管理控制台中配置的发信地址
      $params['AccountName'] = $this->accountname;
      // 使用管理控制台中配置的回信地址
      $params['ReplyToAddress'] = $this->replytoaddress;
      // 0 为随机账号;1 为发信地址
      $params['AddressType'] = $this->addresstype;
      // 目标地址,多个 email 地址可以用逗号分隔,最多100个地址
      $params['ToAddress'] = '';
      if(is_array($to))
      {
            foreach($to as $val)
            {
                if($this->is_email($val))
                {
                  $data['ToAddress'] .= ','.$val;
                }
            }
            $params['ToAddress'] = ltrim($data['ToAddress'],',');
      }else{
            $params['ToAddress'] = $this->is_email($to)?$to:'';
      }
      // 发信人昵称
      if($alias)
      {
            $params['FromAlias'] = $alias;
      }
      // 邮件主题
      if($subject)
      {
            $params['Subject'] = $subject;
      }
      // 邮件 html 正文
      $params['HtmlBody'] = $cont;
      // 取值范围 0~1: 1 为打开数据跟踪功能
      if($this->clicktrace)
      {
            $params['ClickTrace'] = 1;
      }
      if($params['ToAddress'])
      {
            // 签名结果串
            $signature = $this->signature($params);
            $params['Signature'] = $signature;
            /*
            $data = '';
            foreach($params as $k=>$v)
            {
                $data .= '&'.$k.'='.$v;
            }
            $res = $this->curlpost(substr($data,1));
            */
            $res = $this->curlpost($params);
      }else{
            $res = FALSE;
      }
      return $res;
    }
   
    // xml 转数组
    protected function xml2array($xml)
    {
      $array = array();
      $tmp = null;
      try{
            $tmp = (array) simplexml_load_string($xml);
      }catch(Exception $e){}
      if($tmp && is_array($tmp)){
            foreach ( $tmp as $k => $v) {
                $array[$k] = (string) $v;
            }
      }
      return $array;
    }
   
    /**
   * Valid Email
   *
   * @param    string
   * @return    bool
   */
    protected function is_email($str)
    {
      if (function_exists('idn_to_ascii') && sscanf($str, '%[^@]@%s', $name, $domain) === 2)
      {
            $str = $name.'@'.idn_to_ascii($domain);
      }

      return (bool) filter_var($str, FILTER_VALIDATE_EMAIL);
    }
   
}

使用方法:
在 config/email.php中定义配置

$config['dmconf'] = array(    'AccessKeyId'    =>    '阿里AccessKeyId',
                            'AccessKeySecret'=>    '阿里AccessKeySecret',
                            'method'      =>    'POST',
                            'AccountName'    =>    '发件地址',
                            // 'ReplyToAddress'=>    TRUE,
                            'ClickTrace'    =>    1
                  );
   
邮件推送:

    // api 推送
    public function api_mail()
    {
      $emailto = 'xxxxxxxx@163.com';
      $mailcontent = '这是一封由阿里云邮件推送服务发送的测试邮件,邮件生成时间:'.gmdate('Y-m-d H:i:s');
      $subject = '邮件推送测试';
      $alias = '【名称】';
      $this->config->load('email', TRUE);
      $config = $this->config->item('dmconf','email');
      $this->load->library('alidm',$config);
      $res = $this->alidm->single_send($emailto,$mailcontent,$subject,$alias);

      var_dump($res);
    }

与大家分享,高手勿喷。


页: [1]
查看完整版本: ci集成阿里云邮件推送