禁用WooCommerce新订单邮件后,无法通过代码触发发送该邮件
解决WooCommerce自动化工具邮件重复发送问题
问题根源
WooCommerce的内置邮件类(比如WC_Email_New_Order)会优先检查后台的邮件开关状态,关闭开关后trigger()方法会直接跳过发送逻辑;但开启开关后,内置的订单状态钩子又会自动触发邮件,导致和你的自动化工具重复发送。
可行解决方案
方案一:手动构造并发送邮件(完全绕开内置触发逻辑)
直接跳过内置的开关检查和自动触发钩子,手动调用邮件发送逻辑,同时禁用内置的自动触发。
- 首先禁用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' ) ); }
- 修改你的自动化回调函数,手动发送邮件:
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
相关产品推荐
相关产品推荐

