Skip to main content

Replace the built-in set-your-password email with your own

Premium Intermediate

Some subscribers never fill in a signup form. An admin bulk-enrolls them from a list, adds them by hand, or a donation completes and the webhook creates their account. They end up with a WordPress account nobody asked them to choose a password for. Their feed works — the token in the feed URL is the credential — but the account page and billing portal are behind a login they cannot complete.

Benecaster already emails those users. A set-password link goes out on all three of those flows rather than waiting for someone to write this recipe. Use this pattern when you want to send your own message instead — the podcaster’s voice, your own template, an extra CRM call alongside it. If something outside Benecaster is already sending an account-setup email and you only need the built-in one to stop, you want Suppress the Set-Password Email for a Role or a Provisioning Flow instead — it is the first half of this recipe without the second.

Replacing the built-in email rather than adding to it means suppressing it first. Return false from benecaster_subscribe_send_password_email and then send your own from benecaster_subscriber_account_provisioned. The action fires either way; only the email is gated. Suppressing without replacing leaves the subscriber with an account and no way into it.

This is not the hook for people who signed themselves up. It never fires for either self-service form — but ⚠ for two different reasons, which must not be collapsed back into one rule. Both tiers of [benecaster_subscribe] ask for a password on the form, so those subscribers already know their credentials. [benecaster_follower_signup] asks for no password at all: the follower is provisioned with one nobody knows, and the welcome mail carries its own single-use signed link that signs them in. Either way nobody needs a reset link from you, and sending one would be confusing at best. To react to a self-service signup, use benecaster_subscribe_user_created or benecaster_follower_signed_up instead.

Their feed does not exist yet at this point. The action fires before the feed token is generated, so a message sent from here cannot include the feed URL. If that is what you want to send, use benecaster_token_generated instead, which fires once there is a feed to link to.

$source tells you which flow created the account — bulk_enroll, manual_add or donation_signup — so a hand-added comp can read differently from a 400-address import.

If all you want is different wording, you do not need this recipe. The built-in message is a normal Benecaster email template — guest-password-set.php, receiving $reset_url — so you can override it from your theme like any other and keep core’s sending, timing and single-use link. See Customizing Email Templates. Reach for the pattern below when you need more than wording: a different sender, an extra CRM call alongside the send, or a message that goes somewhere other than email.

Code

<?php
// 1. Turn off the core email so the subscriber gets one message, not two.
add_filter( 'benecaster_subscribe_send_password_email', '__return_false' );

// 2. Send your own in its place.
add_action(
    'benecaster_subscriber_account_provisioned',
    function ( int $user_id, int $show_id, string $source ): void {
        $user = get_user_by( 'id', $user_id );
        if ( ! $user ) {
            return;
        }

        // get_password_reset_key() is what makes the link single-use and
        // expiring. Never email a password you generated yourself.
        $key = get_password_reset_key( $user );
        if ( is_wp_error( $key ) ) {
            return;
        }

        $link = add_query_arg(
            [
                'action' => 'rp',
                'key'    => $key,
                'login'  => rawurlencode( $user->user_login ),
            ],
            wp_login_url()
        );

        $show = get_the_title( $show_id );

        benecaster_mail(
            $show_id,
            $user->user_email,
            sprintf(
                /* translators: %s: show name */
                __( 'Your %s account is ready', 'my-addon' ),
                $show
            ),
            sprintf(
                /* translators: 1: show name, 2: set-password link */
                __( "You have been added to %1\$s.\n\nSet your password here:\n%2\$s", 'my-addon' ),
                $show,
                $link
            )
        );
    },
    10,
    3
);

View on GitHub →

Hooks Used