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

PHP 郵件發送實戰案例:mail() 失敗排查與 PHPMailer 成功實作

     編輯:PHP 綜合知識

記錄實際專案中從 mail() 失敗排查到改用 PHPMailer 成功發送的完整過程,包含常見錯誤訊息分析、Sendmail 設定、PHPMailer 完整配置與測試驗證。

一、mail() 失敗排查實錄

錯誤 1:無法連線到郵件伺服器

<?php
mail('test@163.com', 'Test', 'Content');
// Warning: mail(): Failed to connect to mailserver at "localhost" port 25
// verify your "SMTP" and "smtp_port" setting in php.ini
?>

原因:本機未安裝/啟動 MTA (Sendmail/Postfix),或 php.ini 未正確設定。

嘗試修正 php.ini:

SMTP = smtp.163.com
smtp_port = 25
sendmail_from = admin@163.com

結果:仍失敗,新錯誤:

Warning: mail(): SMTP server response: 553 authentication is required

根本原因:mail() 不支援 SMTP 認證。現代郵件伺服器(Gmail、163、Outlook 等)皆要求認證,mail() 無法提供帳號密碼,故無法直接使用外部 SMTP。

解決方案比較

方案可行性說明
架設本地 Postfix/Sendmail 並設定 Relay可行但複雜需精通 MTA 設定、SPF/DKIM、佇列管理
使用不需認證的內部 SMTP罕見現代環境幾乎不存在
改用 PHPMailer (SMTP 類別)✅ 推薦支援認證、SSL/TLS、HTML、附件、純 PHP 實作

二、PHPMailer 成功實作完整流程

1. 安裝

composer require phpmailer/phpmailer
# 或手動下載:https://github.com/PHPMailer/PHPMailer

2. 基本發送 (Gmail 範例)

<?php
require 'vendor/autoload.php';

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

$mail = new PHPMailer(true);

try {
    // SMTP 設定
    $mail->isSMTP();
    $mail->Host = 'smtp.gmail.com';
    $mail->SMTPAuth = true;
    $mail->Username = 'your@gmail.com';
    $mail->Password = 'your_16_char_app_password';  // 應用程式密碼
    $mail->SMTPSecure = 'tls';  // 或 'ssl'
    $mail->Port = 587;          // TLS: 587, SSL: 465

    // 寄件人/收件人
    $mail->setFrom('your@gmail.com', '您的名稱');
    $mail->addAddress('recipient@example.com', '收件人');

    // 內容
    $mail->isHTML(true);
    $mail->Subject = 'PHPMailer 測試';
    $mail->Body = '<h1>HTML 郵件</h1><p>這是 <b>測試</b> 內容。</p>';
    $mail->AltBody = '純文字備用內容';

    $mail->send();
    echo '發送成功!';
} catch (Exception $e) {
    echo "發送失敗: {$mail->ErrorInfo}";
}
?>

3. 163/網易郵箱設定

<?php
$mail->Host = 'smtp.163.com';
$mail->Port = 465;  // SSL
$mail->SMTPSecure = 'ssl';
$mail->Username = 'your@163.com';
$mail->Password = 'client_auth_password';  // 客戶端授權碼,非登入密碼
?>

4. 企業郵箱 / Exchange 設定

<?php
$mail->Host = 'smtp.yourcompany.com';
$mail->Port = 587;
$mail->SMTPSecure = 'tls';
$mail->Username = 'user@yourcompany.com';
$mail->Password = 'your_ad_password';
?>

5. 完整功能範例:附件、抄送、嵌入圖片、優先權

<?php
$mail = new PHPMailer(true);
$mail->isSMTP();
$mail->Host = 'smtp.gmail.com';
$mail->SMTPAuth = true;
$mail->Username = 'sender@gmail.com';
$mail->Password = 'app_password';
$mail->SMTPSecure = 'tls';
$mail->Port = 587;

// 字元編碼
$mail->CharSet = 'UTF-8';

// 寄件人
$mail->setFrom('sender@gmail.com', '發送系統');
$mail->addReplyTo('reply@gmail.com', '回覆處理');

// 收件人
$mail->addAddress('user1@example.com', '用戶一');
$mail->addAddress('user2@example.com');  // 僅信箱
$mail->addCC('cc@example.com', '抄送人');
$mail->addBCC('bcc@example.com', '密件副本');

