ECShop 內建的 cls_smtp 類在某些伺服器環境下會出現 fgets() 逾時或 EHLO command failed 錯誤,導致郵件無法發送。本文提供將 ECShop 郵件發送核心替換為 PHPMailer 的完整解決方案,穩定可靠且支援更豐富的郵件功能。
在 cls_smtp 類的 get_data() 方法中,執行 fgets($this->connection, 512) 時頻繁發生逾時。註釋該行後又回報 ehlo command failed,但連線測試實際是通的。同環境下其他程式使用 PHPMailer 發信正常,因此決定替換核心發信邏輯。
smtp_mail() 函數修改 includes/lib_base.php 或相關郵件發送檔案中的 smtp_mail() 函數:
<?php
/**
* 使用 PHPMailer 發送郵件(替換 ECShop 原生 SMTP)
* @param string $name 收件人姓名
* @param string $email 收件人郵箱
* @param string $subject 郵件主題
* @param string $content 郵件內容(HTML)
* @param int $type 內容類型:1=HTML, 0=純文本
* @param bool $notification 是否要求回執
* @return bool
*/
function smtp_mail($name, $email, $subject, $content, $type = 1, $notification = false)
{
global $_CFG, $_LANG, $err;
// 字元編碼轉換
if ($_CFG['mail_charset'] != EC_CHARSET) {
$name = ecs_iconv(EC_CHARSET, $_CFG['mail_charset'], $name);
$subject = ecs_iconv(EC_CHARSET, $_CFG['mail_charset'], $subject);
$content = ecs_iconv(EC_CHARSET, $_CFG['mail_charset'], $content);
$shop_name = ecs_iconv(EC_CHARSET, $_CFG['mail_charset'], $_CFG['shop_name']);
}
$charset = $_CFG['mail_charset'];
// 載入 PHPMailer(需先將 PHPMailer 放入 includes/phpmailer/ 目錄)
include_once ROOT_PATH . 'includes/phpmailer/class.phpmailer.php';
$mail = new PHPMailer();
// 寄件人設定
$mail->From = $_CFG['smtp_user'];
$mail->FromName = '您的店鋪名稱'; // 建議從後台設定讀取
$mail->CharSet = $charset;
$mail->Encoding = 'base64';
$mail->IsHTML($type);
$mail->Subject = $subject;
$mail->Body = $content;
$mail->Timeout = 30;
$mail->SMTPDebug = false; // 生產環境關閉除錯
$mail->ClearAddresses();
$mail->AddAddress($email, $name);
$mail->ConfirmReadingTo = $notification;
// 郵件發送模式判斷
if ($_CFG['mail_service'] == 0) {
// 使用 PHP mail() 函數
$mail->isMail();
} else {
// 使用 SMTP
$mail->IsSMTP();
$mail->Host = $_CFG['smtp_host'];
$mail->Port = $_CFG['smtp_port'];
$mail->SMTPAuth = !empty($_CFG['smtp_pass']);
$mail->Username = $_CFG['smtp_user'];
$mail->Password = $_CFG['smtp_pass'];
$mail->SMTPSecure = 'tls'; // 或 ssl,視郵箱服務商而定
}
// 發送並處理結果
$result = $mail->Send();
if (!$result) {
$err->add($mail->ErrorInfo);
$err->add($_LANG['sendemail_false']);
return false;
}
return true;
}
?>
class.phpmailer.php、class.smtp.php、PHPMailerAutoload.php 放入 includes/phpmailer/ 目錄smtp_mail() 實現fsockopen/fgets 逾時問題ErrorInfo 提供精確診斷依據| 郵箱服務商 | SMTP 主機 | 埠號 | 加密 |
|---|---|---|---|
| Gmail | smtp.gmail.com | 587 | TLS |
| QQ 郵箱/企業郵箱 | smtp.qq.com / smtp.exmail.qq.com | 465 / 587 | SSL / TLS |
| 163/126 | smtp.163.com | 465 / 994 | SSL |
| Outlook/Hotmail | smtp.office365.com | 587 | TLS |