天天看點

ThinkPHP5結合phpmailer發送郵件

1.安裝composer

2.設定composer為全局變量

3.進入項目目錄

4.在指令行執行:composer require phpmailer/phpmailer

5.建立Test.controller控制器檔案,代碼如下:

<?php
/**
 * Created by PhpStorm.
 * User: dyane
 * Date: 2019/3/29
 * Time: 16:38
 */

namespace app\system_admin\controller;

use think\Request;

class Test
{
    /**
     * 郵件發送頁面
     * @return mixed
     */
    public function index()
    {
        return view('email/index');
    }

    /**
     * 發送郵件
     */
    public function send()
    {
        if($this->request->isPost()) {
            $param = $this->request->param();
            //判斷收件人
            if (empty($param['addressee'])) {
                return json(['code' => 400, 'msg' => '收件人位址不能為空!']);
                die;
            }
            //判斷郵件主題和内容必須存在一個
            if (empty($param['title']) && empty($param['content'])) {
                return json(['code' => 400, 'msg' => '主題和内容必須填寫一個!']);
                die;
            }
            //擷取收件人位址
            $addressee = $param['addressee'];
            //驗證郵箱
            $addressee = $this->checkEmailStr($addressee);
            //擷取主題或内容
            if (!empty($param['title'])) {
                $title = htmlspecialchars($param['title']);
            } else {
                $title = ' ';
            }//空格不能去,否則發送失敗
            if (!empty($param['content'])) {
                $content = $param['content'];
            } else {
                $content = ' ';
            }//空格不能去,否則發送失敗
            //擷取抄送人位址
            if (!empty($param['copyperson'])) {
                $copyerArray = $this->checkEmailStr($param['copyperson']);
            } else {
                $copyerArray = '';
            }
            //擷取密送人位址
            if (!empty($param['secretagent'])) {
                $sercreterArray = $this->checkEmailStr($param['secretagent']);
            } else {
                $sercreterArray = '';
            }
            //擷取附件
            if (!empty($param['files_list'])) {
                $filesArray = $this->checkFiles($param['files_list']);
            } else {
                $filesArray = '';
            }
            $res = $this->sendEmail($addressee,$copyerArray,$sercreterArray,$filesArray,$title,$content);
            //回報發送結果
           if($res){
                 if (!empty($filesArray)) {
                    $this->deleteOldEmaileFiles($filesArray);
                }
                echo json_encode(['code' => 200, 'msg' => '發送成功!']);die;
            }else{
                echo json_encode(['code' => 400, 'msg' => '發送失敗!']);die;
            }
        }
    }
    /**
     * 發送郵件
     * @param $addressee
     * @param $copyerArray
     * @param $sercreterArray
     * @param $filesArray
     * @param $title
     * @param $content
     */
    protected function sendEmail($addressee,$copyerArray,$sercreterArray,$filesArray,$title,$content)
    {
        //使用發送郵件類
        $mail = new EmailYX();
        //設定收件人
        $mail->setManyAddressee($addressee);

        if(!empty($copyerArray)){$mail->setManyCC($copyerArray);}

        if(!empty($sercreterArray)){$mail->setManyBCC($sercreterArray);}

        if(!empty($filesArray)){$mail->setManyAttachment($filesArray);}
        //設定主題和内容
        $mail->setContent($title,$content);
        //發送郵件
        $res = $mail->send();
        return $res;
    }

    /**
     * 發送成功之後删除附件檔案
     * @param $filesArray
     */
    protected function deleteOldEmaileFiles($filesArray)
    {
            foreach ($filesArray as $key => $value){
                $path = ROOT_PATH . 'public'.$value;
                if(file_exists($path)){
                    unlink($path);
                }
            }
    }

    /**
     * 驗證郵箱是否正确
     * @param $str
     */
    protected function checkEmailStr($emailStr)
    {
        $toArray = explode(',',$emailStr);
        $res = $this->checkManyEmail($toArray);
        return $res;
    }
    /**
     * 判斷多組字元竄郵箱是否有不正确的郵箱存在
     * @param $toArray
     * @return bool
     */
    protected function checkManyEmail($toArray)
    {
        foreach ($toArray as $key => $value){
            $check = $this->checkEmail($value);
            if(!$check){unset($toArray[$key]);}
        }
        return $toArray;
    }
    /**
     * 正則驗證郵箱是否合法
     * @param $email
     * @return false|int
     */
    protected function checkEmail($email)
    {
//        $pregEmail='/^[a-zA-Z0-9]+([-_.][a-zA-Z0-9]+)*@([a-zA-Z0-9]+[-.])+([a-z]{2,5})$/ims';
        $pregEmail = '/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,})$/';
        $res = preg_match($pregEmail,$email);
        return $res;
    }
    /**
     * 處理郵件附件字元串
     * @param $filesStr
     * @return array
     */
    protected function checkFiles($filesStr)
    {
        $filesStr = trim($filesStr);
        $filesStr = rtrim($filesStr,',');
        $res = explode(',',$filesStr);
        return $res;
    }
}
           

