Add account email conditionally on Customer processing Order email notification in Woocommerce - php

So this is more of my solution here but I wanted to open this up to see if the community could find a better alternative or potentially find use for this solve.
Our client asked us for the following alteration to the email order receipts received on order creation: The receipts should go to the account holder and cc the billing email if it's different
As we know Woocommerce by default sends the order receipt (Customer Processing) based on only the set billing_email on checkout so I started to look for a way to add on the tack on the account owner email to it as well.
I did some digging and found a few answers on Stackoverflow on how to do this and the proposed solution utilized the woocommerce_email_recipient_customer_processing_order built-in function. This approach would only add on the email in the "to" header -less than ideal. It also doesn't account for potential duplicate sends to the same email address which, at least in the case of our server here, caused the email to not be delivered. No bueno.
The function below represents a work around this wherein we're calling upon the WP Core function wp_get_current_user() to obtain the email that the user is associated with and then checking whether it's the same as the billing email.
add_filter( 'woocommerce_email_headers', 'add_email_recipient', 10, 3);
function add_email_recipient($header, $email_id, $order) {
// Only for "Customer Processing Emails" email notifications
if( ! ( 'customer_processing_order' == $email_id ) ) return;
$curr_user = wp_get_current_user();
$account_holder_email = $curr_user->user_email;
$billing_email = $order->get_billing_email();
$header ='';
if ( $account_holder_email != $billing_email ) {
$header .= 'Cc: '.$account_holder_email;
}
return $header;
}
The logic intends to flow the following way:
Adjust the woocommerce email headers
If the email is the "customer_processing_order" continue
Get the current user email
Get the billing email set in the order
assign a CC field of the current user email
done
As far as I could tell there wasn't an easier way to handle this so I'm posting this up here in the hopes to see if someone else has a more elegant solution. The above code works by placing in the child theme functions.php.

You can't get the current user or the current user ID on email notification hooks.
You need first to get the customer ID from the order, then you can get the WP_User object to get the account email.
There is 2 different ways to add the customer account email when it's different from the order billing email in Customer processing order email notification:
1) Add the customer account email as an additional recipient:
add_filter( 'woocommerce_email_recipient_customer_processing_order', 'add_customer_processing_order_email_recipient', 10, 2 );
function add_customer_processing_order_email_recipient( $recipient, $order ) {
// Not in backend (avoiding errors)
if( is_admin() ) return $recipient;
if( $order->get_customer_id() > 0 ){
// Get the customer WP_User object
$wp_user = new WP_User($order->get_customer_id());
if ( $wp_user->user_email != $order->get_billing_email() ) {
// Add account user email to existing recipient
$recipient .= ','.$wp_user->user_email;
}
}
return $recipient;
}
Code goes in function.php file of your active child theme (active theme). It should works.
2) Add the customer account email as a CC email address:
add_filter( 'woocommerce_email_headers', 'add_cc_email_to_headers', 10, 3);
function add_cc_email_to_headers($header, $email_id, $order) {
// Only for "Customer Processing Emails" email notifications
if( 'customer_processing_order' == $email_id ) {
if( $order->get_customer_id() > 0 ){
// Get the customer WP_User object
$wp_user = new WP_User($order->get_customer_id());
if ( $wp_user->user_email != $order->get_billing_email() ) {
$header .= 'Cc: ' . utf8_decode($order->get_formatted_billing_full_name() . ' <' . $wp_user->user_email . '>') . "\r\n";
}
}
}
return $header;
}
Code goes in function.php file of your active child theme (active theme). It should works.

Related

Add recipients from product custom fields to Woocommerce new order email notification

