微信公眾號常見需求:使用者預約試駕、報名活動、提交維修單後,**即時發送 Email 通知商家/客服**。本文基於 YYUC 框架(原生 PHP 亦可直接套用),示範從表單接收、資料庫查詢通知設定、SMTP 發送到錯誤處理的完整流程。
[微信用戶] → 提交預約表單 → [PHP 控制器] → 寫入資料庫
↓
查詢商家通知設定 (Email、開關)
↓
SMTP 發送郵件 → [商家郵箱]
// yyuc/yyuc.php 或 common/bootstrap.php require_once YYUC_LIB . 'plugin/SendMail.php'; $sendMail = new SendMail(); // 全域可用,或註冊到容器
// wx/conf.php
public static $email = [
'reg' => [
'protocol' => 'smtp',
'smtp_host' => 'smtp.qq.com',
'smtp_port' => 465, // SSL
'smtp_user' => 'notify@example.com',
'smtp_pass' => 'auth_code_or_password',
'from' => ['notify@example.com', '預約系統通知'],
'charset' => 'utf-8',
'ssl' => true,
],
'findpwd' => [ /* ... */ ],
];
// wx/controller/AppointmentController.php
public function submit()
{
$wid = Session::get('wid'); // 微信公眾號 ID
$openid = Session::get('openid');
// 1. 驗證並寫入預約單
$data = $this->validateAndSave($this->input->post());
if (!$data['success']) return $this->ajaxReturn($data);
// 2. 取得商家通知設定
$pubs = new Model('pubs');
$pubs->field('uid')->find(['id' => $wid]);
$merchantUid = $pubs->uid;
$merchant = new Model('micro_car_yysj'); // 商家擴展表
$merchant->field('noticeemailon, noticeemail')->find(['uid' => $merchantUid]);
// 3. 開關開啟且有郵箱 → 發送
if ($merchant->noticeemailon == '1' && !empty($merchant->noticeemail)) {
$subject = '新預約通知';
$body = "您好,有新的預約單:\n"
. "用戶:$openid\n"
. "項目:{$data['item_name']}\n"
. "時間:{$data['appoint_time']}\n"
. "請登入後台查看詳情:https://example.com/admin/appointment/{$data['id']}";
$result = $sendMail->normal_send(
'reg', // 使用 reg 設定
$merchant->noticeemail, // 收件人
$subject,
$body
);
if (!$result) {
// 記錄日誌,不阻斷主流程
log_write('email_failed', "Appointment {$data['id']} notify failed: " . $sendMail->error);
}
}
return $this->ajaxReturn(['success' => true, 'msg' => '預約成功']);
}
class SendMail {
public $error = '';
public function normal_send(string $tpl, string $to, string $subject, string $body): bool
{
$cfg = Config::get("email.$tpl");
if (!$cfg) { $this->error = "郵件模板 $tpl 不存在"; return false; }
// 使用 PHPMailer 或內建 mail(),此處示意 PHPMailer
$mail = new PHPMailer(true);
try {
$mail->isSMTP();
$mail->Host = $cfg['smtp_host'];
$mail->Port = $cfg['smtp_port'] ?? 25;
$mail->SMTPAuth = true;
$mail->Username = $cfg['smtp_user'];
$mail->Password = $cfg['smtp_pass'];
$mail->SMTPSecure = $cfg['ssl'] ? 'ssl' : 'tls';
$mail->CharSet = $cfg['charset'] ?? 'utf-8';
$mail->setFrom(...$cfg['from']);
$mail->addAddress($to);
$mail->Subject = $subject;
$mail->Body = $body;
$mail->isHTML(false); // 純文字,或 true 送 HTML
$mail->send();
return true;
} catch (Exception $e) {
$this->error = $e->getMessage();
return false;
}
}
}
| 風險 | 對策 |
|---|---|
| SMTP 發送阻塞請求(2~5 秒) | **非同步發送**:寫入 email_queue 表,CLI Worker 輪詢發送;或用 fastcgi_finish_request() 先回應用戶再發送。 |
| 郵件被判定垃圾郵件 | 設定 SPF/DKIM/DMARC、使用企業郵箱、內容避免敏感詞、HTML/文字雙版本。 |
| 發送失敗無感知 | 記錄 email_log 表(狀態、重試次數、錯誤訊息),定時重試 + 管理員告警。 |
| 高併發連接數耗盡 | SMTP 連接池複用、限制並發數、考慮第三方郵件服務。 |
// 控制器結束前
$response = ['success' => true];
$this->ajaxReturn($response); // 先輸出 JSON
fastcgi_finish_request(); // 關閉連線,用戶收到回應
// 後續在同進程繼續執行(不阻塞用戶)
if ($needNotify) {
$sendMail->normal_send('reg', $email, $subject, $body);
// 記錄日誌...
}
將郵件通知從「同步阻塞」升級為「非同步可靠佇列」,並配合完整的設定管理、日誌審計、重試機制,即可構建企業級微信公眾號預約通知系統。