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

禁用WooCommerce新订单邮件后,无法通过代码触发发送该邮件

解决WooCommerce自动化工具邮件重复发送问题

问题根源

WooCommerce的内置邮件类(比如WC_Email_New_Order)会优先检查后台的邮件开关状态,关闭开关后trigger()方法会直接跳过发送逻辑;但开启开关后,内置的订单状态钩子又会自动触发邮件,导致和你的自动化工具重复发送。

可行解决方案

方案一:手动构造并发送邮件(完全绕开内置触发逻辑)

直接跳过内置的开关检查和自动触发钩子,手动调用邮件发送逻辑,同时禁用内置的自动触发。

  1. 首先禁用WooCommerce内置的新订单邮件自动触发:
// 移除所有内置的新订单邮件触发钩子
add_action( 'woocommerce_email', 'disable_default_new_order_trigger', 10, 1 );
function disable_default_new_order_trigger( $email_class ) {
    $new_order_email = $email_class->emails['WC_Email_New_Order'];
    remove_action( 'woocommerce_order_status_pending_to_processing_notification', array( $new_order_email, 'trigger' ) );
    remove_action( 'woocommerce_order_status_pending_to_completed_notification', array( $new_order_email, 'trigger' ) );
    remove_action( 'woocommerce_order_status_pending_to_on-hold_notification', array( $new_order_email, 'trigger' ) );
    remove_action( 'woocommerce_order_status_failed_to_processing_notification', array( $new_order_email, 'trigger' ) );
    remove_action( 'woocommerce_order_status_failed_to_completed_notification', array( $new_order_email, 'trigger' ) );
    remove_action( 'woocommerce_order_status_failed_to_on-hold_notification', array( $new_order_email, 'trigger' ) );
}
  1. 修改你的自动化回调函数,手动发送邮件:
add_action( 'email_callback', 'email_callback' ); 
function email_callback( $args ) {  
    $order_id = $args['order_id'];
    $order = wc_get_order( $order_id );
    if ( !$order ) return;

    // 获取新订单邮件实例
    $email_new_order = WC()->mailer()->get_emails()['WC_Email_New_Order'];
    
    // 强制启用邮件发送(忽略后台开关)
    $email_new_order->enabled = 'yes';
    
    // 填充邮件必要参数(复用WooCommerce模板变量)
    $email_new_order->recipient = $email_new_order->get_option( 'recipient' );
    $email_new_order->find = array( '{order_date}', '{order_number}' );
    $email_new_order->replace = array( 
        date_i18n( wc_date_format(), strtotime( $order->get_date_created() ) ), 
        $order->get_order_number() 
    );
    
    // 获取邮件内容(优先HTML格式, fallback到纯文本)
    $message = $email_new_order->get_content_html();
    if ( empty( $message ) ) {
        $message = $email_new_order->get_content_plain();
    }
    
    // 执行发送
    $email_new_order->send( 
        $email_new_order->recipient, 
        $email_new_order->get_subject(), 
        $message, 
        $email_new_order->get_headers(), 
        $email_new_order->get_attachments() 
    );
}

方案二:修改邮件启用状态判断(复用内置trigger逻辑)

通过过滤器动态控制邮件的启用状态,仅在你的自动化工具触发时允许发送,其他场景遵循后台开关设置。

// 动态控制新订单邮件的启用状态
add_filter( 'woocommerce_email_enabled_new_order', 'custom_new_order_email_status', 10, 2 );
function custom_new_order_email_status( $enabled, $order ) {
    // 检查是否是自动化工具触发的请求(通过当前钩子上下文判断)
    if ( did_action( 'email_callback' ) ) {
        return true;
    }
    // 其他场景保持后台设置的关闭状态
    return false;
}

// 你的回调函数保持不变,现在后台关闭开关也能正常触发,且不会重复发送
add_action( 'email_callback', 'email_callback' ); 
function email_callback( $args ) {  
    $email_new_order = WC()->mailer()->get_emails()['WC_Email_New_Order'];
    $email_new_order->trigger( $args['order_id'] );
}

方案选择建议

  • 方案一更灵活,适合需要自定义邮件内容、收件人或发送时机的场景,完全脱离内置触发逻辑的限制。
  • 方案二更简洁,复用WooCommerce原生的trigger()方法和模板逻辑,适合不需要额外定制的场景。

扩展提示

如果需要处理其他类型的邮件(比如处理中邮件、完成邮件),只需要替换对应的邮件类(如WC_Email_Customer_Processing_Order)和对应的钩子/过滤器即可,逻辑完全一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 13:40:59