Customizing Headers of Wordpress Multisite Emails

Hi there, I've been working on customizing the emails that Wordpress Multisite sends when I add users to one of my specific sub-sites. I created the plugin, copied the wordpress pluggable wp_new_user_notification function, and I've been able to take care of all of the customization I wanted except for the email header. I'd like for the email to send from the email address that is the Wordpress admin of that site, not the Multisite email address.

When I use this code:

if ( ! function_exists( 'wp_new_user_notification' ) ) :
    /**
     * Email login credentials to a newly-registered user.
     *
     * A new user registration notification is also sent to admin email.
     *
     * @since 2.0.0
     * @since 4.3.0 The <code>$plaintext_pass</code> parameter was changed to <code>$notify</code>.
     * @since 4.3.1 The <code>$plaintext_pass</code> parameter was deprecated. <code>$notify</code> added as a third parameter.
     * @since 4.6.0 The <code>$notify</code> parameter accepts 'user' for sending notification only to the user created.
     *
     * @global wpdb         $wpdb      WordPress database object for queries.
     * @global PasswordHash $wp_hasher Portable PHP password hashing framework instance.
     *
     * <a title=@param href=/profile/param>param</a> int    $user_id    User ID.
     * <a title=@param href=/profile/param>param</a> null   $deprecated Not used (argument deprecated).
     * <a title=@param href=/profile/param>param</a> string $notify     Optional. Type of notification that should happen. Accepts 'admin' or an empty
     *                           string (admin only), 'user', or 'both' (admin and user). Default empty.
     */
    function wp_new_user_notification( $user_id, $deprecated = null, $notify = '' ) {
        if ( $deprecated !== null ) {
            _deprecated_argument( __FUNCTION__, '4.3.1' );
        }

        // Accepts only 'user', 'admin' , 'both' or default '' as $notify
        if ( ! in_array( $notify, array( 'user', 'admin', 'both', '' ), true ) ) {
            return;
        }

        global $wpdb, $wp_hasher;
        $user = get_userdata( $user_id );

        // The blogname option is escaped with esc_html on the way into the database in sanitize_option
        // we want to reverse this for the plain text arena of emails.
        $blogname = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );

        if ( 'user' !== $notify ) {
            $switched_locale = switch_to_locale( get_locale() );

            /* translators: %s: site title */
            $message = sprintf( __( 'New user registration on your site %s:' ), $blogname ) . "\r\n\r\n";
            /* translators: %s: user login */
            $message .= sprintf( __( 'Username: %s' ), $user->user_login ) . "\r\n\r\n";
            /* translators: %s: user email address */
            $message .= sprintf( __( 'Email: %s' ), $user->user_email ) . "\r\n";

            $wp_new_user_notification_email_admin = array(
                'to'      => get_option( 'admin_email' ),
                /* translators: Password change notification email subject. %s: Site title */
                'subject' => __( '[%s] New User Registration' ),
                'message' => $message,
                'headers' => '',
            );

            /**
             * Filters the contents of the new user notification email sent to the site admin.
             *
             * @since 4.9.0
             *
             * <a title=@param href=/profile/param>param</a> array   $wp_new_user_notification_email {
             *     Used to build wp_mail().
             *
             *     @type string $to      The intended recipient - site admin email address.
             *     @type string $subject The subject of the email.
             *     @type string $message The body of the email.
             *     @type string $headers The headers of the email.
             * }
             * <a title=@param href=/profile/param>param</a> WP_User $user     User object for new user.
             * <a title=@param href=/profile/param>param</a> string  $blogname The site title.
             */
            $wp_new_user_notification_email_admin = apply_filters( 'wp_new_user_notification_email_admin', $wp_new_user_notification_email_admin, $user, $blogname );

            @wp_mail(
                $wp_new_user_notification_email_admin['to'],
                wp_specialchars_decode( sprintf( $wp_new_user_notification_email_admin['subject'], $blogname ) ),
                $wp_new_user_notification_email_admin['message'],
                $wp_new_user_notification_email_admin['headers']
            );

            if ( $switched_locale ) {
                restore_previous_locale();
            }
        }

        if ( 'admin' === $notify || ( empty( $deprecated ) && empty( $notify ) ) ) {
            return;
        }

        // Generate something random for a password reset key.
        $key = wp_generate_password( 20, false );

        /** This action is documented in wp-login.php */
        do_action( 'retrieve_password_key', $user->user_login, $key );

        // Now insert the key, hashed, into the DB.
        if ( empty( $wp_hasher ) ) {
            require_once ABSPATH . WPINC . '/class-phpass.php';
            $wp_hasher = new PasswordHash( 8, true );
        }
        $hashed = time() . ':' . $wp_hasher->HashPassword( $key );
        $wpdb->update( $wpdb->users, array( 'user_activation_key' => $hashed ), array( 'user_login' => $user->user_login ) );

        $switched_locale = switch_to_locale( get_user_locale( $user ) );

        /* translators: %s: user login */
        if(wp_login_url() == 'https://secularhumanism.org/wp-login.php') {
            $message = __( 'Congratulations <em>Free Inquiry</em> subscriber! An account was just created for you at <a href="https://secularhumanism.org/">https://secularhumanism.org/</a>.' ) . "\r\n\r\n";
            $message .= __( 'All <em>Free Inquiry</em> print subscribers now receive a free digital subscription that grants full access to the archives. Your account is now ready, follow the instructions below to choose a password and begin reading online:' ) . "\r\n\r\n";
            $message  .= sprintf( __( 'Your username to login is <strong>%s</strong>' ), $user->user_login ) . "\r\n";
            $message .= __( 'To set your password, visit the following address:' ) . "\r\n";
            $message .= '<' . network_site_url( "wp-login.php?action=rp&key=$key&login=" . rawurlencode( $user->user_login ), 'login' ) . ">\r\n\r\n";

            $message .= __( 'If you’d rather not take advantage of your free digital subscription to <em>Free Inquiry</em>, simply ignore this message and continue to enjoy the print edition of the magazine.' );

            $wp_new_user_notification_email = array(
                'to'      => $user->user_email,
                /* translators: Password change notification email subject. %s: Site title */
                'subject' => __( 'Your Free Inquiry digital subscription is ready' ),
                'message' => $message,
                'headers' => '',
            );
        } else {
            $message  = sprintf( __( 'Username: %s' ), $user->user_login ) . "\r\n\r\n";
            $message .= __( 'To set your password, visit the following address:' ) . "\r\n\r\n";
            $message .= '<' . network_site_url( "wp-login.php?action=rp&key=$key&login=" . rawurlencode( $user->user_login ), 'login' ) . ">\r\n\r\n";

            $message .= wp_login_url() . "\r\n";

            $wp_new_user_notification_email = array(
                'to'      => $user->user_email,
                /* translators: Password change notification email subject. %s: Site title */
                'subject' => __( '[%s] Your username and password info' ),
                'message' => $message,
                'headers' => '',
            );
        }

        /**
         * Filters the contents of the new user notification email sent to the new user.
         *
         * @since 4.9.0
         *
         * <a title=@param href=/profile/param>param</a> array   $wp_new_user_notification_email {
         *     Used to build wp_mail().
         *
         *     @type string $to      The intended recipient - New user email address.
         *     @type string $subject The subject of the email.
         *     @type string $message The body of the email.
         *     @type string $headers The headers of the email.
         * }
         * <a title=@param href=/profile/param>param</a> WP_User $user     User object for new user.
         * <a title=@param href=/profile/param>param</a> string  $blogname The site title.
         */
        $wp_new_user_notification_email = apply_filters( 'wp_new_user_notification_email', $wp_new_user_notification_email, $user, $blogname );

        wp_mail(
            $wp_new_user_notification_email['to'],
            wp_specialchars_decode( sprintf( $wp_new_user_notification_email['subject'], $blogname ) ),
            $wp_new_user_notification_email['message'],
            $wp_new_user_notification_email['headers']
        );

        if ( $switched_locale ) {
            restore_previous_locale();
        }
    }
