邮件已经发送成功,但模板里的订单号、客户名称或自定义内容是空白,这类问题通常与 SMTP 无关。传输链路已经工作,接下来要看模板写了什么变量,以及发送代码实际传入了什么。

先确认变量名称

模板中写 {{var order.increment_id}},前提是发送时确实存在名为 order 的对象,并且模板系统允许访问对应数据。变量名大小写或层级不一致,通常不会报明显异常,只会渲染为空。

后台邮件模板页面会显示可用变量信息,但自定义模块新增的变量仍需在代码和模板之间保持一致。

自定义邮件的传值示例

$transport = $this->transportBuilder
    ->setTemplateIdentifier($templateId)
    ->setTemplateOptions([
        'area' => \Magento\Framework\App\Area::AREA_FRONTEND,
        'store' => $storeId,
    ])
    ->setTemplateVars([
        'customer_name' => $customerName,
        'order_number' => $order->getIncrementId(),
        'support_note' => $supportNote,
    ])
    ->setFromByScope('general', $storeId)
    ->addTo($recipient)
    ->getTransport();
$transport->sendMessage();

对应模板应使用 {{var customer_name}}{{var order_number}}{{var support_note}},而不是继续按订单对象的写法读取。

对象、数组和标量不要混用

如果代码把 order_number 作为字符串传入,模板就不能写成 order_number.increment_id。反过来,传入对象时也要确认模板安全规则允许访问目标字段。最稳妥的方式是只传模板真正需要的标量值,减少对象暴露。

Store View 也会让测试产生误判

邮件模板可按 Store View 配置。你修改了中文模板,但测试订单属于英文 Store View,收到的仍可能是另一份模板。记录订单的 store_id,并检查发送代码中的 template options。

一个实用的调试方法

在测试环境记录变量键名和非敏感值类型,例如字符串、整数或对象类名,不要把客户地址、Token 或完整订单内容写进日志。确认键名到达 TransportBuilder 后,再回头检查模板。

邮件变量问题修好后,用游客订单、注册客户订单和不同 Store View 各发一封。三封邮件的模板和变量都正确,才说明不是偶然命中了默认范围。