用户
 找回密码
 入住 CI 中国社区
搜索
查看: 2664|回复: 5
收起左侧

[中级] ci集成阿里云邮件推送

[复制链接]
发表于 2018-2-22 18:36:47 | 显示全部楼层 |阅读模式
本帖最后由 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);
    }

与大家分享,高手勿喷。


本版积分规则