---
title: WordPress Emails
date: 2025-05-13T08:03:46+00:00
modified: 2025-05-14T07:09:51+00:00
image:: https://wpelevator.com/wp-content/uploads/sites/12/2025/05/wordpress-email-spf-dkim-dmarc.png
permalink: https://wpelevator.com/guides/wordpress-emails
post_type: page
author:
  name: Kaspars
  avatar: https://secure.gravatar.com/avatar/92bfcd3a8c3a21a033a6484d32c25a40b113ec6891f674336081513d5c98ef76?s=96&d=robohash&r=g
---

# WordPress Emails

All transactional emails in WordPress are sent by the [`wp_mail()` function](https://github.com/WordPress/WordPress/blob/f5f3764a9feb2fdfde23a1498e2e07a3b5964e60/wp-includes/pluggable.php#L146-L587) 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.com` where `example.com` is the `home_url` of the primary site `network_home_url()`, unless customized via the [`wp_mail_from` filter](https://developer.wordpress.org/reference/hooks/wp_mail_from/).
- “From” name: `WordPress` unless customized via the [`wp_mail_from_name` filter](https://developer.wordpress.org/reference/hooks/wp_mail_from_name/).

It uses the `PHPMailer` library for sending email behind the scenes ([included with WordPress](https://github.com/WordPress/WordPress/tree/master/wp-includes/PHPMailer)), which configures the following additional headers:

- SMTP envelope `Sender` or `MAIL FROM` in SMTP (which gets turned into `Return-Path` by the recipient server) [to `ini_get('sendmail_from')`](https://github.com/WordPress/WordPress/blob/f5f3764a9feb2fdfde23a1498e2e07a3b5964e60/wp-includes/PHPMailer/PHPMailer.php#L1741-L1746), if set; or [dynamically resolved by the mail transfer agent](https://github.com/WordPress/WordPress/blob/f5f3764a9feb2fdfde23a1498e2e07a3b5964e60/wp-includes/PHPMailer/PHPMailer.php#L1755-L1760).

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.

![Diagram of how server IP, Return-Path and From headers are used for DKIM and SFP aligment ](https://wpelevator.com/wp-content/uploads/sites/12/2025/05/wordpress-email-spf-dkim-dmarc.png?strip=all&quality=90&resize=2380,1417)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](https://wpelevator.com/plugins/mail-pilot) 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](https://github.com/WordPress/WordPress/blob/f5f3764a9feb2fdfde23a1498e2e07a3b5964e60/wp-includes/general-template.php#L658-L685) 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](https://github.com/WordPress/WordPress/blob/f5f3764a9feb2fdfde23a1498e2e07a3b5964e60/wp-login.php#L897):

```
<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](https://konstantin.blog/2021/wp_mail-is-not-broken/) by Konstantin.