How to Send Custom Email Notifications in WordPress

WordPress’s wp_mail() function wraps PHP’s native mail() and adds filter hooks that let you control the sender name, sender address, content type, and headers from anywhere in your code — no plugin required.

Problem: How do you send a custom HTML email from WordPress — triggered by a form submission, a post status change, or any custom event — without installing a plugin?

Solution: Use wp_mail() with a Content-Type: text/html header added via the wp_mail_content_type filter. It respects the site's configured mail transport (PHP mail, SMTP, or a plugin) and reads the From address from WordPress settings.

Sending a basic HTML email:

add_filter( 'wp_mail_content_type', function() {
    return 'text/html';
} );

$to      = 'recipient@example.com';
$subject = 'Your order has shipped';
$body    = '
    <p>Hi there,</p>
    <p>Your order #<strong>1042</strong> has been shipped and is on its way.</p>
    <p>Thanks for shopping with us.</p>
';
$headers = [
    'From: My Shop <shop@example.com>',
    'Reply-To: support@example.com',
    'Cc: manager@example.com',
];

wp_mail( $to, $subject, $body, $headers );

// Important: reset content type after sending to avoid affecting other emails
remove_filter( 'wp_mail_content_type', function() {
    return 'text/html';
} );

A cleaner approach — use a named function so it can be removed:

function set_html_content_type() {
    return 'text/html';
}

add_filter( 'wp_mail_content_type', 'set_html_content_type' );
wp_mail( $to, $subject, $body, $headers );
remove_filter( 'wp_mail_content_type', 'set_html_content_type' );

Override the default "WordPress" sender name and address globally:

add_filter( 'wp_mail_from',      function() { return 'noreply@example.com'; } );
add_filter( 'wp_mail_from_name', function() { return 'My Website'; } );

NOTE: For reliable deliverability, configure an SMTP plugin (WP Mail SMTP, Post SMTP) to route emails through a transactional mail service like SendGrid, Mailgun, or Amazon SES. PHP's built-in mail() function is frequently blocked or flagged as spam by receiving servers.