Skip to main content

Overview

WooCommerce includes a comprehensive email notification system that automatically sends emails to customers and store administrators for various order events. The system is highly customizable through hooks, filters, and custom email classes.

Default WooCommerce Emails

WooCommerce sends these emails by default:

Customer Emails

New Order

Sent to customers when a new order is placed.

Processing Order

Sent when order status changes to Processing.

Completed Order

Sent when order status changes to Completed.

Refunded Order

Sent when an order is refunded.

Cancelled Order

Sent when an order is cancelled.

Failed Order

Sent when an order payment fails.

Customer Invoice

Manual invoice email that can be sent by admin.

Customer Note

Sent when a customer note is added to an order.

Reset Password

Password reset email for customer accounts.

New Account

Welcome email when a customer account is created.

Admin Emails

  • New Order: Notifies admin when new order is received
  • Cancelled Order: Notifies admin when order is cancelled
  • Failed Order: Notifies admin when order payment fails

Email Template Structure

WooCommerce email templates follow this hierarchy:
plugins/woocommerce/templates/emails/
├── admin-cancelled-order.php
├── admin-failed-order.php
├── admin-new-order.php
├── customer-completed-order.php
├── customer-invoice.php
├── customer-new-account.php
├── customer-note.php
├── customer-processing-order.php
├── customer-refunded-order.php
├── customer-reset-password.php
├── email-header.php              # Email header
├── email-footer.php              # Email footer
├── email-styles.php              # Inline CSS styles
└── email-addresses.php           # Customer addresses

Template Overrides

Override email templates in your theme:
1

Create email directory in your theme

mkdir -p wp-content/themes/your-theme/woocommerce/emails/
2

Copy template file

Copy the template from WooCommerce to your theme:
cp plugins/woocommerce/templates/emails/customer-completed-order.php \
   themes/your-theme/woocommerce/emails/
3

Customize the template

Edit the template in your theme directory. Your changes will override the default.
Always maintain the same directory structure. Template overrides in incorrect locations won’t work.

Customizing Email Content

Email Heading and Subject

Customize email headings and subjects with filters:
// Customize completed order email subject
add_filter( 'woocommerce_email_subject_customer_completed_order', function( $subject, $order ) {
    return sprintf( 'Your order #%s has been shipped!', $order->get_order_number() );
}, 10, 2 );

// Customize completed order email heading
add_filter( 'woocommerce_email_heading_customer_completed_order', function( $heading, $order ) {
    return 'Your order is on its way!';
}, 10, 2 );

// Customize new order email subject (admin)
add_filter( 'woocommerce_email_subject_new_order', function( $subject, $order ) {
    return sprintf( 'New order #%s - %s', $order->get_order_number(), $order->get_billing_email() );
}, 10, 2 );

Adding Custom Content

Add content before or after various sections:
// Add content before email header
add_action( 'woocommerce_email_header', function( $email_heading, $email ) {
    if ( $email->id === 'customer_completed_order' ) {
        echo '<p style="text-align:center; font-weight:bold;">🎉 Thank you for your purchase!</p>';
    }
}, 10, 2 );

// Add content after order details
add_action( 'woocommerce_email_after_order_table', function( $order, $sent_to_admin, $plain_text, $email ) {
    if ( $email->id === 'customer_processing_order' ) {
        echo '<p>Your order will be processed within 24 hours.</p>';
    }
}, 10, 4 );

// Add content before email footer
add_action( 'woocommerce_email_footer', function( $email ) {
    echo '<p>Follow us on social media: @yourstore</p>';
} );

Available Email Hooks

Header Hooks:
  • woocommerce_email_header - Before email header
Body Hooks:
  • woocommerce_email_before_order_table - Before order details
  • woocommerce_email_after_order_table - After order details
  • woocommerce_email_order_meta - Order meta section
  • woocommerce_email_customer_details - Customer details section