6.封裝設定郵件發送參數類Email.controller檔案,代碼如下:

<?php
/**
 * Created by PhpStorm.
 * User: dyane
 * Date: 2019-03-21
 * Time: 10:10
 */

namespace app\system_admin\controller;

use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
vendor('autoload.php');

class Email
{
    const SMTPDebug  = 0;
    const HOST       = 'smtp.qq.com';
    const USERNAME   = '你的QQ号@qq.com';
    const PASSOWRD   = 'SMTP授權碼,非QQ郵箱密碼';
    const CHARSET    = 'UTF-8';
    const SMTPAUTH   = true;
    const ISHTML     = true;
    const SMTPSECURE = 'ssl';
    const PORT       = 465;
    static $addressee = array();
    static $sender    = array('a'=>'你的QQ号@qq.com','n'=>'測試系統郵件');
    static $cc        = array();
    static $bcc       = array();
    static $attachment= array();
    static $title     = '';
    static $body      = '';
    static $altBody   = '';
    private $mail     = null;

    function __construct()
    {
        $this->mail = new PHPMailer();
    }

    //初始化參數
    public function start()
    {
        $this->mail->SMTPDebug   = self::SMTPDebug;
        $this->mail->Host        = self::HOST;
        $this->mail->CharSet     = self::CHARSET;
        $this->mail->SMTPAuth    = self::SMTPAUTH;
        $this->mail->Username    = self::USERNAME;
        $this->mail->Password    = self::PASSOWRD;
        $this->mail->SMTPSecure  = self::SMTPSECURE;
        $this->mail->Port        = self::PORT;
        if(self::SMTPSECURE == 'ssl'){
            $this->mail->SMTPOptions = array(
                'ssl' => array(
                    'verify_peer' => false,
                    'verify_peer_name' => false,
                    'allow_self_signed' => true
                )
            );
        }
        $this->mail->isHTML(self::ISHTML);
    }

    //發送人
    public function setSender($address,$senderName = '')
    {
        self::$sender['a'] = $address;
        self::$sender['n'] = $senderName;
    }

    //收件人回複的位址
    public function setReplyAddress($address = '', $replayName = '')
    {
        self::$sender['a'] = $address;
        self::$sender['n'] = $replayName;
    }

    //單個接收人
    public function setAddressee($address,$recName = '')
    {
        call_user_func_array([$this, 'setAddress'],['addressee',$address, $recName]);
    }

    //多個接收人
    public function setManyAddressee($array)
    {
        array_walk($array,function($v, $k){
            $this->setAddressee($v);
        });
    }

    //抄送單個
    public function setCC($address = '', $name = '')
    {
        call_user_func_array([$this, 'setAddress'],['cc',$address, $name]);
    }

    //抄送多個
    public function setManyCC($array)
    {
        array_walk($array,function($v, $k){
            $this->setCC($v);
        });
    }

    //暗抄送單個
    public function setBCC($address = '', $name = '')
    {
        call_user_func_array([$this, 'setAddress'],['bcc',$address, $name]);
    }

    //暗抄送單個
    public function setManyBCC($array)
    {
        array_walk($array,function($v, $k){
            $this->setBCC($v);
        });
    }

    //附件單個
    public function setAttachment($address, $newName = '')
    {
        call_user_func_array([$this, 'setAddress'],['attachment',$address, $newName]);
    }

    //附件多個
    public function setManyAttachment($array)
    {
        array_walk($array,function($v, $k){
            $this->setAttachment($v);
        });
    }

    public function setAddress($param, $address, $name)
    {
        array_push(self::${$param}, [
                'a'=>$address,'n'=>$name
            ]
        );
    }

    public function setContent($title = '', $body='', $table = '', $altBody='')
    {
        self::$title     = $title;
        if($table) $body = $body.'<br/>'.$table;
        self::$body      = $body;
        self::$altBody   = $altBody;
    }

    //發送郵件
    public function send()
    {
        $res = false;
        try {
            $this->mail->isSMTP();

            $this->start();

            $this->mail->setFrom(self::$sender['a'], self::$sender['n']);
            $this->mail->addReplyTo(self::$sender['a'], self::$sender['n']);

            $this->addAddress(self::$addressee,'addAddress');
            $this->addAddress(self::$bcc,'addBCC');
            $this->addAddress(self::$cc,'addCC');
            $this->addAddress(self::$attachment,'addAttachment');
            $this->mail->Subject = self::$title;
            $this->mail->Body    = self::$body;
            $this->mail->AltBody = self::$altBody;
            $result = $this->mail->send();
            $this->mail->isSMTP();
            $result && $res = true;
        }catch (Exception $e){
            // YXLog::error('Mailer Error: ' . $this->mail->ErrorInfo);
        }
        return $res;
    }

