Dynamically determine whether to send a WooCommerce email.
A member of the Advanced WooCommerce Facebook group asked how to not send WooCommerce emails if the email address was of a certain format. I looked at a few approaches before deciding on a simple one.
Investigating various options
My first search was through the wp_mail() function but I could not find any filter that would prevent an email from being sent.
Next was WC_Email::send() but it doesn’t have the ability to stop an email from being sent.
I noticed that the individual email classes check whether their email is enabled before sending the email. This WC_Email::is_enabled() function does have a filter. It’s a dynamic filter where part of the filter name is the WC_Email::id member variable.
Experimenting
I searched the email classes for their WC_Email::id member variables and examined the WC_Email::object member variable that they pass to the filter function. For most of them it is set to a WC_Order object. This will contain the order contents and, of course, the customer email address.
I wrote a tiny filter function that would work for all the WooCommerce emails that passed an order object. The current_filter() function can be used to determine the active filter, if you want to tweak behaviour for different filters. I also experimented with accessing the order object e.g. calling WC_Order::get_order_number() and WC_Order::get_billing_email()).
The code
The skeleton code is very simple. The one function handles all the filter calls. The code checks for a specific email address. The Facebook group member needed to match emails with a specific format – a regular expression test with preg_match() would work for it.
Obviously the code could be changed to check other attributes of the order e.g. if certain items were in the order, or the total was over or under a certain amount.
hi,
can we change the conditions with gatway for exmple if coustomer pay with paypal or klarna, not send order procssing email if yes please send me the code I really looking for this solutions
thanks
@Jahn: If you only want to change the order processing email you will probably need to call the current_filter() function first and then I think that you can check the payment method with $order->get_payment_method(). If it is PayPal or Klarna you can then return false.
I don’t know whether $order->get_payment_method() will return a string or an object so you will need to do some testing e.g. add these lines to the top of the function:
error_log( 'Filter: ' . var_export( current_filter(), true ) ); error_log( 'Payment method: ' . var_export( $order->get_payment_method(), true ) );
Hi Damien,
Great piece of code that might be of use to me! Except the last part. Could you filter on product id’s? So if product id is 20031 no emails are sent?
@Sander: You would have to look at the $order item and loop through the items in the order. This is covered in WooCommerce: Get Order Info (total, items, etc) From $order Object
It would look something like:
foreach ( $order->get_items() as $item_id => $item ) { if ( 20031 == $item->get_product_id() ) { return false; // Do not send the email. } }
How can I have fair access to the $order object? So $order = wc_get_order( $object );
should i do? Otherwise $id= $order->get_id();
can i use it?
@sezer: You can get the order number with
$order_number = $object->get_order_number();
By using this code i am getting fatal error under woocommerce > settings > email tab Uncaught Error: Call to a member function get_billing_email() on null
@Codeixer – Thank you for reporting that bug. I found that $object is null when in WooCommerce/Settings/Email so I added a check for this and return early.
I have updated the code: https://gist.github.com/damiencarbery/8951165f836ef032d709a03927f548a1#file-conditional-wc-email-sending-php
after post this comment I do the same that you added. also, thanks for the article.
Hi. What line of code would work to block emails from a certain domain?
@Alfredo – You can add a test like this:
if ( false !== strpos( $object->get_billing_email(), '@domain.com' ) ) { return false; }
function dcwd_conditionally_send_wc_email( $whether_enabled, $object ) { // When in admin $object is null so return early. if ( null == $object ) { return $whether_enabled; } //error_log( 'is_enabled: ' . current_filter() . ' - Order: ' . $object->get_order_number() ); // Debugging info.
//$order = wc_get_order( $object->get_order_number()); $orderno = $object->get_order_number() $control = get_post_meta($orderno, "tamam_mail", true)
if ( strstr($object->get_billing_email(), "mailsiz") = false and $control != "atildi" ) { //error_log( "Do not send email." ); // Only for debugging. update_post_meta($orderno, "tamam_mail", "atildi") return true; } else{ return false; }
return $whether_enabled; }
where am i doing wrong?
@Sezer: I think that you have a small error in one line:
if ( strstr($object->get_billing_email(), "mailsiz") = false and $control != "atildi" ) {
should be
if ( false == strstr($object->get_billing_email(), "mailsiz") && $control != "atildi" ) {
I moved the ‘false’ to be in front of the strstr call and I changed = to ==. If I used = when false is in front it would cause an error. In your code you are assigning strstr() to false because it used one =.
Please try that and tell me if it works. You can also uncomment the ‘Do not send email’ error_log call so that you can check your logs to see if it worked.
@Sezer: I just found the real error – there is no semi-colon at the end of the line:
$orderno = $object->get_order_number()
how to disable woocommerce new order emails programmatically
@Raman: To disable the New Order email, please try this code:
add_filter( 'woocommerce_email_enabled_new_order', 'rg_disable_new_order_email', 10, 2 ); function rg_disable_new_order_email( $enabled, $object ) { return false; }
disable woocommerce processing order and complete order emails programmatically
Reply
@Khush/Raman: To disable the Processing order and Complete Order emails, please update the code I sent you earlier to:
add_filter( 'woocommerce_email_enabled_new_order', 'rg_disable_order_emails', 10, 2 ); add_filter( 'woocommerce_email_enabled_customer_completed_order', 'rg_disable_order_emails', 10, 2 ); add_filter( 'woocommerce_email_enabled_customer_processing_order', 'rg_disable_order_emails', 10, 2 ); function rg_disable_order_emails( $enabled, $object ) { return false; }