Footer Hooks:
  • woocommerce_email_footer - Before email footer
Product Hooks:
  • woocommerce_order_item_name - Product name in email
  • woocommerce_order_item_quantity_html - Product quantity display

Styling Emails

Customizing Email Styles

Email styles are defined inline for email client compatibility:
// Customize email styles
add_filter( 'woocommerce_email_styles', function( $css ) {
    $css .= '
        #template_header {
            background-color: #843cfb !important;
            border-bottom: 0 !important;
        }
        #template_header h1 {
            color: #ffffff !important;
        }
        a {
            color: #843cfb !important;
        }
    ';
    return $css;
} );

Using Custom Email Template Colors

Set custom colors in WooCommerce settings:
// Programmatically set email template colors
add_filter( 'woocommerce_email_background_color', function( $color ) {
    return '#f5f5f5';
} );

add_filter( 'woocommerce_email_base_color', function( $color ) {
    return '#843cfb';
} );

add_filter( 'woocommerce_email_body_background_color', function( $color ) {
    return '#ffffff';
} );

add_filter( 'woocommerce_email_text_color', function( $color ) {
    return '#333333';
} );

Creating Custom Emails

Create a completely custom email class:
1

Create email class

Create a new class extending WC_Email:
class WC_Custom_Email extends WC_Email {
    
    public function __construct() {
        $this->id             = 'custom_email';
        $this->title          = 'Custom Email';
        $this->description    = 'Custom email sent on specific trigger';
        $this->template_html  = 'emails/custom-email.php';
        $this->template_plain = 'emails/plain/custom-email.php';
        $this->template_base  = plugin_dir_path( __FILE__ ) . 'templates/';
        
        // Triggers
        add_action( 'your_custom_action', array( $this, 'trigger' ), 10, 2 );
        
        // Call parent constructor
        parent::__construct();
        
        // Recipient defaults to admin
        $this->recipient = $this->get_option( 'recipient', get_option( 'admin_email' ) );
    }
    
    public function trigger( $order_id, $custom_data = null ) {
        $this->setup_locale();
        
        if ( $order_id ) {
            $this->object = wc_get_order( $order_id );
            $this->custom_data = $custom_data;
            
            // Set recipient to customer email
            $this->recipient = $this->object->get_billing_email();
        }
        
        if ( $this->is_enabled() && $this->get_recipient() ) {
            $this->send(
                $this->get_recipient(),
                $this->get_subject(),
                $this->get_content(),
                $this->get_headers(),
                $this->get_attachments()
            );
        }
        
        $this->restore_locale();
    }
    
    public function get_content_html() {
        return wc_get_template_html(
            $this->template_html,
            array(
                'order'         => $this->object,
                'custom_data'   => $this->custom_data,
                'email_heading' => $this->get_heading(),
                'sent_to_admin' => false,
                'plain_text'    => false,
                'email'         => $this,
            ),
            '',
            $this->template_base
        );
    }
    
    public function get_content_plain() {
        return wc_get_template_html(
            $this->template_plain,
            array(
                'order'         => $this->object,
                'custom_data'   => $this->custom_data,
                'email_heading' => $this->get_heading(),
                'sent_to_admin' => false,
                'plain_text'    => true,
                'email'         => $this,
            ),
            '',
            $this->template_base
        );
    }
}
2

Register email class

Add your email to WooCommerce:
add_filter( 'woocommerce_email_classes', function( $email_classes ) {
    $email_classes['WC_Custom_Email'] = new WC_Custom_Email();
    return $email_classes;
} );
3

Create email template

Create templates/emails/custom-email.php in your plugin:
<?php
/**
 * Custom email template
 */
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

do_action( 'woocommerce_email_header', $email_heading, $email );
?>

<p>Hello <?php echo esc_html( $order->get_billing_first_name() ); ?>,</p>

<p>Your custom email content here.</p>