    public function addAddress($address,$func)
    {
        foreach ($address as $item){
            $item['a'] && $this->mail->{$func}($item['a'], $item['n']);
        }
    }

    public function setTable($th = array(), $data = array(), $title = '')
    {
        $table_data = '<table  cellpadding="2" cellspacing="0" style="font-size: 12px;">';
        $title && $table_data .= '<caption>'.$title.'</caption>';
        $table_data .= $this->setTh($th);
        $table_data .= $this->setTd($data);
        $table_data .= '</table>';
        return $table_data;
    }

    public function setTd($td = array())
    {
        $data = '';
        foreach ($td as $item){
            $data .= '<tr>';
            foreach ($item as $value){
                $data .= '<td>'.$value.'</td>';
            }
            $data .= '</tr>';
        }
        return $data;
    }

    public function setTh($th = array())
    {
        $data = '<tr>';
        foreach ($th as $item){
            $data .='<th>'.$item.'</th>';
        }
        $data .= '</tr>';

        return $data;
    }

}

           

7.前段頁面代碼,前端本人使用的是layui架構:

{include file='common/head'}
<div style="overflow-x: hidden;width: 96%;margin: auto;padding-top: 1rem;">
    <blockquote class="layui-elem-quote"><span>測試子產品&nbsp;&nbsp;&nbsp;&nbsp;郵件發送 (<span style="color: red;margin-right: 0.2rem;font-size: 20px;">*</span>為必填  |  多個郵箱之間用","号隔開)</span></blockquote>

    <div class="demoTable layui-form" action="" method="post" style="margin-top: 3rem">
        <div class="layui-form-item">
            <label class="layui-form-label"><span style="color: red;margin-right: 0.2rem;font-size: 20px">*</span>收件人</label>
            <div class="layui-input-block">
                <input type="text"  lay-verify="required" name="addressee" placeholder="請輸入收件人郵箱"  autocomplete="off" class="layui-input">
                <button class="layui-btn layui-btn-radius chao" style="margin-top:0.5rem">抄送</button>
                <button class="layui-btn layui-btn-radius layui-btn-normal mi" style="margin-top:0.5rem">密送</button>
                        
            </div>
        </div>
        <div class="layui-form-item input-chao" style="display: none">
            <label class="layui-form-label">抄送人</label>
            <div class="layui-input-block">
                <input type="text" name="copyperson" placeholder="請輸入抄送人郵箱" autocomplete="off" class="layui-input">
            </div>
        </div>
        <div class="layui-form-item input-mi" style="display: none;">
            <label class="layui-form-label">密送人</label>
            <div class="layui-input-block">
                <input type="text" name="secretagent" placeholder="請輸入密送人郵箱" autocomplete="off" class="layui-input">
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label">主題</label>
            <div class="layui-input-block">
                <input type="text" name="title"  placeholder="請輸入郵件主題" autocomplete="off" class="layui-input">
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label">附件</label>
            <div class="layui-input-block">
                <blockquote class="layui-elem-quote layui-quote-nm" style="margin-top: 10px;">
                    <div id="uploadImg" class="layui-upload">
                        <button type="button" class="layui-btn" id="upload">選擇檔案</button>
                        <div class="layui-upload-list">
                            <table class="layui-table" style="text-align: center;">
                                <thead>
                                <tr>
                                    <th style="text-align: center;">檔案名</th>
                                    <th style="text-align: center;">大小</th>
                                    <th style="text-align: center;">狀态</th>
                                    <th style="text-align: center;">操作</th>
                                </tr>
                                </thead>
                                <tbody id="imgList"></tbody>
                            </table>
                        </div>
                        <button type="button" class="layui-btn" id="startUpload">開始上傳</button>
                    </div>
                    <input type="text" name="files_list" id="imgInput" style="display: none;">
                </blockquote>
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label">郵件内容</label>
            <div class="layui-input-block" style="width: 1220px;height: 300px">
                <textarea id="demo" name="content" lay-verify="content" lay-verify="required"></textarea>
            </div>
        </div>
        <div class="layui-form-item" style="margin-top: 2rem">
            <div class="layui-input-block">
                <button class="layui-btn" lay-submit="" lay-filter="demo1">發送</button>
            </div>
        </div>
    </div>


