
OpenCart 3.x 已弃用原生 mail() 函数,改用统一的 Mail 类进行邮件发送;直接调用 mail() 会失败,必须通过 OpenCart 的邮件服务层配置 SMTP 或 mail 引擎并实例化 Mail 对象。
opencart 3.x 已弃用原生 `mail()` 函数,改用统一的 `mail` 类进行邮件发送;直接调用 `mail()` 会失败,必须通过 opencart 的邮件服务层配置 smtp 或 mail 引擎并实例化 `mail` 对象。
在 OpenCart 3.0.2.0 及后续版本中,系统已移除对 PHP 原生 mail() 函数的直接依赖,转而采用封装更完善、可配置性更强的 Mail 类(位于 system/library/mail.php)。该类支持多种邮件引擎(如 mail、smtp、sendmail),并内置字符编码处理、HTML 渲染、安全头设置等功能。若继续沿用 OpenCart 2.x 风格的裸 mail() 调用(如 mail($to, $subject, $message, $headers)),将因缺少必要的 MIME 头、编码处理及 OpenCart 上下文而静默失败。
✅ 正确做法是使用 OpenCart 3+ 推荐的 Mail 类实例,并严格遵循其 API 规范:
// 实例化 Mail 类(自动读取后台邮件配置)
$mail = new Mail($this->config->get('config_mail_engine'));
// 根据所选引擎加载对应参数(SMTP 或 mail)
$mail->parameter = $this->config->get('config_mail_parameter');
$mail->smtp_hostname = $this->config->get('config_mail_smtp_hostname');
$mail->smtp_username = $this->config->get('config_mail_smtp_username');
$mail->smtp_password = html_entity_decode($this->config->get('config_mail_smtp_password'), ENT_QUOTES, 'UTF-8');
$mail->smtp_port = $this->config->get('config_mail_smtp_port');
$mail->smtp_timeout = $this->config->get('config_mail_smtp_timeout');
// 设置收件人、发件人与显示名称(注意:setFrom() 是邮箱地址,setSender() 是显示名)
$mail->setTo('<a class="__cf_email__" data-cfemail="176e78626557727a767e7b396f6f6f" href="/cdn-cgi/l/email-protection">[email protected]</a>');
$mail->setFrom('<a class="__cf_email__" data-cfemail="630a0d050c230a0c020d0d0c1610170c1106104d000c0e" href="/cdn-cgi/l/email-protection">[email protected]</a>');
$mail->setSender(html_entity_decode('Ioannou Stores', ENT_QUOTES, 'UTF-8')); // 显示名称,需解码防止乱码
// 主题与内容必须经 html_entity_decode 处理,确保希腊语等 UTF-8 字符正确呈现
$mail->setSubject(html_entity_decode('-5% Έκπτωση στο ioannoustores.com', ENT_QUOTES, 'UTF-8'));
$mail->setHtml(html_entity_decode(
'Χρησιμοποιήστε το εκπτωτικό κουπόνι στις αγορές σας και κερδίστε 5% έκπτωση. Ο κωδικός σας είναι: ' . $res . ' και ισχύει για 7 ημέρες.',
ENT_QUOTES,
'UTF-8'
));
// 发送邮件
$mail->send();⚠️ 关键注意事项:
- 编码必须显式处理:OpenCart 3 默认对配置项做 HTML 实体编码,因此 smtp_password、subject 和 message 必须用 html_entity_decode(..., ENT_QUOTES, 'UTF-8') 还原,否则希腊语等非 ASCII 字符将显示为乱码或实体符号(如 α)。
- setFrom() ≠ setSender():setFrom() 设置的是 RFC 5321 的 MAIL FROM 地址(用于 SMTP 回退和 SPF 验证),必须是合法邮箱;setSender() 设置的是 RFC 5322 的显示发件人名称(如“Ioannou Stores”),支持 Unicode。
- 避免硬编码邮箱:生产环境应从数据库或配置中动态获取收件人列表(如订阅者邮箱),而非写死 $to;批量发送建议配合队列或分页,防止超时。
- 验证后台配置:请确保管理后台 → 系统 → 设置 → 编辑站点 → 邮件选项中已启用并正确配置邮件引擎(推荐 SMTP)、主机、端口、认证凭据等。
? 补充建议:若需向所有订阅用户群发,应在模型层(如 catalog/model/extension/newsletter/subscribe.php)查询 newsletter 表,循环调用上述 Mail 实例(或使用异步任务),并添加速率限制与错误日志记录,以提升稳定性与可维护性。


