<?php if ( $custom_data ) : ?>
    <p>Custom data: <?php echo esc_html( $custom_data ); ?></p>
<?php endif; ?>

<?php
do_action( 'woocommerce_email_order_details', $order, $sent_to_admin, $plain_text, $email );
do_action( 'woocommerce_email_order_meta', $order, $sent_to_admin, $plain_text, $email );
do_action( 'woocommerce_email_customer_details', $order, $sent_to_admin, $plain_text, $email );
do_action( 'woocommerce_email_footer', $email );
4

Trigger the email

// Trigger your custom email
do_action( 'your_custom_action', $order_id, $custom_data );

Testing Emails

Send Test Emails

Manually trigger emails for testing:
// Get all email classes
$emails = WC()->mailer()->get_emails();

// Send a specific email
if ( isset( $emails['WC_Email_Customer_Completed_Order'] ) ) {
    $emails['WC_Email_Customer_Completed_Order']->trigger( $order_id );
}

Email Preview

Add email preview capability:
// Add email preview query parameter
add_action( 'template_redirect', function() {
    if ( isset( $_GET['preview_email'] ) && current_user_can( 'manage_woocommerce' ) ) {
        $order_id = isset( $_GET['order_id'] ) ? intval( $_GET['order_id'] ) : 0;
        $order = wc_get_order( $order_id );
        
        if ( ! $order ) {
            wp_die( 'Invalid order ID' );
        }
        
        $emails = WC()->mailer()->get_emails();
        $email_type = sanitize_key( $_GET['preview_email'] );
        
        if ( isset( $emails[ $email_type ] ) ) {
            echo $emails[ $email_type ]->get_content_html();
            exit;
        }
    }
} );

// Preview URL:
// /wp-admin/?preview_email=WC_Email_Customer_Completed_Order&order_id=123

Email Attachments

Add attachments to emails:
// Add PDF invoice to completed order email
add_filter( 'woocommerce_email_attachments', function( $attachments, $email_id, $order ) {
    if ( $email_id === 'customer_completed_order' ) {
        $invoice_path = '/path/to/invoice-' . $order->get_id() . '.pdf';
        
        if ( file_exists( $invoice_path ) ) {
            $attachments[] = $invoice_path;
        }
    }
    
    return $attachments;
}, 10, 3 );

Advanced Customization

Conditional Email Sending

Prevent emails from sending based on conditions:
// Prevent completed order email for free orders
add_filter( 'woocommerce_email_enabled_customer_completed_order', function( $enabled, $order ) {
    if ( $order->get_total() == 0 ) {
        return false;
    }
    return $enabled;
}, 10, 2 );

Custom Email Recipients

Add additional recipients:
// Add BCC to new order emails
add_filter( 'woocommerce_email_headers', function( $headers, $email_id, $order ) {
    if ( $email_id === 'new_order' ) {
        $headers .= "BCC: [email protected]\r\n";
    }
    return $headers;
}, 10, 3 );

Email Settings

Access email settings programmatically:
// Get email object
$emails = WC()->mailer()->get_emails();
$completed_email = $emails['WC_Email_Customer_Completed_Order'];

// Get settings
$enabled = $completed_email->is_enabled();
$subject = $completed_email->get_subject();
$heading = $completed_email->get_heading();

// Update settings
$completed_email->update_option( 'subject', 'New subject line' );
$completed_email->update_option( 'heading', 'New heading' );

Troubleshooting

Check WordPress email configuration:
// Test email sending
wp_mail( '[email protected]', 'Test Subject', 'Test message' );
Consider using an SMTP plugin like WP Mail SMTP or Post SMTP.
Ensure CSS is inline (email clients strip <style> tags):
// Use inline styles
echo '<p style="color: #333; font-size: 16px;">Content</p>';

Next Steps

Template Overrides

Learn about template customization

Hooks and Filters

Master WooCommerce hooks

Build docs developers (and LLMs) love