搜索全站
建站 10 分钟阅读

WooCommerce 订单邮件通知配置详解:模板、钩子与 SMTP 送达

订单已经付款成功,客户却没收到确认邮件,多半是模板被改坏或邮件压根没发出去。本文讲清 WooCommerce 各订单状态邮件的触发逻辑、模板覆盖方式、常用钩子写法,以及 SMTP 发送失败的排查路径。

U
UFO_PF 2017-01-05 · 阅读 10 分钟
Wo 建站
阅读提示
本文约 3,631 字,预计阅读 10 分钟。文中命令与配置均经过实测,可直接参考执行。

引言:钱到账了,客户却在问”我下单成功了吗”

最常见的投诉不是物流慢,而是”下单之后什么也没收到”。客户看不到「订单已确认」,就会怀疑付款是否成功,接着去申请退款;客服则要人工翻后台核实,成本极高。另一类故障更隐蔽:管理员收到了「新订单」通知,但客户邮件石沉大海——这通常是 mail() 被主机禁用,或者 SaaS 邮件服务把站点域名判为未验证来源,静默丢弃。要把这件事解决干净,得先搞明白 WooCommerce 邮件是怎么被触发的。

原理分析:邮件由「状态机」驱动,不是按钮

WooCommerce 的邮件是绑定订单状态的。当订单状态变化时,WC_Order::status_transition() 触发 woocommerce_order_status_changed 动作,WC_Emails 里的 send_transactional_email() 再去匹配对应的邮件类。也就是说,只要你调用 wc_get_order()->update_status( 'completed' ),邮件就应该发出去;但如果你用的是 $wpdb 直接改 post_status,邮件一条都不会发——这是很多”批量导出/批量发货”脚本失手的根本原因。

后台 WooCommerce → 设置 → 邮件 里的列表,对应一些真实存在的邮件类:WC_Email_New_Order(管理员)、WC_Email_Customer_Processing_Order、WC_Email_Customer_Completed_Order、WC_Email_Customer_On_Hold_Order、WC_Email_Customer_Refunded_Order、WC_Email_Cancelled_Order、WC_Email_Customer_Note。

订单状态 触发的邮件 适用节点
Pending payment → Processing 客户:订单已收到 + 管理员:新订单 支付成功即刻
Processing → Completed 客户:订单已完成 虚拟商品可自动完成
Completed → Refunded 客户:已退款 全额/部分退款均可触发
任意 → Cancelled 客户:订单已取消 库存回滚后发送

模板文件位于 wp-content/plugins/woocommerce/templates/emails/,覆盖时复制到 你的主题/woocommerce/emails/ 目录下同名文件,无需改动插件本体。

保姆级实操

步骤 1:先解决能不能发出去。 装 WP Mail SMTP 插件,把发送方式改为 SMTP 或 API(SendLayer、SMTP.com、Brevo 都是该插件官方支持的渠道)。配置完成后在插件内自带的邮件测试工具里发一封,收不到就先别做模板。

步骤 2:核对发件人与站点域名一致。 很多 ESP 要求 From 的域名做过 SPF/DKIM/DMARC 授权,否则直接判为伪造发件人被抛弃。

步骤 3:关闭不需要的通知。 客户 Notes 邮件频繁打扰时,可在 Woocommerce → 设置 → 邮件里逐个停用,或用过滤器精确关闭:

// 只对"低库存"类通知做开关控制,新订单通知保留
add_filter( 'woocommerce_email_enabled_low_stock', '__return_false' );

// 让管理员的新订单通知额外抄送仓库邮箱
add_filter( 'woocommerce_email_recipient_new_order', function ( $recipient, $order ) {
    if ( 'cod' === $order->get_payment_method() ) {
        $recipient .= ',warehouse@example.com';
    }
    return $recipient;
}, 10, 2 );

步骤 4:改造已付款订单的邮件标题。 用过滤器改写主题行是安全的做法,不用碰模板:

add_filter( 'woocommerce_email_subject_customer_processing_order', function ( $subject, $order ) {
    return sprintf( '【%s】订单 %s 已收到,我们正在备货', get_bloginfo( 'name' ), $order->get_order_number() );
}, 10, 2 );

步骤 5:在邮件里插入自定义字段。 联名学号、门店自提码这类信息,靠 woocommerce_email_order_meta 输出:

add_action( 'woocommerce_email_order_meta', function ( $order, $sent_to_admin, $plain_text ) {
    $code = get_post_meta( $order->get_id(), '_pickup_code', true );
    if ( $code ) {
        echo '<p>自提码:<strong>' . esc_html( $code ) . '</strong></p>';
    }
}, 10, 3 );

// 完成订单时附带电子发票 PDF
add_filter( 'woocommerce_email_attachments', function ( $attachments, $email_id, $order ) {
    if ( in_array( $email_id, [ 'customer_completed_order' ], true ) ) {
        $dir = WP_CONTENT_DIR . '/invoices';
        $file = sprintf( '%s/invoice-%s.pdf', $dir, $order->get_order_number() );
        if ( file_exists( $file ) ) {
            $attachments[] = $file;
        }
    }
    return $attachments;
}, 10, 3 );

步骤 6:给虚拟商品设置自动完成。 WooCommerce → 设置 → 商品 → 虚拟商品(Virtual)里把”已完成”的自动完成开关打开,订单付款后直接到 Completed,触发对应邮件。WooCommerce 虚拟商品自动发货搭建

常见踩坑

  1. 直接改 post_status 或调用 wp_update_post 而不走 WC_Order::update_status(),邮件完全不触发。
  2. 案例: 某站点把SMTP端口写成 465 却选了 “None” 加密,插件侧不报错,邮件却全部卡在 “queued”,直到客户投诉才发现近两周的订单邮件一封没发。
  3. 主题复制了旧版本 emails/ 模板,升级 WooCommerce 后 customer-completed-order.php 里缺失新的 wc_get_template() 参数,页面报 PHP Warning。
  4. 邮件测试的收件箱是 Gmail,误以为”没收到”——实际进了推广标签。
  5. 用了 woocommerce_email_recipient_new_order 但没有第二个参数声明,匿名函数只接收一个实参,导致 $order 为 null,$order->get_payment_method() 直接致命错误。
  6. 自托管主机对 wp_mail 做了频率限制,促销类群发触发限制后连带交易邮件被拒。
  7. 管理员邮件收件人写成多个邮箱却用了中文顿号分隔,解析失败。WordPress SMTP 邮件发送失败排查

总结

判断邮件链路健康状况的标准很简单:能否发出去(SMTP/ESP)、是谁触发的(状态机)、内容里有没有必要的业务信息(钩子注入)、以及有没有兜底监控(日志)。行动清单:① 用 SMTP 或 API 通道替代 mail();② 任何改订单状态的操作都走 update_status();③ 自定义内容用钩子而非硬改模板;④ 每周跑一遍下单自测。邮件是最容易被忽视却最直接影响复购的一环。

U
UFO_PF作者

专注 WordPress 生态的实战作者,内容以「可复制、可验证」为第一原则。

留下你的想法

邮箱地址不会被公开。带 * 的为必填项。