</div>
{include file='common/footer'}
<script>
    layui.use(['table', 'form', 'element', 'upload', 'layedit'], function () {
        var table = layui.table;
        var form = layui.form;
        var element = layui.element;
        var $ = layui.jquery;
        var upload = layui.upload;
        var layedit = layui.layedit;
        // //建立一個編輯器
        layedit.set({
            uploadImage:{
                url:'{:url("Upload/editUpload")}',
                type:'post'
            }
        });
        var editIndex = layedit.build('demo', {
            tool: [
                'strong' //加粗
                ,'italic' //斜體
                ,'underline' //下劃線
                ,'del' //删除線

                ,'|' //分割線

                ,'left' //左對齊
                ,'center' //居中對齊
                ,'right' //右對齊
                ,'image'
            ],
        });
        //
        //自定義驗證規則
        form.verify({
            content: function(value){
                layedit.sync(editIndex);
            }
        });
        //多檔案清單示例
        var demoListView = $('#imgList');
        var totalArray = new Array();
        var uploadInst = upload.render({
            elem: '#upload' //綁定元素
            , url: '{:url("Upload/file_images")}' //上傳接口
            , accept: 'file'  // 允許上傳的檔案類型
            // , acceptMime: 'image/jpg,image/png'   // (隻支援jpg和png格式,多個用逗号隔開),
            , size: 5120        // 最大允許上傳的檔案大小  機關 KB
            , auto: false //選擇檔案後不自動上傳
            , bindAction: '#startUpload' //指向一個按鈕觸發上傳
            , multiple: true   // 開啟多檔案上傳
            , number: 6    //  同時上傳檔案的最大個數
            , choose: function (obj) {
                console.log(obj)
                var files = this.files = obj.pushFile(); //将每次選擇的檔案追加到檔案隊列
                var arr = Object.keys(files);
                totalArray = totalArray.concat(arr);
                // 檢查上傳檔案的個數
                if (totalArray.length <= 6) {
                    //讀取本地檔案
                    obj.preview(function (index, file, result) {
                        var tr = $(['<tr id="upload-' + index + '">'
                            , '<td>'+file.name+'</td>'
                            , '<td>' + (file.size / 1014).toFixed(1) + 'kb</td>'
                            , '<td>等待上傳</td>'
                            , '<td>'
                            , '<button class="layui-btn demo-reload layui-hide">重傳</button>'
                            , '<button class="layui-btn layui-btn-danger demo-delete">删除</button>'
                            , '</td>'
                            , '</tr>'].join(''));

                        //單個重傳
                        tr.find('.demo-reload').on('click', function () {
                            obj.upload(index, file);
                        });

                        //删除
                        tr.find('.demo-delete').on('click', function () {
                            delete files[index]; //删除對應的檔案
                            tr.remove();
                            uploadListIns.config.elem.next()[0].value = ''; //清空 input file 值,以免删除後出現同名檔案不可選
                        });

                        demoListView.append(tr);
                    });
                } else {
                    // 超出上傳最大檔案
                    layer.msg("上傳檔案最大不超過6個")
                }

            }
            , done: function (res, index, upload) {
                if (res.code == 0) { //上傳成功
                    // 上傳成功後将圖檔路徑拼接到input中,多個路徑用","分割
                    var inputVal = document.getElementById("imgInput").value;
                    var valData = "";
                    if (inputVal) {
                        valData = inputVal + "," + res.data.src;
                    } else {
                        valData = res.data.src;
                    }
                    document.getElementById("imgInput").value = valData;
                    var tr = demoListView.find('tr#upload-' + index)
                        , tds = tr.children();
                    tds.eq(2).html('<span style="color: #5FB878;">上傳成功</span>');
                    tds.eq(3).html(''); //清空操作
                    return delete this.files[index]; //删除檔案隊列已經上傳成功的檔案

                }
                this.error(index, upload);
            }
            , error: function (index, upload) {
                var tr = demoListView.find('tr#upload-' + index)
                    , tds = tr.children();
                tds.eq(2).html('<span style="color: #FF5722;">上傳失敗</span>');
                tds.eq(3).find('.demo-reload').removeClass('layui-hide'); //顯示重傳
            }
        });
        var url='{:url("EmailSend/send")}';
        form.on('submit(demo1)', function(data){
            layer.msg('郵件正在發送中,請稍後.....',{time:2000},function(){
                    $.post(url,data.field,function (obj) {
                        if(obj.code==200){
                            parent.layer.msg(obj.msg, {icon: 6,time: 1000});
                            window.location.reload();
                        }
                        if(obj.code==400){
                            parent.layer.msg(obj.msg, {icon: 5,time: 1000});
                        }
                    },"JSON");
                })
            
        });
        //抄送人、密送人input框顯示
        $('.chao').click(function(){
            $('.input-chao').css('display','block');
            $('.chao').css('display','none');
        })
        //抄送人、密送人input框顯示
        $('.mi').click(function(){
            $('.input-mi').css('display','block');
            $('.mi').css('display','none');
        })
    });
</script>
</body>
</html>