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

自定义邮件通知导致WooCommerce默认自动邮件无法发送

WooCommerce自定义发货状态导致默认邮件失效的问题排查

问题描述

为WooCommerce开发「发货与发票」插件时,新增了processing到shipped的订单状态流转(含下拉选择、批量操作),同时添加了订单变为shipped时的客户发货通知邮件。但出现异常:默认自动邮件(如新订单通知、订单完成通知等)无法触发,仅手动发送邮件正常,下单、状态变更等场景无自动邮件。

问题根源分析

1. 邮件动作注册与触发逻辑冲突

  • 错误添加woocommerce_order_status_wc-shipped到邮件动作列表,同时手动绑定send_transactional_email到该动作,干扰了WooCommerce原生邮件触发机制。
  • 自定义邮件类中重复绑定woocommerce_order_status_shipped_notification动作,且直接调用send()方法,未遵循WooCommerce标准邮件触发流程。

2. 邮件类初始化优先级问题

使用20的优先级注册自定义邮件类,可能在原生邮件类初始化前执行,导致原生邮件类被干扰或覆盖。

3. 状态变更动作命名不规范

使用简化版的woocommerce_order_status_shipped动作,而非WooCommerce标准的woocommerce_order_status_to-shipped格式,导致状态变更事件链混乱,影响原生邮件触发。

修复代码方案

步骤1:修正邮件动作注册逻辑

删除冗余手动触发代码,改用原生机制:

add_filter( 'woocommerce_email_actions', 'shipped_email_actions', 20, 1 );
function shipped_email_actions( $actions ) {
    // 添加标准状态变更动作
    $actions[] = 'woocommerce_order_status_to-shipped';
    return $actions;
}

// 移除以下两行冗余代码:
// add_action( 'woocommerce_order_status_wc-shipped', array( 'WC_Emails', 'send_transactional_email' ), 10, 1 );
// add_action('woocommerce_order_status_shipped', 'shipped_status_trigger_email_notification', 10, 2 );

步骤2:重构自定义邮件类

移除内部冗余动作绑定,遵循原生触发流程:

class WC_Shipped_Order_Email extends WC_Email {

    public function __construct() {
        $this->id             = 'customer-shipped-order';
        $this->customer_email = true;
        $this->title          = 'Shipped order';
        $this->description    = 'This notification is sent to customers after shipping, including product details and tracking number.';
        $this->template_html  = 'emails/customer-shipped-order.php';
        $this->placeholders   = array(
            '{order_date}'   => '',
            '{order_number}' => '',
        );

        parent::__construct();
        
        // 绑定标准状态变更动作触发邮件
        add_action( 'woocommerce_order_status_to-shipped', array( $this, 'trigger' ), 10, 2 );
    }

    public function trigger( $order_id, $order = false ) {
        if ( ! $order_id ) return;
        
        $this->object = is_a( $order, 'WC_Order' ) ? $order : wc_get_order( $order_id );
        
        if ( ! is_a( $this->object, 'WC_Order' ) ) return;
        
        $this->recipient                      = $this->object->get_billing_email();
        $this->placeholders['{order_date}']   = wc_format_datetime( $this->object->get_date_created() );
        $this->placeholders['{order_number}'] = $this->object->get_order_number();

        if ( ! $this->is_enabled() || ! $this->get_recipient() ) return;

        $this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() );
    }

    // 其余方法(get_content_html、init_form_fields)保持不变
}

步骤3:调整邮件类注册优先级

降低优先级,确保原生邮件类先完成初始化:

add_filter( 'woocommerce_email_classes', 'add_shipped_order_woocommerce_email', 30, 1 );
function add_shipped_order_woocommerce_email( $email_classes ) {
    require( SHIPMENT_INVOICE_PLUGIN_DIR . 'includes/classes/ShippedOrderEmail.php' );
    $email_classes['WC_Shipped_Order_Email'] = new WC_Shipped_Order_Email();
    return $email_classes;
}

步骤4:优化批量状态修改逻辑

添加批量操作处理函数,确保状态变更符合原生流程:

add_action( 'admin_action_mark_shipped', 'handle_bulk_mark_shipped' );
function handle_bulk_mark_shipped() {
    if ( ! isset( $_POST['post'] ) || ! is_array( $_POST['post'] ) ) return;
    
    foreach ( $_POST['post'] as $order_id ) {
        $order = wc_get_order( $order_id );
        if ( is_a( $order, 'WC_Order' ) ) {
            // 使用update_status触发原生状态变更事件
            $order->update_status( 'shipped', 'Bulk marked as shipped' );
        }
    }
    
    wp_redirect( wp_get_referer() );
    exit;
}

验证方法

  1. 保存代码后,通过WooCommerce后台「状态 > 工具」清除缓存
  2. 测试下单流程,检查默认新订单邮件是否正常触发
  3. 将订单从processing改为shipped,验证自定义发货邮件是否发送
  4. 测试批量修改订单状态,确认邮件逻辑正常

内容的提问来源于stack exchange,提问作者Volkan Ülkü

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 12:25:17