Send value of PHP variable in template via hidden field in a form

The short answer- don’t send all that data with the form.

You know what data goes with the form, and the email has to be sent from the server, so there’s no reason for that data to make a round trip out to a browser and back to your server.

Set some sort of unique identifier and use that to get whatever data you need to send, whether it’s attached to the current page, the current logged in user, etc..

Here’s a quick proof of concept.

First, a Shortcode to output the form. Here we show two possible methods for identifying the form- an ID supplied with the shortcode, or the current page ID. We also check if the user is logged in or not, and whether to display the form or show a message that it’s just been submitted.

function wpd_form_shortcode( $atts ){
    $a = shortcode_atts( array(
        'form_id' => 0,
    ), $atts );

    if( is_user_logged_in() ){

        if( isset( $_GET['sent'] ) ){
            $form = 'form submitted';
        } else {
            $form = '<form method="post" action="' . admin_url( 'admin-post.php' ) . '">';
            $form .= '<input type="hidden" name="action" value="wpd_send_form">';
            $form .= '<input type="hidden" name="form_id" value="' . $a['form_id'] . '">';
            $form .= '<input type="hidden" name="post_id" value="' . get_the_ID() . '">';
            $form .= '<input type="submit" value="Submit">';
            $form .= '</form>';
        }

    } else {

        $form = 'You must be logged in';

    }

    return $form;
}
add_shortcode( 'wpd_form', 'wpd_form_shortcode' );

Now the action hooked to admin_post that the above form points to. Here we show how to fetch the passed values, get the current logged in user, and send an email. This is where you should get those post IDs, whether from post meta, user meta, etc., and iterate over each to build the email.

function wpd_send_form_function() {

    // get the form ID or post ID
    // use these to get whatever data you need, get_post_meta, etc.
    $form_id = $_POST['form_id'];
    $post_id = $_POST['post_id'];

    // get the current logged in user info
    $current_user = wp_get_current_user();

    // put the data in the content of the email and send it
    $to = '[email protected]';
    $subject="Email from " . $current_user->user_login;
    $body = 'Email from post_id ' . $post_id;

    wp_mail( $to, $subject, $body );

    // redirect back to the page that contained the form we just submitted
    wp_safe_redirect( $_SERVER['HTTP_REFERER'] . '?sent=true', 303 );
    exit;
}
add_action( 'admin_post_wpd_send_form', 'wpd_send_form_function' );
// uncomment next line if you want to allow users who aren't logged in
// add_action( 'admin_post_nopriv_wpd_send_form', 'wpd_send_form_function' );

You should also look into using a nonce with the form, as well as doing some basic checks that you’ve got a valid post ID, that the user has permission to access the data for that post, etc..