Search code examples
phpwordpresswoocommerceadminemail-notifications

Change programmatically the email for new order, cancelled order and failed order WooCommerce notifications


when you go to WooCommerce->Settings->Emails you can set which email address you want for new orders, failed orders, cancelled orders and so on.

I'm trying to see how I can change all of them programmatically, so I created a little template with an input field and a submit button to change these emails all at once, but the only email address that changes is the one for Email Sender Options (the setting at the bottom of the WooCommerce->Settings->Emails page), and not the ones for new order, cancelled order and failed orders.

Inspecting the possible hooks, I thought the following code should do the trick:

function change_notification_email_callback() {
    // Log form data for debugging
    error_log( print_r( $_POST, true ) );

    if ( isset( $_POST['new_notification_email'] ) && ! empty( $_POST['new_notification_email'] ) ) {
        $new_email = sanitize_email( $_POST['new_notification_email'] );

        // Log current value of woocommerce_new_order_recipient option
        $old_recipient_email = get_option( 'woocommerce_new_order_recipient' );
        error_log( 'Old Recipient Email: ' . $old_recipient_email );

        // Update the notification email
        update_option( 'woocommerce_email_from_address', $new_email );
        update_option( 'woocommerce_new_order_email', $new_email );
        update_option( 'woocommerce_cancelled_order_email', $new_email );
        update_option( 'woocommerce_failed_order_email', $new_email );

        // Log updated value of woocommerce_new_order_recipient option
        $updated_recipient_email = get_option( 'woocommerce_new_order_recipient' );
        error_log( 'Updated Recipient Email: ' . $updated_recipient_email );

        // Log updated value of woocommerce_cancelled_order_recipient option
        $updated_recipient_email_cancelled = get_option( 'woocommerce_cancelled_order_recipient' );
        error_log( 'Updated Recipient Email for cancelled: ' . $updated_recipient_email_cancelled );

        // Set success message
        $message = 'Notification email changed successfully.';
        $notice_type = 'success';
    } else {
        // Set error message
        $message = 'Failed to change notification email. Please enter a valid email.';
        $notice_type = 'error';
    }
    
    // Set admin notice
    add_flash_notice( $message, $notice_type );

    // Redirect back to the WooCommerce dashboard page after email change
    wp_redirect( admin_url( 'admin.php?page=wc-dashboard' ) );
    exit;
}

So again, under the // Update the notification emails, only the first update_option works, and even though the logs show that all instances were changed (woocommerce_email_from_address, woocommerce_new_order_email, etc) and even looking up those fields in the wp_options table they show updated, but when I check the WooCommerce->Settings->Emails page, those are still unchanged (image below shows what I mean). I did a test to put a order through to make sure it wasn't cache or something, but it's going to whatever email is there. Does anyone know what else I can try?

enter image description here


Solution

  • You are not using the correct option keys for "New order", "Cancelled order" and "Failed order". For those 3, each option is an array of settings…

    Important: You will need, only once, to manually set for each of those 3 notifications a new email and update to create the setting options. Once done you will have in your database under wp_options the following:

    enter image description here

    Once done, you can use the following revised code:

    function change_notification_email_callback() {
        if ( isset( $_POST['new_notification_email'] ) && ! empty( $_POST['new_notification_email'] ) ) {
            $new_email = sanitize_email( $_POST['new_notification_email'] );
    
            // Array of option keys for email settings
            $email_setting_keys = array(
                'woocommerce_new_order_settings'       => __('New order'),
                'woocommerce_cancelled_order_settings' => __('Cancelled order'),
                'woocommerce_failed_order_settings'    => __('Failed order'),
            );
            $updated = array(); // Initializing
        
            // Loop through the emails settings keys
            foreach ( $email_setting_keys as $key => $label ) {
                $settings = get_option( $key, array() ); // Get option settings array for the current notification
    
                if ( ! empty($settings) && isset($settings['recipient']) ) {
                    $settings['recipient'] = $new_email; // change recipient with the new email 
                    update_option( $key, $settings ); // Update/save settings for the current notification
                    $updated[] = $label; // Tag as updated
                }
            }
    
            // Update the "from Address" email
            update_option( 'woocommerce_email_from_address', $new_email );
            $updated[] = __('From Address'); // Tag as updated
    
            // Set success message
            $message = sprintf( __('Email changed successfully for "%s" notifications.' ), implode('", "', $updated) );
            $notice_type = 'success';
        } else {
            // Set error message
            $message = __('Failed to change notification email. Please enter a valid email.');
            $notice_type = 'error';
        }
        add_flash_notice( $message, $notice_type ); // Set admin notice
    
        // Redirect back to the WooCommerce dashboard page after email change
        wp_redirect( admin_url( 'admin.php?page=wc-dashboard' ) );
        exit();
    }
    

    Code goes in functions.php file of your child theme (or in a plugin). It should work.