All transactional emails in WordPress are sent by the wp_mail() function which is one of the “pluggable” functions (can be overwritten) in wp-includes/pluggable.php.
It sets the following email headers by default:
- “From” email address:
wordpress@example.comwhereexample.comis thehome_urlof the primary sitenetwork_home_url(), unless customized via thewp_mail_fromfilter. - “From” name:
WordPressunless customized via thewp_mail_from_namefilter.
It uses the PHPMailer library for sending email behind the scenes (included with WordPress), which configures the following additional headers:
- SMTP envelope
SenderorMAIL FROMin SMTP (which gets turned intoReturn-Pathby the recipient server) toini_get('sendmail_from'), if set; or dynamically resolved by the mail transfer agent.
This address is used for bounces or notifications about any delivery issues. Importantly, it is also used for SFP and DMARC alignment — the hostname (domain) of Return-Path should match the From domain.

On many hosts the Sender is set to something like www-data@example.com which is (1) an invalid/inactive address which can’t even process the bounce emails, (2) will fail the SFP alignment checks by Gmail and other email providers.
Use the phpmailer_init filter to set the Sender email address to the From address:
add_action(
'phpmailer_init',
function ( $phpmailer ) {
$phpmailer->Sender = $phpmailer->From;
}
);
Tip: Use the Mail Pilot plugin to configure the From email address and name, and ensure that Return-Path email matches the From email address for SFP and DMARC alignment. It also supports DKIM signing for extra reliable delivery.
Transactional Email Types
Password Reset
The password reset links in the footer of the login form wp-login.php point to the main site of the network in wp_lostpassword_url() instead of the current site:
function wp_lostpassword_url( $redirect = '' ) {
$args = array(
'action' => 'lostpassword',
);
if ( ! empty( $redirect ) ) {
$args['redirect_to'] = urlencode( $redirect );
}
if ( is_multisite() ) {
$blog_details = get_site();
$wp_login_path = $blog_details->path . 'wp-login.php';
} else {
$wp_login_path = 'wp-login.php';
}
$lostpassword_url = add_query_arg( $args, network_site_url( $wp_login_path, 'login' ) );
// ...
}
Same with the password reset form, which sends a POST request to the main site of the network:
<form name="lostpasswordform" id="lostpasswordform" action="<?php echo esc_url( network_site_url( 'wp-login.php?action=lostpassword', 'login_post' ) ); ?>" method="post">
...
</form>
Technically, WordPress supports all password reset functionality at the sub-site level. Use the following filters to adjust the URLs to point to the current sub-site to align the password reset experience with the branding of each site:
// Allow password reset from the specific blog.
function wpelevator_password_reset_local( $url ) {
// Specify `/` because both methods have different defaults.
return str_replace( network_site_url( '/' ), site_url( '/' ), $url );
}
add_filter( 'retrieve_password_message', 'wpelevator_password_reset_local' );
add_filter( 'lostpassword_url', 'wpelevator_password_reset_local' );
// Adjust the form action URL for the password reset form.
add_filter(
'network_site_url',
function ( $url, $path, $scheme ) {
if ( 'login_post' === $scheme ) {
return wpelevator_password_reset_local( $url );
}
return $url;
},
10,
3
);
Resources
- wp_mail() is NOT broken by Konstantin.

Leave a Reply