You could use the transition_post_status
hook instead, as it already knows what the current and previous status of the post are.
<?php
add_action('transition_post_status', 'wpse_366380_email_on_publish', 10, 3);
function wpse_366380_email_on_publish( $new_status, $old_status, $post ) {
// Only if this post was just published, and previously it was either
// "auto-draft" (brand new) or "pending" (not yet published)
if ( 'publish' == $new_status && ( 'auto-draft' == $old_status || 'pending' == $old_status ) ) {
$post = get_post($post_id);
$author = get_userdata($post->post_author);
$subject = "Post Published: ".$post->post_title."";
$message = "Hi ".$author->display_name.",
Your post, \"".$post->post_title."\" has just been published.
View post: ".get_permalink( $post_id )."";
wp_mail($author->user_email, $subject, $message);
}
}
?>