PHP 內建 mail() 函數雖簡單,但郵件送達率極低(常被 Hotmail、Live、Outlook 等主流信箱攔截或判定為垃圾郵件)。PHPMailer 作為成熟的郵件發送庫,支援 SMTP 認證、HTML/純文字雙格式、附件、加密簽名等企業級功能,是發送郵件的不二之選。
# Composer(推薦)
composer require phpmailer/phpmailer
# 或手動下載:https://github.com/PHPMailer/PHPMailer
<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;
require_once __DIR__ . '/vendor/autoload.php';
function sendWelcomeEmail(string $nickname, string $email, int $userId, string $activationCode): bool {
$mail = new PHPMailer(true); // true = 啟用異常拋出
try {
// === SMTP 伺服器設定 ===
$mail->isSMTP();
$mail->Host = 'smtp.163.com'; // SMTP 主機
$mail->SMTPAuth = true; // 啟用認證
$mail->Username = 'your_email@163.com'; // 帳號
$mail->Password = 'your_auth_code'; // 授權碼(非登入密碼)
$mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS; // SSL 加密 (465 port)
$mail->Port = 465; // SSL 埠號
// $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; // TLS 加密 (587 port)
// $mail->Port = 587;
// === 寄件人/收件人 ===
$mail->setFrom('your_email@163.com', '系統名稱');
$mail->addAddress($email, $nickname); // 收件人
$mail->addReplyTo('noreply@example.com', '客服團隊'); // 回覆地址
// === 郵件內容 ===
$mail->isHTML(true); // HTML 格式
$mail->Subject = '=?UTF-8?B?' . base64_encode('歡迎加入我們!') . '?=';
$body = '<div style="font-family: Arial, sans-serif; max-width: 640px; margin: 0 auto;">';
$body .= '<h2 style="color: #333;">' . htmlspecialchars($nickname) . ',您好</h2>';
$body .= '<p>恭喜您成為第 ' . $userId . ' 位會員!</p>';
$body .= '<p>請點擊下方連結驗證信箱:</p>';
$body .= '<p><a href="https://example.com/activate?code=' . urlencode($activationCode) . '" style="background:#007bff;color:#fff;padding:10px 20px;text-decoration:none;border-radius:4px;">立即驗證</a></p>';
$body .= '<hr><p style="color:#999;font-size:12px;">若非您本人操作,請忽略此郵件。</p>';
$body .= '</div>';
$mail->Body = $body;
$mail->AltBody = strip_tags($body); // 純文字備用版本
// === 附件(可選) ===
// $mail->addAttachment('/path/to/file.pdf', 'custom_name.pdf');
// === 發送 ===
$mail->send();
return true;
} catch (Exception $e) {
error_log("Mailer Error: {$mail->ErrorInfo}");
return false;
}
}
// 使用
sendWelcomeEmail('小明', 'user@example.com', 12345, 'abc123xyz');
?>
| 設定 | 說明 | 常見值 |
|---|---|---|
SMTPSecure | 加密方式 | ENCRYPTION_SMTPS (SSL, port 465) / ENCRYPTION_STARTTLS (TLS, port 587) |
SMTPAuth | 是否認證 | true(現代 SMTP 幾乎都需認證) |
CharSet | 編碼 | UTF-8(預設) |
DKIM_* | DKIM 簽名 | 提升送達率,需私鑰/選擇器/域名 |
SMTPDebug | 除錯等級 | SMTP::DEBUG_OFF / DEBUG_SERVER / DEBUG_CLIENT |
<?php
$mail = new PHPMailer(true);
$mail->isSMTP();
// ... 共用 SMTP 設定 ...
$recipients = [
['email' => 'a@example.com', 'name' => 'User A'],
['email' => 'b@example.com', 'name' => 'User B'],
// ...
];
foreach ($recipients as $to) {
// 重置收件人相關設定
$mail->clearAddresses();
$mail->clearAttachments();
$mail->clearCustomHeaders();
$mail->addAddress($to['email'], $to['name']);
$mail->Subject = "專屬優惠給 {$to['name']}";
$mail->Body = generatePersonalizedBody($to);
try {
$mail->send();
// 記錄成功
} catch (Exception $e) {
// 記錄失敗,繼續下一封
}
// 避免觸發頻率限制
usleep(100_000); // 0.1 秒
}
?>
<?php
$mail->addEmbeddedImage('/path/to/logo.png', 'logo_cid', 'logo.png');
$mail->Body = '<img src="cid:logo_cid" alt="Logo">';
<?php
$mail->DKIM_domain = 'example.com';
$mail->DKIM_selector = 'mail';
$mail->DKIM_private = file_get_contents('/etc/dkim/private.key');
$mail->DKIM_passphrase = 'your_passphrase'; // 若私鑰有密碼
$mail->DKIM_identity = $mail->From;
直接在 HTTP 請求中發送郵件會阻塞回應,標準做法:
| 現象 | 可能原因 | 解決方向 |
|---|---|---|
| Could not instantiate mail function | PHP mail() 未配置 / sendmail 路徑錯誤 | 改用 SMTP 模式 $mail->isSMTP() |
| SMTP connect() failed | 主機/埠號/加密方式錯誤、防火牆阻擋 | telnet 測試連通性、確認 465/587 埠開放 |
| Authentication failed | 帳號/授權碼錯誤、未開啟 SMTP 服務 | 確認信箱服務商 SMTP 設定、使用授權碼而非登入密碼 |
| 郵件進垃圾桶 | 缺少 SPF/DKIM/DMARC、內容觸發規則、IP 信譽差 | 設定 DNS 記錄、優化內容、使用專業郵件服務(SendGrid、Mailgun、Amazon SES) |
PHPMailer 功能強大、社群活躍、文件完善。掌握 SMTP 認證配置、HTML/文字雙格式、異常處理、批量發送優化、DKIM 簽名、非同步佇列 等核心技能,即可應對絕大多數專案郵件發送需求。