首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 使用 PHPMailer 透過 QQ 企業郵箱發送郵件完整範例

     編輯:PHP 相關知識

PHP 內建 mail() 功能有限,生產環境強烈建議使用 **PHPMailer** 透過 SMTP 發送,支援認證、加密、HTML/文字多格式、附件、郵件佇列。本文以 QQ 企業郵箱 (騰訊企業郵) 為例,提供完整可用程式碼與常見坑點解析。

一、前置準備

  1. 註冊/登入 騰訊企業郵,建立發信帳號 (如 noreply@yourdomain.com)
  2. 開啟 **SMTP 服務**:郵箱設定 → 客戶端設定 → 開啟 SMTP/IMAP
  3. 取得 **授權碼** (非登入密碼):設定 → 帳號 → 開啟 POP3/SMTP → 產生授權碼
  4. DNS 設定 **MX 記錄** 指向騰訊企業郵 (若自有域名)

二、Composer 安裝 PHPMailer

composer require phpmailer/phpmailer

三、完整發信類別封裝

<?php
namespace App\Mail;

use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;

class QqMailer {
    private PHPMailer $mailer;
    private array $config;

    public function __construct(array $config) {
        $this->config = $config;
        $this->mailer = new PHPMailer(true); // true = 啟用例外

        // SMTP 設定
        $this->mailer->isSMTP();
        $this->mailer->Host       = $config['host'] ?? 'smtp.exmail.qq.com';
        $this->mailer->SMTPAuth   = true;
        $this->mailer->Username   = $config['username'];
        $this->mailer->Password   = $config['password']; // 授權碼
        $this->mailer->SMTPSecure = $config['secure'] ?? PHPMailer::ENCRYPTION_STARTTLS; // TLS
        $this->mailer->Port       = $config['port'] ?? 587;
        $this->mailer->CharSet    = 'UTF-8';
        $this->mailer->Timeout    = 30;

        // 除錯模式 (僅開發環境)
        if (($config['debug'] ?? false)) {
            $this->mailer->SMTPDebug = 2; // 2 = 詳細輸出
            $this->mailer->Debugoutput = function($str, $level) {
                error_log("PHPMailer [$level]: $str");
            };
        }
    }

    /**
     * 發送郵件
     *
     * @param string|array $to 收件者 [email => name] 或單一 email
     * @param string       $subject 主旨
     * @param string       $htmlBody HTML 內容
     * @param string|null  $textBody 純文字備選內容
     * @param array        $attachments 附件 ['path' => '/path/file.pdf', 'name' => 'file.pdf']
     * @param array        $options 額外選項 ['cc', 'bcc', 'replyTo']
     * @return bool
     * @throws Exception
     */
    public function send(
        $to,
        string $subject,
        string $htmlBody,
        ?string $textBody = null,
        array $attachments = [],
        array $options = []
    ): bool {
        // 寄件者
        $this->mailer->setFrom($this->config['username'], $this->config['from_name'] ?? '系統通知');

        // 收件者
        if (is_array($to)) {
            foreach ($to as $email => $name) {
                $this->mailer->addAddress($email, $name);
            }
        } else {
            $this->mailer->addAddress($to);
        }

        // CC/BCC
        foreach (($options['cc'] ?? []) as $email => $name) {
            $this->mailer->addCC($email, $name);
        }
        foreach (($options['bcc'] ?? []) as $email => $name) {
            $this->mailer->addBCC($email, $name);
        }

        // Reply-To
        if (!empty($options['replyTo'])) {
            $this->mailer->addReplyTo($options['replyTo'][0], $options['replyTo'][1] ?? '');
        }

        // 內容
        $this->mailer->isHTML(true);
        $this->mailer->Subject = $subject;
        $this->mailer->Body    = $htmlBody;
        $this->mailer->AltBody = $textBody ?? strip_tags($htmlBody); // 重要:純文字備選

        // 附件
        foreach ($attachments as $att) {
            $this->mailer->addAttachment($att['path'], $att['name'] ?? basename($att['path']));
        }

        // 發送
        $this->mailer->send();
        return true;
    }
}

四、使用範例

<?php
require_once __DIR__ . '/vendor/autoload.php';

use App\Mail\QqMailer;

$config = [
    'host'     => 'smtp.exmail.qq.com',
    'username' => 'noreply@yourcompany.com',
    'password' => 'your_auth_code_here', // 授權碼,非密碼
    'port'     => 587,
    'secure'   => PHPMailer::ENCRYPTION_STARTTLS,
    'from_name' => '我的系統',
    'debug'    => true, // 開發時開啟
];

$mailer = new QqMailer($config);

try {
    $result = $mailer->send(
        to: 'user@example.com',
        subject: '歡迎註冊',
        htmlBody: '<h1>歡迎</h1><p>感謝加入我們!</p>',
        textBody: '歡迎\n感謝加入我們!',
        attachments: [
            ['path' => __DIR__ . '/assets/welcome.pdf', 'name' => 'welcome.pdf']
        ],
        options: [
            'replyTo' => ['support@yourcompany.com', '客服團隊']
        ]
    );
    echo "發送成功";
} catch (Exception $e) {
    error_log("郵件發送失敗: " . $e->getMessage());
    echo "發送失敗: " . $e->getMessage();
}

五、QQ 企業郵專屬坑點與解決

問題原因解決
535 Error: authentication failed使用登入密碼而非授權碼必須在郵箱設定產生**授權碼**並填入 Password
Connection timed out (port 465/587)伺服器防火牆封鎖輸出連線開放輸出 TCP 465 (SSL) 或 587 (STARTTLS);或改用 25 (無加密,不推薦)
Certificate verification failedPHP 無 CA 憑證束php.ini 設定 openssl.cafile=/path/cacert.pem 或 curl.cainfo
郵件進垃圾桶缺少 SPF/DKIM/DMARC域名 DNS 加入騰訊提供的 SPF (include:spf.exmail.qq.com)、DKIM 記錄
發送大量郵件被限流觸發頻率限制使用佇列 (Redis + Worker) 限流,單 IP 每分鐘 < 60 封

六、進階:非同步佇列發送 (Laravel/ThinkPHP/Symfony 整合)

將郵件任務推入佇列,背景 Worker 處理,避免阻塞 HTTP 請求:

<?php
// Laravel Job 範例
class SendWelcomeEmail implements ShouldQueue {
    use Queueable, SerializesModels;

    public $userId;

    public function __construct(int $userId) { $this->userId = $userId; }

    public function handle() {
        $user = User::find($this->userId);
        $mailer = new QqMailer(config('mail.qq'));
        $mailer->send($user->email, '歡迎', view('emails.welcome', ['user' => $user])->render());
    }
}

// 控制器
SendWelcomeEmail::dispatch($user->id);

七、總結

  • **棄用 mail()**,全面改用 PHPMailer + SMTP Auth + TLS/SSL
  • QQ 企業郵**必須使用授權碼**,並正確設定 DNS (MX, SPF, DKIM)
  • 封裝可重用類別,支援 HTML/文字、附件、CC/BCC、Reply-To
  • 生產環境**必須**佇列化、記錄日誌、監控送達率
  • 定期輪換授權碼,最小權限原則
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved