You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js+Express中SendGrid邮件模板Handlebars {{#each}}遍历失效问题

解决SendGrid中Handlebars {{#each}}遍历失效的问题

我一眼就看出问题所在了——你现在把ES6模板字符串的变量替换和SendGrid的Handlebars模板语法混在一起用,但没有把order_items作为模板数据传递给SendGrid,所以SendGrid根本不知道这个变量存在,遍历自然就不生效。

下面是具体的修复步骤:

1. 集中整理所有模板需要的动态数据

先把邮件里要用到的所有动态值(订单信息、订单项、订单号)集中到一个对象里,确保SendGrid能拿到所有渲染需要的数据:

// 假设addedOrder是你生成的订单号
const templateData = {
  addedOrder: addedOrder,
  order: req.body, // 直接传入整个订单对象,方便Handlebars调用属性
  order_items: req.body.order_items
};

2. 重构HTML模板,纯用Handlebars语法

把原来HTML里的ES6模板字符串${}全部替换成Handlebars的{{}},同时去掉不必要的HTML标签转义,直接写正常的HTML结构:

const msg = {
  to: [req.body.customer_email],
  bcc: 'test@test.com',
  from: 'test@test.com',
  subject: `Test`,
  // 用纯Handlebars语法编写模板,不再混合ES6模板字符串
  html: `
    <head>
      <title></title>
    </head>
    <body>
      <div data-role="module-unsubscribe" class="module" role="module" data-type="unsubscribe" style="color:#444444; font-size:12px; line-height:20px; padding:16px 16px 16px 16px; text-align:left;" data-muid="4e838cf3-9892-4a6d-94d6-170e474d21e5">
        <p>This is a confirmation that your order has been processed. You will receive a delivery time within the next 24 hours. Thanks for being a valued customer. Please see order below. If any part of this order is incorrect please reach out to us at test@mail.com</p>
        <h3 style="margin-top:4rem;">Order #{{addedOrder}}</h3>
        <p style="font-size:12px; line-height:20px;"> Name on order: {{order.customer_first_name}} {{order.customer_last_name}}</p>
        <p style="text-transform:capitalize">Address: {{order.customer_address}} {{order.customer_city}} {{order.customer_state}}, {{order.customer_zip}}</p>
        <p>Phone Number: {{order.customer_phone}}</p>
        <p>Order Status: {{order.status}}</p>
        
        {{#each order_items}}
          <div>
            <img style="width:100%;" src="{{this.image_url}}"/>
          </div>
          <p style="font-size:1.3rem">{{this.title}}</p>
          <p style="font-size:1.5rem">${{this.price}}</p>
          <p>Total: ${{this.price * this.quantity}}</p>
        {{/each}}
      </div>
    </body>
  `,
  // 关键!把整理好的模板数据传给SendGrid,让它处理渲染
  dynamicTemplateData: templateData
};

3. 发送逻辑保持不变

最后发送邮件的代码无需修改,SendGrid会自动用dynamicTemplateData里的数据解析HTML中的Handlebars语法:

sgMail.send(msg)
  .then(() => { console.log('Message sent') })
  .catch((error) => { 
    console.log(error.response.body) 
    console.log(error.response.body.errors[0].message) 
  });

为什么原来的写法不行?

你之前的代码里,${addedOrder}这类是Node在发送邮件前就替换成了具体值,但{{#each order_items}}是SendGrid的Handlebars语法,而你根本没把order_items传给SendGrid——SendGrid解析模板时找不到这个变量,遍历自然就不生效了。把所有动态数据统一放到dynamicTemplateData里,让SendGrid来处理所有模板渲染,就能解决这个问题。

内容的提问来源于stack exchange,提问作者cosmicChocolate

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 15:17:47