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

PHP 發送郵件兩大方案:內建 mail() vs SMTP 類別庫 (PHPMailer/PEAR Mail)

     編輯:PHP 相關知識

PHP 發送郵件兩大方案:內建 mail() vs SMTP 類別庫 (PHPMailer/PEAR Mail)

PHP 發送郵件主要有兩條路徑:呼叫內建 mail() 依賴本地 MTA (Sendmail/Postfix),或使用 SMTP 協議直接連線遠端郵件伺服器。本文比較兩者優劣、設定細節、常見坑點,並推薦現代專案採用 PHPMailer 或 Symfony Mailer 等成熟函式庫。

方案一:內建 mail() 函式

mail('to@example.com', '主旨', '郵件內容', 'From: sender@example.com\r\nContent-Type: text/html; charset=UTF-8');

運作原理

  • PHP 呼叫系統 sendmail 二進制 (由 php.ini sendmail_path 指定),將郵件遞交給本地 MTA。
  • MTA 負責排隊、重試、DNS 查詢 MX 記錄、SMTP 遞送至收件伺服器。

必要條件

  1. 伺服器已安裝並正確設定 MTA (Postfix、Exim、Sendmail)。
  2. php.ini 設定 sendmail_path = /usr/sbin/sendmail -t -i (Linux) 或 SMTP = localhost, smtp_port = 25 (Windows)。
  3. 本地 MTA 需允許 Relay 或已驗證發件域名 (SPF/DKIM/DMARC)。

常見失敗原因

  • 「Failed to connect to mailserver at localhost port 25」:Windows 無內建 MTA,需安裝 hMailServer 或改用 SMTP 方案。
  • 「553 authentication is required」:遠端 SMTP 需驗證,但 mail() 無法提供 SMTP AUTH,除非本地 MTA 設定智慧主機並處理驗證。
  • 郵件進垃圾桶:缺少 SPF/DKIM/DMARC、IP 信譽差、內容觸發反垃圾規則。

優缺點

優點缺點
程式碼極簡、無額外依賴高度依賴本地 MTA 設定,跨平台部署困難
效能較好 (非同步遞交給 MTA)無法直接使用外部 SMTP (Gmail、SendGrid 等) 需驗證
適合簡單通知、本地開發錯誤處理弱、無附件/HTML 內建支援、難以除錯

方案二:SMTP 類別庫 (推薦 PHPMailer / Symfony Mailer)

為何推薦 PHPMailer?

  • 純 PHP 實作 SMTP、POP3、IMAP,無需本地 MTA。
  • 支援 SSL/TLS、STARTTLS、SMTP AUTH (LOGIN/PLAIN/XOAUTH2)。
  • 內建 HTML/純文字替代內容、內嵌圖片、附件、DKIM 簽章。
  • 錯誤訊息詳細、除錯模式完整、相容 PHP 5.5+。
  • Composer 安裝:composer require phpmailer/phpmailer。

PHPMailer 實戰範例 (Gmail SMTP)

<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;

require 'vendor/autoload.php';

$mail = new PHPMailer(true); // true = 啟用例外錯誤
try {
    // 伺服器設定
    $mail->isSMTP();
    $mail->Host       = 'smtp.gmail.com';
    $mail->SMTPAuth   = true;
    $mail->Username   = 'your@gmail.com';
    $mail->Password   = 'your_app_password'; // 應用程式密碼
    $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; // 或 ENCRYPTION_SMTPS (465 port)
    $mail->Port       = 587;

    // 發件/收件
    $mail->setFrom('your@gmail.com', 'Your Name');
    $mail->addAddress('recipient@example.com', 'Recipient Name');
    $mail->addReplyTo('reply@example.com', 'Reply Name');
    $mail->addCC('cc@example.com');
    $mail->addBCC('bcc@example.com');

    // 附件
    $mail->addAttachment('/path/to/file.pdf');
    $mail->addAttachment('/path/to/image.jpg', 'rename.jpg');

    // 內容
    $mail->isHTML(true);
    $mail->Subject = 'PHPMailer 測試郵件';
    $mail->Body    = '

HTML 內容

支援 粗體、圖片、連結。

'; $mail->AltBody = '純文字備份內容,給不支援 HTML 的收件軟體。'; $mail->send(); echo '郵件已發送'; } catch (Exception $e) { echo "發送失敗: {$mail->ErrorInfo}"; }

PEAR Mail (舊專案維護用)

若專案已使用 PEAR,可安裝 pear install Mail Mail_Mime Net_SMTP。語法較繁瑣,功能較 PHPMailer 弱,新專案不建議採用。

進階:非同步發送與佇列

為避免 HTTP 請求阻塞,生產環境應將發送動作推入佇列 (Redis、RabbitMQ、Database),由背景 Worker (Supervisor + PHP CLI) 非同步處理。Laravel、Symfony 內建 Mailer 皆支援佇列驅動。

總結建議

  • 新專案 / 需可靠遞送 / 使用外部 SMTP:直接用 PHPMailer 或框架內建 Mailer (Laravel Mail, Symfony Mailer)。
  • 簡單內部通知、本地有完善 MTA:mail() 可接受,但需監控 MTA 日誌。
  • 大量行銷郵件:改用專業服務 (SendGrid, Mailgun, Amazon SES, Postmark) 並走 API 或 SMTP,自行維護 IP 信譽極高成本。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved