推薦使用 Composer (ThinkPHP 5.1+):
composer require phpmailer/phpmailer
或手動下載放入:extend/PHPMailer/
<?php
// app/common/service/MailService.php
namespace app\common\service;
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
use think\facade\Config;
class MailService
{
private $mailer;
public function __construct()
{
$this->mailer = new PHPMailer(true);
$this->initConfig();
}
private function initConfig()
{
$cfg = Config::get('mail');
$this->mailer->CharSet = 'UTF-8';
$this->mailer->isSMTP();
$this->mailer->Host = $cfg['smtp_host'];
$this->mailer->SMTPAuth = true;
$this->mailer->Username = $cfg['smtp_user'];
$this->mailer->Password = $cfg['smtp_pass'];
$this->mailer->SMTPSecure = $cfg['smtp_secure'] ?? 'tls'; // tls/ssl
$this->mailer->Port = $cfg['smtp_port'] ?? 587;
$this->mailer->setFrom($cfg['from_addr'], $cfg['from_name']);
}
public function send(string $to, string $subject, string $body, array $attachments = []): bool
{
try {
$this->mailer->clearAddresses();
$this->mailer->addAddress($to);
$this->mailer->Subject = $subject;
$this->mailer->Body = $body;
$this->mailer->isHTML(true);
foreach ($attachments as $path => $name) {
$this->mailer->addAttachment($path, $name);
}
return $this->mailer->send();
} catch (Exception $e) {
// 記錄日誌
\think\facade\Log::error("Mail send failed: {$this->mailer->ErrorInfo}");
return false;
}
}
}
<?php
// config/mail.php
return [
'smtp_host' => 'smtp.exmail.qq.com',
'smtp_user' => 'noreply@example.com',
'smtp_pass' => 'your_password',
'smtp_secure' => 'ssl',
'smtp_port' => 465,
'from_addr' => 'noreply@example.com',
'from_name' => '系統通知',
];
<?php
// app/controller/Index.php
namespace app\controller;
use app\common\service\MailService;
use think\facade\View;
class Index
{
public function testMail()
{
$mail = new MailService();
$result = $mail->send(
'user@example.com',
'測試郵件',
'Hello ThinkPHP!
這是一封測試郵件。
'
);
return json(['success' => $result, 'message' => $result ? '發送成功' : '發送失敗']);
}
}
MailJob 推入 Redis/RabbitMQView::fetch('mail/welcome', ['user' => $user]) 渲染 HTMLaddBCC() 隱藏副本,保護收件人隱私addEmbeddedImage($path, 'cid'),HTML 中用 
| 現象 | 可能原因 | 解決 |
|---|---|---|
| SMTP connect() failed | 端口/加密方式錯誤 | 檢查 465(SSL)/587(TLS)、防火牆 |
| Authentication failed | 帳號密碼/授權碼錯誤 | 確認 SMTP 服務商授權碼 (非登入密碼) |
| 郵件進垃圾箱 | SPF/DKIM/DMARC 未配置 | 域名 DNS 配置郵件認證記錄 |
| 中文亂碼 | CharSet 未設定 | $mail->CharSet = 'UTF-8' |
封裝服務類統一管理配置與異常,讓控制器保持輕量,符合單一職責原則。