In Woocommerce, I would like to add a email custom field with the Advanced Custom Fields plugin to products post type.
If customer place an order I would like to add the corresponding email adresses for each order items to new order email notification .
How to add recipients from product custom fields to Woocommerce new order email notification?
For "New order" email notification, here is the way to add custom emails from items in the order (The email custom field is set with ACF in the products).
So you will set first a custom field in ACF for "product" post type:
Then you will have in backend product edit pages:
Once done and when that product custom-fields will be all set with an email adress, you will use this code that will add to "New order" notification the emails for each corresponding item in the order:
add_filter( 'woocommerce_email_recipient_new_order', 'add_item_email_to_recipient', 10, 2 );
function add_item_email_to_recipient( $recipient, $order ) {
if( is_admin() ) return $recipient;
$emails = array();
// Loop though Order IDs
foreach( $order->get_items() as $item_id => $item ){
// Get the student email
$email = get_field( 'product_email', $item->get_product_id() );
if( ! empty($email) )
$emails[] = $email; // Add email to the array
}
// If any student email exist we add it
if( count($emails) > 0 ){
// Remove duplicates (if there is any)
$emails = array_unique($emails);
// Add the emails to existing recipients
$recipient .= ',' . implode( ',', $emails );
}
return $recipient;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
Related: Send Woocommerce Order to email address listed on product page

Send Woocommerce new order email notification from specific user role to specific user

We have a "main wholesaler" who is in charge of other wholesalers. This wholesaler is assigned to user role: wholesale_customer just as the other wholesalers.
This "main wholesaler" places orders for his stores, and the other wholesalers place orders for their own stores as normal.
I would like that the "main wholesaler" receive an email notification when the other wholesalers place their orders, so he will get notified when other wholesalers are ordering because he gets a commission.
So is there a way that we can make the "main wholesaler" to receive an email notification when the other wholesalers place their orders?
Maybe this can be done with a function somewhat like this:
WooCommerce email notifications: different email recipient for different cities
Any help is appreciated.
Updated (solved a bug in backend email settings)
The following function will send an additional "new order" email notidfication to the "Wholesale manager" when others wholesale_customer user roles will make a purchase.
You will just need to set in this function the User ID for the "Wholesale manager"…
add_filter( 'woocommerce_email_recipient_new_order', 'wholesale_manager_email_recipient', 20, 2 );
function wholesale_manager_email_recipient( $recipient, $order ) {
if( is_admin() ) return $recipient;
// Only for 'wholesale_customer' user role
if( is_admin() || ! user_can( $order->get_user_id(), 'wholesale_customer' ) )
return $recipient; // Exit if not a 'wholesale_customer'
// HERE Set the main wholesale manager user ID
$manager_id = 5;
$manager_user = new WP_User( $manager_id );
$manager_email = $manager_user->user_email;
// Add manager email when other 'wholesale_customer' place orders
if ( $order->get_user_id() != $manager_id )
$recipient .= ',' . $manager_email; // coma separate emails
return $recipient;
}
Code goes in function.php file of your active child theme (or theme). Tested and works.

Conditional custom New Order Woocommerce email notification on different recippients

Okay I have had a question come from a client that doesn't seem impossible, but correctly setting up the conditions is a problem for me. Here is what is happening and what I need. i would really this to be a function of possible.
The store has a user hierarchy. There are 2x Super Admins (ID: admin), 5x Admins (ID: admin2), 15x Bank Customers (ID: banks), and 2x Real Estate customers (ID: real estate). I have already setup the custom users with the ID's. No products have pricing. Everything is invoiced in an email with the order_info. Everything is paid at a later date in house. So the site really relies on emails.
If the 15x Bank Customers place a new_order, these new_order(s) need to send the email invoice to the 5x Admins.
If the 2x Real Estate customers place a new_order, these new_order(s) need to send the email invoice to the 5x Admins.
If the 5x Admins place a new_order, these new_order(s) need to send the email invoice to the 2x Super Admins.
I am not the greatest with php and what I had previous was very sloppy.
Any help?
You can use wc hook as follows in functions.php filr
add_action( 'woocommerce_new_order', 'send_email_to_admin', 1, 1 );
function send_email_to_admin($order_id) {
// use order id to find user id and send email
}
Using a custom function hooked in woocommerce_thankyou action hook, will allow you to make that conditional email notifications based on user roles and on custom multiple recipients.
You will need to replace admins and super admins email in this function.
You will need also to check that the users roles are matching in the 3 if statements… The ID for Real estate can't have a space normally and should be instead: 'real_estate'
This will send email notifications for orders that have a status like 'on-hold', 'pending', 'processing' or 'completed'...
Once this custom email will be triggered a custom field '_custom_emails_sent' will be set for the order.
Here is the code:
add_action( 'woocommerce_thankyou', 'custom_new_order_email_notifications', 10, 1 );
function custom_new_order_email_notifications( $order_id ){
// If Custom Emails already sent we exit
if( get_post_meta( $order_id, '_custom_emails_sent', true ) ) return;
$targeted_statuses = array( 'wc-on-hold', 'wc-pending', 'wc-processing', 'wc-completed' );
$order_status = get_post_status( $order_id );
// Only for the correct order statuses; If not we exit
if( ! in_array( $order_status, $targeted_statuses ) ) return;
// HERE (below) replace super admins and admins REAL emails
$super_admin_emails = array(
'supadmin1#example.com', 'supadmin2#example.com' );
$admin_emails = array(
'admin1#example.com', 'admin2#example.com',
'admin3#example.com', 'admin4#example.com', 'admin5#example.com' );
// Get the user of the order
$user_id = get_post_meta( $order_id, '_customer_user', true );
$user = get_userdata( $user_id );
$recipient = '';
// 1. Bank Customers user role
if( in_array('banks', $user->roles) ){
$recipients = implode(',', $admin_emails);
}
// 2. Real estate Customers user role
if( in_array('real_estate', $user->roles) ){
$recipients = implode(',', $admin_emails);
}
// 3. Admins Customers user role
if( in_array('admin2', $user->roles) ){
$recipients = implode(',', $admin_emails);
}
// Sending new order email notification to the targeted recipients
if( '' != $recipients ){
$mailer = WC()->mailer()->get_emails();
$mailer['WC_Email_New_Order']->recipient = $recipients;
$mailer['WC_Email_New_Order']->trigger( $order_id ); // sending
// We set a custom field that will avoid repetitive sends
update_post_meta( $order_id, '_custom_emails_sent', '1' );
}
}
Code goes in function.php file of your active child theme (or active theme).
Tested and works

Send Woocommerce Order to email address listed on product page

I'm using Woocommerce and the Product Addons plugin to add extra fields to a product. One of those fields is an email address to let people send the confirmation of the order to a DIFFERENT address than the billing address shown on the checkout page. Emails should be sent to both addresses.
Any thoughts on maybe how to modify the functions.php file to do this?
In the woocommerce_email_recipient_{$this->id} filter hook, you can use the $order argument to get your 2nd email.
But first Lets add globally an email field with the Product Add-ons plugin…
The add on field on the product (fill the field and add to cart):
This "Email" field in order-received (Thank you) page, after checkout:
As you can notice the label of this field is "Email"…
Now if I look in the database in wp_woocommerce_order_itemmeta for this order I can see for the meta_key "Email" the meta_value "loic#TheAztec.com" :
Now I can set the correct meta_key in the code below to get my email.
Here is the code that will add this additional email recipient for processing and completed customer order email notifications:
add_filter( 'woocommerce_email_recipient_customer_completed_order', 'additional_customer_email_recipient', 10, 2 ); // Processing Order
add_filter( 'woocommerce_email_recipient_customer_processing_order', 'additional_customer_email_recipient', 10, 2 ); // Completed Order
function additional_customer_email_recipient( $recipient, $order ) {
if ( ! is_a( $order, 'WC_Order' ) ) return $recipient;
$additional_recipients = array(); // Initializing…
// Iterating though each order item
foreach( $order->get_items() as $item_id => $item_data ){
// HERE set the the correct meta_key (like 'Email') to get the correct value
$email = wc_get_order_item_meta( $item_id, 'Email', true );
// Avoiding duplicates (if many items with many emails)
// or an existing email in the recipient
if( ! in_array( $email, $additional_recipients ) && strpos( $recipient, $email ) === false )
$additional_recipients[] = $email;
}
// Convert the array in a coma separated string
$additional_recipients = implode( ',', $additional_recipients);
// If an additional recipient exist, we add it
if( count($additional_recipients) > 0)
$recipient .= ','.$additional_recipients;
return $recipient;
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
Tested and works.
You can add below code in your function.php
add_filter( 'woocommerce_email_recipient_customer_completed_order', 'your_email_recipient_filter_function', 10, 2);
function your_email_recipient_filter_function($recipient, $object) {
$recipient = $recipient . ', me#myemail.com';
return $recipient;
}
and if you want to send email in BCC then please try below code:
add_filter( 'woocommerce_email_headers', 'mycustom_headers_filter_function', 10, 2);
function mycustom_headers_filter_function( $headers, $object ) {
if ($object == 'customer_completed_order') {
$headers .= 'BCC: My name <my#email.com>' . "\r\n";
}

WooCommerce email notifications: different email recipient for different cities

I using Woocommerce and actually I receive order notifications only to one email. I would like to receive notifications about orders in 2 different emails depending on customer location:
For customer from zone 1 (Germany) I would like to receive the email notifications at Mail #1 (mail1#mail.com),
For all other zones like zone 2 (Mexico) I would like to receive the email notifications at Mail #2 (mail2#mail.com).
I looking for some functions on net, but I was find only funtcions to send to two email adresses, but without any If condition.
What I will need is something like that:
if ($user->city == 'Germany') $email->send('mail1#mail.com')
else $email->send('mail2#mail.com')
Which hook can I use to get this working?
Thanks.
You can use a custom function hooked in woocommerce_email_recipient_{$this->id} filter hook, targeting 'New Order' email notification, this way:
add_filter( 'woocommerce_email_recipient_new_order', 'diff_recipients_email_notifications', 10, 2 );
function diff_recipients_email_notifications( $recipient, $order ) {
if ( ! is_a( $order, 'WC_Order' ) ) return $recipient;
// Set HERE your email adresses
$email_zone1 = 'name1#domain.com';
$email_zone_others = 'name2#domain.com';
// Set here your targeted country code for Zone 1
$country_zone1 = 'GE'; // Germany country code here
// User Country (We get the billing country if shipping country is not available)
$user_country = $order->shipping_country;
if(empty($user_shipping_country))
$user_country = $order->billing_country;
// Conditionaly send additional email based on billing customer city
if ( $country_zone1 == $user_country )
$recipient = $email_zone1;
else
$recipient = $email_zone_others;
return $recipient;
}
For WooCommerce 3+, some new methods are required and available from WC_Order class concerning billing country and shipping country: get_billing_country() and get_shipping_country() …
Usage with $order instance object:
$order->get_billing_country(); // instead of $order->billing_country;
$order->get_shipping_country(); // instead of $order->shipping_country;
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
Code is tested and works.
Related answers:
How to get order ID in woocommerce_email_headers hook
Send on-hold order status email notification to admin

Categories