// 附件
$mail->addAttachment('/path/to/report.pdf', '月報.pdf');
$mail->addAttachment('/path/to/data.xlsx');

// 嵌入圖片 (CID)
$mail->addEmbeddedImage('/path/to/logo.png', 'logo_cid');
$mail->addEmbeddedImage('/path/to/banner.jpg', 'banner_cid');

// 內容
$mail->isHTML(true);
$mail->Subject = '【重要】月度報告 - ' . date('Y-m');
$mail->Priority = 1;  // 1=高, 3=普通, 5=低
$mail->Body = '
    <html><body>
    <img src="cid:banner_cid" alt="Banner" style="max-width:100%">
    <h1>月度報告</h1>
    <p>親愛的用戶,附件為本月報告,請查收。</p>
    <img src="cid:logo_cid" alt="Logo">
    </body></html>
';
$mail->AltBody = '月度報告已寄出,請查收附件。';

// 除錯模式 (開發時啟用)
// $mail->SMTPDebug = 2;  // 0=關閉, 1=客戶端, 2=伺服器, 3=連線, 4=低階

$mail->send();
echo '郵件發送成功!';
?>

三、常見錯誤與解決

錯誤訊息原因解決
SMTP connect() failed主機/埠口/加密錯誤、防火牆阻擋檢查設定、telnet 測試連線、開放防火牆
535 Authentication failed帳號/密碼錯誤Gmail 用應用程式密碼、163 用授權碼、企業郵箱確認 AD 密碼
550 Mailbox unavailable收件信箱不存在/滿/被封確認收件地址正確
554 Transaction failed / Spam被判定垃圾郵件設定 SPF/DKIM/DMARC、避免垃圾詞、用專業郵件服務
SSL routines:ssl3_get_server_certificate:certificate verify failedSSL 憑證驗證失敗$mail->SMTPOptions = ['ssl'=>['verify_peer'=>false,'verify_peer_name'=>false,'allow_self_signed'=>true]]; (僅測試用)
Could not instantiate mail function未呼叫 isSMTP() 卻用 SMTP 設定確認 $mail->isSMTP() 在設定之前

四、部署檢查清單

  1. ✅ Composer 安裝 PHPMailer
  2. ✅ SMTP 主機、埠口、加密方式正確
  3. ✅ 使用應用程式密碼/授權碼(非登入密碼)
  4. ✅ 寄件人信箱與 SMTP 帳號一致(或允許代發)
  5. ✅ 伺服器防火牆開放 465/587/25 埠輸出
  6. ✅ 設定 SPF/DKIM/DMARC DNS 記錄
  7. ✅ 測試發送到 Gmail/Outlook/企業郵箱確認收件
  8. ✅ 關閉 SMTPDebug (生產環境)
  9. ✅ 加入錯誤記錄與監控告警

五、本地測試腳本

<?php
// test_mail.php - 放在專案根目錄,瀏覽器或 CLI 執行
require 'vendor/autoload.php';
use PHPMailer\PHPMailer\PHPMailer;

$mail = new PHPMailer(true);
$mail->isSMTP();
$mail->Host = 'smtp.gmail.com';
$mail->SMTPAuth = true;
$mail->Username = 'test@gmail.com';
$mail->Password = 'app_password';
$mail->SMTPSecure = 'tls';
$mail->Port = 587;
$mail->CharSet = 'UTF-8';
$mail->setFrom('test@gmail.com', '測試系統');
$mail->addAddress('test@gmail.com');  // 寄給自己
$mail->Subject = 'PHPMailer 測試 ' . date('H:i:s');
$mail->Body = '<h1>測試成功!</h1><p>時間: ' . date('Y-m-d H:i:s') . '</p>';

try {
    $mail->send();
    echo "✅ 發送成功\n";
} catch (Exception $e) {
    echo "❌ 發送失敗: {$mail->ErrorInfo}\n";
    if ($mail->SMTPDebug) echo $mail->getSMTPInstance()->getError();
}
?>

結論:mail() 適合有完整 MTA 基礎設施的內部系統;對外發送、現代雲端環境、需 HTML/附件/認證的場景,**PHPMailer 是標準解法**,穩定、功能全、社群支援好。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved