Adding a button to send email to a user in WordPress Admin Users table

There’s a flaw in your approach.

The filter hook you are using – user_row_actions – is for adding a “hover link” to the user row. It is run on each user row in the Users > All Users screen. That part by itself would be OK if what you were doing with the filter was just adding the link; but you’re using the filter to also process your action of sending an email.

The filter is run 20 times on a page load of Users > All Users (the default number of users shown in a table view), so when you do it this way, you end up sending 20 emails (or the number of users in the view).

So here’s a rule of thumb – filters are for changing the way something displays. Actions are for running some type of process. So use the filter to add the link, and an action to process the result if the link is clicked.

Continue using the user_row_actions filter to add your link. I’d suggest using an action hook like admin_notices to check if your link was submitted and then process it, since you need to use that hook to display a “success” message anyway. That way you can combine those two processes. That way, your processing of the clicked link will only be run once instead of 20 times.

Here’s your original code modified as I described above. I’ve included comments to clarify what it’s doing and why.

// Adds "Send verification email" action to Users page
add_filter('user_row_actions', 'send_verification_email_link', 10, 2);
function send_verification_email_link($actions, $user_object) {
    $actions['send_rejection'] = "<a class="send_verification_email" href="" . admin_url( "users.php?action=send_verification_email&amp;user_id=" . $user_object->ID ) . "">" . __( 'Send Verification Email' ) . "</a>";
    return $actions;
}


add_action( 'admin_notices', 'send_verification_email' );
function send_verification_email() {

    // Get the current screen so you only move forward if this is the users.php screen.
    $screen = get_current_screen();
    if ( 'users' == $screen->id ) {

        // Make sure to check if the $_GET value is actually set before you compare the value, 
        // otherwise you may get errors if the page is loaded without it.
        if ( isset( $_GET['action'] ) && 'send_verification_email' == $_GET['action'] ) {

            // Check that the email was passed too.
            $user_id = ( isset( $_GET['user_id'] ) ) ? $_GET['user_id'] : false;

            // Get the user info object info using the user ID (you'll need 
            // this for the email address and other data like "first_name" you use in the email message.
            $user_object = get_user_by( 'ID', $user_id );

            // If you have a user with an email address.
            if ( $user_object->user_email ) {

                $my_logo = "<img src="https://example.com/" alt="logo" />";

                $subject="Your Example Account is not yet verified";
                $headers = array('Content-Type: text/html; charset=UTF-8');

                $message="<p style="text-align: center;">".$my_logo.'</p>

                    <div style="max-width: 600px; margin: 30px auto; padding: 15px; font-family: Roboto,Open Sans,Helvetica,Arial; border: 1px solid #e8e8e8; line-height: 1.6; text-align: center; background-color: white;">

                    <div style="text-align: left;">
                    <p>Hi '.$user_object->first_name.',</p>

                    <p>Thank you for registering your business on Example.com. Your account is not yet verified because you have not provided the verification information or the information you provided is invalid. Please provide the necessary information below to get verified:</p>

                    <p><strong>Private person:</strong></p>
                    <ul>
                    <li>Upload a profile photo.</li>
                    <li>Upload an identification document.</li>
                    </ul>

                    <p><strong>Company:</strong></p>
                    <ul>
                    <li>Upload a profile photo.</li>
                    <li>Upload an identification document.</li>
                    <li>Provide your registered company name.</li>
                    <li>Provide your company registration number.</li>
                    </ul>

                    <a style="text-align: center;" href="https://example.com/login/" rel="noopener noreferrer" target="_blank">Click here to login to your account.</a>

                    <p>When you are logged in, click the settings icon on your profile page and click edit profile. Scroll to the verification section to provide the verification information.</p>

                    <p>Please let us know if you have any questions.</p>

                    <p>Kind regards,<br>Example Team</p>

                    </div>        
                    </div>';

                // Send message.
                wp_mail( $user_object->user_email, $subject, $message, $headers );

                // Set up admin notice
                $class="updated notice"; 
                $admin_notice="Success! The verification email has been sent to " . $user_object->user_email;

            } else {

                // Set up admin notice for error state.
                $class="notice notice-error";
                $admin_notice = "No email address was passed so no email was sent.";
            }

            // Display message.
            printf( '<div class="%s"><p>%s</p></div>', $class, $admin_notice );
        }
    }
}