endif;

Everything is fine, but as soon as I put anything in the array for 'headers' then the email starts showing all the html tags within. Any ideas for what I can try to customize the header?

  • Dimitris
    • Support Star

    Hello there Marc Kreidler,

    hope you're doing well and thanks for reaching us! :slight_smile:

    I've already pinged Panos from our Second Level Support team to have a look on this.

    Everything is fine, but as soon as I put anything in the array for 'headers' then the email starts showing all the html tags within.

    Could you please let us know what exact change you're making?

    As a sidenote, there's also a handy plugin that you could test:
    https://wordpress.org/plugins/welcome-email-editor/

    Warm regards,
    Dimitris

  • Marc Kreidler
    • New Recruit

    Hi Dimitris,

    Thanks for replying. Specifically I'm adjusting this part:

    $wp_new_user_notification_email = array(
                    'to'      => $user->user_email,
                    /* translators: Password change notification email subject. %s: Site title */
                    'subject' => __( 'Your Free Inquiry digital subscription is ready' ),
                    'message' => $message,
                    'headers' => '',
                );

    I adjusted the $message content above that, but that part is fine as long as the header is left blank.

    I've tried:
    'headers' => 'From: Free Inquiry <info@secularhumanism.org>',
    'headers' => __('From: Free Inquiry <info@secularhumanism.org>'),
    'headers' => 'From'.get_bloginfo('name').' <'.get_bloginfo('admin_email').'>',

    And all have resulted in email arrivals from the desired sender, but with email content that includes html tags.

    I can't use any plugins that currently exist because I'm customizing this for just one site in the Multisite, as you can see with this:
    if(wp_login_url() == 'https://secularhumanism.org/wp-login.php') {

    Thanks for any tips you might have!

  • Panos
    • SLS

    Hi Marc Kreidler ,

    By setting the headers this way it seems that it is overriding the Content-Type part, which was probably set (by theme or some plugin) to html. Since it is overridden, there is no content type set, so it uses the text/plain content type which is the default and doesn't allow html.

    I would suggest to either include the content type in your header, eg:

    From: Free Inquiry <info@secularhumanism.org>
    Content-Type: text/plain; charset="UTF-8"

    or, instead of setting the headers entirely, you can modify the From part only (which I see this is what you need to set) with the wp_mail_from and wp_mail_from_name filters:
    https://codex.wordpress.org/Plugin_API/Filter_Reference/wp_mail_from and
    https://codex.wordpress.org/Plugin_API/Filter_Reference/wp_mail_from_name

    for example:

    add_filter( 'wp_mail_from', function( $from){ return 'info@secularhumanism.org'; }, 999 );
    add_filter( 'wp_mail_from_name', function( $from){ return 'Free Inquiry'; }, 999 );

    Kind regards!

  • Marc Kreidler
    • New Recruit

    Hi Panos,

    Thanks so much for your response! Unfortunately, neither worked as-is but I've tweaked the first solution and got it to work:

    $wp_new_user_notification_email = array(
                    'to'      => $user->user_email,
                    /* translators: Password change notification email subject. %s: Site title */
                    'subject' => __( 'Your Free Inquiry digital subscription is ready' ),
                    'message' => $message,
                    'headers' => array('From: Free Inquiry <info@secularhumanism.org>',
                        'Content-Type: text/plain; charset="UTF-8"'),
                );

    All I had to do is treat the header as an array and it worked. Thanks so much for your help!

Thank NAME, for their help.

Let NAME know exactly why they deserved these points.

Gift a custom amount of points.