计算机网络/计算机科学与应用/系统/运维/开发

ThinkPHP5.1 phpmailer发送邮件

一、phpmailer下载

https://packagist.org/packages/phpmailer/phpmailer

composer require phpmailer/phpmailer

image.png


image.png


安装完成后,项目vendor目录下会生成phpmailer/phpmailer文件夹,同时 Composer 会自动加载类库,无需手动引入文件,直接在代码中使用命名空间即可。


二、封装通用邮件发送类

在application\common\lib\目录下封装邮件工具类(自动加载、全局可用)包含基础配置、核心发送方法、支持自定义收件人、主题、内容附件等。


创建工具类:

application/common/lib/Email.php 


<?php
namespace app\common\lib;
// 引入PHPMailer核心命名空间(Composer自动加载,无需手动require)
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;
/**
 * ThinkPHP5.1 PHPMailer邮件发送工具类
 * 支持:SMTP加密、多收件人、HTML内容、附件发送、抄送/密送
 */
class Email
{
    // 邮件发送核心方法
    public static function send($to, $subject, $content, $attach = [], $cc = [], $bcc = [])
    {
        // 1. 初始化PHPMailer实例,true表示开启异常处理(推荐)
        $mail = new PHPMailer(true);
        try {
            // 2. 服务器配置(关键!根据自己的邮箱SMTP信息修改)
            $mail->SMTPDebug = SMTP::DEBUG_OFF; // 调试模式:OFF=关闭(生产环境)、SERVER=服务器信息、CLIENT=客户端信息
            $mail->isSMTP(); // 使用SMTP协议发送
            $mail->Host       = 'smtp.qq.com'; // 邮箱SMTP服务器地址(例:163邮箱=smtp.163.com,QQ邮箱=smtp.qq.com)
            $mail->SMTPAuth   = true; // 开启SMTP身份验证
            $mail->Username   = '2065646680@qq.com'; // 发件人邮箱账号
            $mail->Password   = 'urikxzrimckwcecb'; // 发件人邮箱授权码(不是登录密码!重要!)
            $mail->SMTPSecure = 'ssl'; // 加密方式:SSL(常用)/TLS,根据邮箱要求选择
            $mail->Port       = 465; // 对应加密方式的端口:SSL=465,TLS=587(需与SMTPSecure匹配)
            // 3. 发件人信息
            $mail->setFrom('2065646680@qq.com', '主邮件'); // 发件人邮箱(与Username一致)、发件人昵称(自定义,如“XX系统”)
            $mail->CharSet    = 'UTF-8'; // 设置邮件编码,解决中文乱码(必须!)
            // 4. 收件人配置(支持单个/多个收件人)
            if (is_string($to)) {
                $to = explode(',', $to); // 单个收件人直接转数组,多收件人用逗号分隔(例:a@163.com,b@qq.com)
            }
            foreach ($to as $email) {
                $mail->addAddress(trim($email)); // 添加收件人,trim()去除空格避免错误
            }
            // 5. 抄送/密送(可选,按需启用)
            if (!empty($cc)) {
                $cc = is_string($cc) ? explode(',', $cc) : $cc;
                foreach ($cc as $email) {
                    $mail->addCC(trim($email)); // 抄送
                }
            }
            if (!empty($bcc)) {
                $bcc = is_string($bcc) ? explode(',', $bcc) : $bcc;
                foreach ($bcc as $email) {
                    $mail->addBCC(trim($email)); // 密送
                }
            }
            // 6. 附件配置(可选,支持单个/多个附件)
            if (!empty($attach)) {
                $attach = is_string($attach) ? [$attach] : $attach;
                foreach ($attach as $filePath) {
                    // 验证附件文件是否存在且可读
                    if (is_file($filePath) && is_readable($filePath)) {
                        $mail->addAttachment($filePath); // 添加附件(可传第二个参数自定义附件名称)
                    } else {
                        throw new \Exception("附件不存在或不可读:{$filePath}");
                    }
                }
            }
            // 7. 邮件内容配置
            $mail->isHTML(true); // 设置邮件内容为HTML格式(支持富文本、图片等),false为纯文本
            $mail->Subject = $subject; // 邮件主题
            $mail->Body    = $content; // HTML邮件内容
            $mail->AltBody = strip_tags($content); // 纯文本备用内容(当收件人邮箱不支持HTML时显示)
            // 8. 执行发送
            $mail->send();
            return [
                'code' => 1,
                'msg'  => '邮件发送成功'
            ];
        } catch (Exception $e) {
            // 捕获PHPMailer自身异常(邮件发送相关错误)
            return [
                'code' => 0,
                'msg'  => 'PHPMailer错误:' . $mail->ErrorInfo // ErrorInfo是PHPMailer内置的错误信息方法
            ];
        } catch (\Exception $e) {
            // 捕获自定义异常/其他全局异常(如附件不存在)
            return [
                'code' => 0,
                'msg'  => '系统错误:' . $e->getMessage()
            ];
        }
    }
}


常见邮箱服务器:

image.png


授权码不是登录密码!

