Skip to content

#34712 - Add a reset_password_url filter - #13590

Open
skikken wants to merge 2 commits into
WordPress:trunkfrom
skikken:fix/34712-reset-password-url-filter
Open

skikken wants to merge 2 commits into
WordPress:trunkfrom
skikken:fix/34712-reset-password-url-filter

Conversation

@skikken

@skikken skikken commented Sep 17, 2026

Copy link
Copy Markdown

The ticket asks for a way to send the password reset link to a custom reset page: "For example if I want make custom reset password page." There is no filter for that URL today.

retrieve_password() builds the reset link inline and appends it straight to the message body:

$message .= network_site_url( 'wp-login.php?login=' . rawurlencode( $user_login ) . "&key=$key&action=rp", 'login' ) . '&wp_lang=' . $locale . "\r\n\r\n";

The closest existing hook is retrieve_password_notification_email (since 6.0.0), but it filters the entire to/subject/message/headers array, so a site that only wants to change the URL has to rebuild the whole email body and keep up with any future changes to its wording.

This adds a focused reset_password_url filter on the URL itself, before the locale fragment is appended:

$reset_url = network_site_url( 'wp-login.php?login=' . rawurlencode( $user_login ) . "&key=$key&action=rp", 'login' );

/** This filter is documented in wp-includes/user.php */
$reset_url = apply_filters( 'reset_password_url', $reset_url, $user_login, $key, $user_data );

$message .= $reset_url . '&wp_lang=' . $locale . "\r\n\r\n";

Two boundaries worth stating explicitly, because both were deliberate:

  • The locale is filtered outside the URL. &wp_lang= is appended to the message after the URL rather than being part of it, so the filter receives exactly the reset URL and nothing else. Moving wp_lang inside the filtered value would have changed the default output and would also have made the filter responsible for a fragment it does not own.
  • wp_new_user_notification() in pluggable.php builds a similar link and is not changed. It is pluggable, so a site can already replace it outright, and the ticket is about the password reset flow. Worth a follow-up if the same filter is wanted there.

lostpassword_url already exists (since 2.8.0) but filters a different URL: the "Lost your password?" link that takes a user to the request form, not the reset link that carries the key. This is a separate hook.

With no filter registered the message is unchanged, and there is a test asserting that specifically so the default output cannot drift silently.

Tests cover the filter being applied, its four arguments, and the unchanged default message including the locale fragment.

Trac ticket: https://core.trac.wordpress.org/ticket/34712

Use of AI Tools

AI assistance: Yes
Tool(s): Claude
Model(s): Sonnet
Used for: test cases, code review


This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.

The password reset link emailed by retrieve_password() was built inline and
appended straight to the message, so the only way to point it at a custom
reset page was the retrieve_password_notification_email filter, which
replaces the whole email body.

Build the URL into its own variable and pass it through a reset_password_url
filter before it is appended to the message, so a site can redirect the link
without rebuilding the email.

The filter receives the URL, the user login, the activation key and the
WP_User object. The locale, which is appended after the URL rather than
being part of it, is deliberately left outside the filtered value. With no
filter registered the message is unchanged.

Props sebastian.pisula.
Fixes #34712.
Assert that the filter is applied to the password reset URL in the email
sent by retrieve_password(), that it receives the documented arguments, and
that the unfiltered message still carries the default wp-login.php reset
URL together with the locale fragment.

The last of these guards the back-compat requirement that the default email
output does not change.

Fixes #34712.
@github-actions

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

Unlinked Accounts

The following contributors have not linked their GitHub and WordPress.org accounts: @skikken.

Contributors, please read how to link your accounts to ensure your work is properly credited in WordPress releases.

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@github-actions

Copy link
Copy Markdown

Test using WordPress Playground

The changes in this pull request can previewed and tested using a WordPress Playground instance.

WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser.

Some things to be aware of

  • All changes will be lost when closing a tab with a Playground instance.
  • All changes will be lost when refreshing the page.
  • A fresh instance is created each time the link below is clicked.
  • Every time this pull request is updated, a new ZIP file containing all changes is created. If changes are not reflected in the Playground instance,
    it's possible that the most recent build failed, or has not completed. Check the list of workflow runs to be sure.

For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation.

Test this pull request with WordPress Playground.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant