Get WooCommerce Email Classes in Backend

Like I’ve pointed in my comment, you can use wc()->mailer()->emails, which would give you a list of all the email class instances. Example:

// Get all the email class instances.
$emails = wc()->mailer()->emails;

// Prints all the email class names.
var_dump( array_keys( $emails ) );

// Access the default subject for new order email notifications.
$subject = $emails['WC_Email_New_Order']->get_default_subject();

The same ‘$emails’ can also be accessed from within a callback function hooked to the woocommerce_email_classes filter. Here is an example for overriding a specific class:

// By default, $emails is an array of '{CLASS NAME}' => {The class instance}.
add_filter( 'woocommerce_email_classes', function( $emails ){
    $emails['WC_Email_New_Order'] = include 'path/to/your/custom/class.php';
    /* Or if the class file is already "included":
    $emails['WC_Email_New_Order'] = new My_Custom_WC_Email_New_Order_Class();
    */

    return $emails;
} );

And (although you may already know) the email class files (e.g. class-wc-email-new-order.php) are stored in woocommerce/includes/emails.


A better way to access the emails property (or the class instances)

Use wc()->mailer()->get_emails(), except from within a callback function hooked to the woocommerce_email_classes filter.

// Both of these work, but the latter is preferred.
$emails = wc()->mailer()->emails;
$emails = wc()->mailer()->get_emails();

Additional Code

(These are in reply to your comments as well as the “UPDATE” part in your question.)

Can I use the $emails['WC_Email_New_Order']->template_html to force
custom template selection?

Yes, you can. However, the value needs to be a path relative to the custom WooCommerce templates directory in your theme; e.g. wp-content/themes/your-theme/woocommerce. So:

// This works, if wp-content/themes/your-theme/woocommerce/emails/your-custom-template.php
// exists.
$emails['WC_Email_New_Order']->template_html="emails/your-custom-template.php";

// But this doesn't work, even if the file exists.
$emails['WC_Email_New_Order']->template_html="/absolute/path/to/your-custom-template.php";

If you want to use an absolute path (e.g. in your custom plugin folder), you can use the woocommerce_locate_core_template filter:

// $a and $b can be ignored, but $file and $id are important
add_filter( 'woocommerce_locate_core_template', function( $file, $a, $b, $id ){
    if ( 'new_order' === $id ) {
        return '/absolute/path/to/your-custom-template.php';
    }

    return $file;
}, 10, 4 );

Leave a Comment