所有主流邮箱(163/QQ/ 新浪等)为了安全,禁止直接使用登录密码进行 SMTP 验证,必须先开启「SMTP 服务」并获取「授权码」,步骤如下(通用流程):

登录发件人邮箱,进入「设置」→「POP3/SMTP/IMAP」;

开启「SMTP 服务」(部分邮箱需开启 POP3);

验证身份(手机短信 / 密保),获取授权码;

将代码中的Password值改为该授权码(不是邮箱登录密码!)。


三、场景使用

在Index.php控制器中

(单人收件+纯文本)

<?php
namespace app\index\controller;
use  think\Controller;
use app\common\lib\Email; // 引入邮件工具类
class Index  extends Controller
{
public function sendEmail()
    {
        $to = 'm18328321035@163.com '; // 收件人邮箱
        $subject = 'ThinkPHP5.1 PHPMailer测试邮件'; // 邮件主题
        $content = '这是一封由ThinkPHP5.1集成PHPMailer发送的纯文本测试邮件,请注意查收!'; // 纯文本内容
        // 调用发送方法
        $result = Email::send($to, $subject, $content);
        if ($result['code'] == 1) {
            return json($result); // 返回成功
        } else {
            return json($result, 400); // 返回失败,状态码400
        }
    }
}


多人收件+富文本

public function sendHtmlEmail()
{
    $to = 'a@163.com,b@qq.com,c@sina.com'; // 多收件人,逗号分隔
    $subject = '【XX系统】您的账号登录提醒';
    // HTML富文本内容(支持CSS、图片、链接)
    $content = <<<HTML
        <div style="width: 600px; margin: 0 auto; padding: 20px; border: 1px solid #eee;">
            <h3 style="color: #333;">账号登录提醒</h3>
            <p>尊敬的用户,您好!</p>
            <p>您的账号于 <span style="color: red; font-weight: bold;">2026-02-02 15:30</span> 在异地登录,若非本人操作,请及时修改密码:<a href="https://xxx.com/reset">点击修改</a></p>
            <p style="color: #999; margin-top: 30px;">此邮件为系统自动发送,请勿回复!</p>
        </div>
HTML;

    $result = Email::send($to, $subject, $content);
    dump($result); // TP5.1内置dump方法,打印结果
}


带附件发送邮件

public function sendAttachEmail()
{
    $to = 'recipient@163.com';
    $subject = '【XX系统】您的月度报表已发送';
    $content = '您好!您的2026年1月月度报表已作为附件发送,请查收!';

    // 附件配置:支持单个(字符串)/多个(数组),使用TP5.1框架常量拼接绝对路径
    $attach = [
        ROOT_PATH . 'public' . DS . 'file' . DS . '202601报表.xlsx', // 报表文件
        ROOT_PATH . 'runtime' . DS . 'export' . DS . '202601数据.pdf' // 数据文件
    ];
    // 单个附件直接传字符串:$attach = ROOT_PATH . 'public/file/202601报表.xlsx';

    $result = Email::send($to, $subject, $content, $attach);
    dump($result);
}


带抄送、密送 + html + 附件

public function sendFullEmail()
{
    $to = 'main@qq.com'; // 主收件人
    $cc = 'cc1@163.com,cc2@sina.com'; // 抄送(多地址逗号分隔)
    $bcc = ['bcc1@qq.com', 'bcc2@163.com']; // 密送(数组格式)
    $subject = '【项目会议】会议纪要及资料';
    $content = '<h3>项目会议纪要</h3><p>本次会议讨论内容如下:...</p>';
    $attach = ROOT_PATH . 'public/file/会议纪要.docx'; // 单个附件

    // 调用时传入抄送、密送参数
    $result = Email::send($to, $subject, $content, $attach, $cc, $bcc);
    dump($result);
}


四、生产环境下配置

application/common/config/email.php

<?php
return [
    'host'       => 'smtp.163.com',
    'username'   => 'your_email@163.com',
    'password'   => 'your_auth_code',
    'smtp_secure'=> 'SSL',
    'port'       => 465,
    'from_email' => 'your_email@163.com',
    'from_name'  => 'XX系统'
];


修改工具类下的配置信息:

// 替换原硬编码配置
$config = config('email'); // 读取配置文件
$mail->Host       = $config['host'];
$mail->Username   = $config['username'];
$mail->Password   = $config['password'];
$mail->SMTPSecure = $config['smtp_secure'];
$mail->Port       = $config['port'];
$mail->setFrom($config['from_email'], $config['from_name']);


异步发送(解决邮件发送阻塞请求)

public function sendEmail()
{
    // 先返回成功结果,断开前端连接
    fastcgi_finish_request();
    // 后续执行邮件发送,不阻塞前端
    $to = 'recipient@qq.com';
    $subject = '异步测试邮件';
    $content = '这是一封异步发送的邮件';
    Email::send($to, $subject, $content);
}


工具类调用:

Email::send($to, $subject, $content, $attach = [], $cc = [], $bcc = [])


image.png

顺,不妄喜;逆,不惶馁;安,不奢逸;危,不惊惧。--史记

评论

^