---
title: "Nice Default Emails"
description: "How Adminkeep's Nice Default Emails works: the 25 WordPress core emails it wraps in HTML, what the layout holds, what is left alone, the filter and WP-CLI."
source: https://adminkeep.com/docs/nice-default-emails/
---

Nice Default Emails sends the plain-text emails WordPress itself writes, such as password resets,
new-user notices and comment notifications, in a simple HTML layout with your site's name on it.
The text is unchanged; it gets a header, a card and a footer. This page is the reference; the
[Nice Default Emails](/nice-default-emails/) page has the overview.

## Turn it on

Go to **Settings → Adminkeep** and switch on **Nice Default Emails**, in the **Email** group.
There are no settings: one layout, coloured and named from the site. From then on, each of the
emails below goes out as HTML.

Nothing is stored. Switch the feature off and the next email goes out as plain text again.

## The emails it covers

25 emails: 19 on a single site, and 6 more that exist only on a multisite network. The id in
the first column is what the [filter](#for-developers) and the [WP-CLI commands](#wp-cli) call
each one.

### Accounts

| Id | Email |
|---|---|
| `password_reset` | Password reset link |
| `new_user` | New account: login details, to the user |
| `new_user_admin` | New account: notice to the site admin |
| `password_changed` | Password changed, to the user |
| `password_changed_admin` | Password changed, to the site admin |
| `email_changed` | Account email changed, to the old address |
| `email_change_request` | Confirm a new account email |
| `admin_email_change_request` | Confirm a new site admin email |
| `admin_email_changed` | Site admin email changed, to the old address |

### Comments

| Id | Email |
|---|---|
| `comment_notification` | New comment, to the post author |
| `comment_moderation` | Comment awaiting moderation |

### Updates and site health

| Id | Email |
|---|---|
| `core_update` | WordPress updated automatically |
| `plugin_theme_update` | Plugins or themes updated automatically |
| `update_debug` | Automatic update debug report |
| `recovery_mode` | Technical issue (recovery mode) notice |

### Privacy

| Id | Email |
|---|---|
| `privacy_request` | Personal data request: confirm |
| `privacy_request_confirmed` | Personal data request confirmed, to the site admin |
| `privacy_export_ready` | Personal data export ready |
| `privacy_erasure_done` | Personal data erased |

### Multisite only

| Id | Email |
|---|---|
| `signup_site` | Activate a new site |
| `signup_user` | Activate a new account |
| `welcome_site` | New site welcome |
| `welcome_user` | New account welcome |
| `network_admin_email_change_request` | Confirm a new network admin email |
| `network_admin_email_changed` | Network admin email changed |

## What is left alone

- **Every other plugin's email.** WooCommerce order emails, form notifications, membership and
  newsletter plugins: none of them are touched, HTML or plain text.
- **Anything already sent as HTML or multipart**, whoever sends it. An email that declares a
  content type other than `text/plain` is not asked about, whatever the filter below says.
- **A core email another plugin has changed in its own `wp_mail` filter.** The feature
  recognises an email by the text WordPress settled on. If another plugin then changes that text
  in a `wp_mail` filter, the email no longer matches and goes out as that plugin left it. Changes
  made through WordPress's own per-email filters, such as `retrieve_password_notification_email`,
  are fine: the feature reads the text after them.

When in doubt, nothing is touched: an email the feature cannot identify is sent as it was.

## How an email is recognised

WordPress passes each of its emails through a filter of its own just before sending, such as
`retrieve_password_notification_email` or `comment_notification_text`. Nice Default Emails
listens on each of those, last, and notes the text WordPress settled on. When `wp_mail()` is
then called with that same text, and the email is plain text, the layout is applied. Placeholders
WordPress fills in between the filter and the send are allowed for.

That is why the feature does not guess from subjects, which are translated and filterable, and why
it does not sweep up every plain-text email on the site.

## The layout

- **Header**: your site's name, linking to the home page. A site with no name is called by its
  host instead.
- **Card**: the text WordPress wrote, unchanged. Line breaks are kept and web addresses become
  links, so a reset or confirmation link still works. Text is escaped first, so nothing in an
  email is read as markup.
- **Footer**: the site's name and its address, linking home.

The template is built for mail clients rather than browsers: tables, every style inline, no web
fonts and no images. Colours are WordPress admin's own (near-black text, admin-blue links, a light
grey page). Mail clients that respect `prefers-color-scheme` get a dark version; clients that drop
the style block, as Gmail does, show the light one. The email's language and direction follow the
site's.

The `Content-Type` header is swapped for `text/html` with the site's charset; every other header
is kept as it was.

## With SMTP and Email Log

The layout is applied on the `wp_mail` filter, after ordinary filters and before the email reaches
the mailer, so it goes out the same way with Adminkeep's [SMTP](/docs/configuration/#smtp)
feature, with another SMTP plugin, or with no SMTP setup at all.

With [Email Log](/docs/email-log/) on, the log records the HTML version, which is what was sent,
and the preview renders it as a mail client would. Sign-in and reset links are still removed
before the email is stored, as for any other email.

## For developers

One filter decides whether an email gets the layout:

```php
/**
 * @param bool   $wrap     True for one of WordPress core's own emails, false otherwise.
 * @param string $email_id The email's id (see the tables above), or '' when it is not one of core's.
 * @param array  $atts     wp_mail() arguments: to, subject, message, headers, attachments.
 */
add_filter( 'adminkeep_nice_emails_wrap', function ( $wrap, $email_id, $atts ) {
    // Keep the comment moderation email plain.
    if ( 'comment_moderation' === $email_id ) {
        return false;
    }

    // Give a plain-text email of your own the same layout.
    if ( 'Weekly digest' === $atts['subject'] ) {
        return true;
    }

    return $wrap;
}, 10, 3 );
```

The filter is not asked about an email that already declares HTML or multipart content; those are
left alone regardless. If the template cannot be built for an email, that email goes out as plain
text rather than not at all.

## WP-CLI

Most of these emails are hard to trigger on purpose, so the plugin can send them for you:

```bash
wp adminkeep feature enable nice_emails
wp adminkeep emails list
wp adminkeep emails send password_reset --to=you@example.com
wp adminkeep emails send --all --to=you@example.com
```

| Command | What it does |
|---|---|
| `wp adminkeep emails list` | The core emails this site can send, with the function that sends each |
| `wp adminkeep emails send <id>... --to=<email>` | Sends the named emails to one address |
| `wp adminkeep emails send --all --to=<email>` | Sends every one of them |

`send` makes WordPress send each email through the function that sends it for real, so it arrives
exactly as your site would send it: through your mailer, in the layout, and recorded by Email Log
when that is on. Only the recipient is changed; every email goes to `--to` and to nobody else.
What an email needs is created for the run and deleted after it (a throwaway subscriber, a
private post with two comments, personal data requests), and settings WordPress writes while
sending are put back, so the links in those emails do nothing. It needs Nice Default Emails
switched on, and exits 1 if any email fails.

The full reference is [Core emails](/docs/wp-cli/#core-emails) in the WP-CLI docs, and
`wp help adminkeep emails` matches the version you run.