PHP 發送郵件主要有兩條路徑:呼叫內建 mail() 依賴本地 MTA (Sendmail/Postfix),或使用 SMTP 協議直接連線遠端郵件伺服器。本文比較兩者優劣、設定細節、常見坑點,並推薦現代專案採用 PHPMailer 或 Symfony Mailer 等成熟函式庫。
mail('to@example.com', '主旨', '郵件內容', 'From: sender@example.com\r\nContent-Type: text/html; charset=UTF-8');
sendmail 二進制 (由 php.ini sendmail_path 指定),將郵件遞交給本地 MTA。php.ini 設定 sendmail_path = /usr/sbin/sendmail -t -i (Linux) 或 SMTP = localhost, smtp_port = 25 (Windows)。mail() 無法提供 SMTP AUTH,除非本地 MTA 設定智慧主機並處理驗證。| 優點 | 缺點 |
|---|---|
| 程式碼極簡、無額外依賴 | 高度依賴本地 MTA 設定,跨平台部署困難 |
| 效能較好 (非同步遞交給 MTA) | 無法直接使用外部 SMTP (Gmail、SendGrid 等) 需驗證 |
| 適合簡單通知、本地開發 | 錯誤處理弱、無附件/HTML 內建支援、難以除錯 |
composer require phpmailer/phpmailer。<?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,可安裝 pear install Mail Mail_Mime Net_SMTP。語法較繁瑣,功能較 PHPMailer 弱,新專案不建議採用。
為避免 HTTP 請求阻塞,生產環境應將發送動作推入佇列 (Redis、RabbitMQ、Database),由背景 Worker (Supervisor + PHP CLI) 非同步處理。Laravel、Symfony 內建 Mailer 皆支援佇列驅動。
mail() 可接受,但需監控 MTA 日誌。