Send notification email to admin for every new post published

You can use the transition_post_status hook.

<?php
add_action( 'transition_post_status', 'custom_send_admin_email', 10, 3 );

function custom_send_admin_email( $new_status, $old_status, $post ) {
    if ( 'publish' === $new_status && 'publish' !== $old_status ) {
        // Consider sending an email here.
    }
}

Here’s a second example that also checks for a specific post type. Note that $post is an instance of WP_Post, so you can access all of its properties if you need to learn more about the post.

<?php
add_action( 'transition_post_status', 'custom_send_admin_email', 10, 3 );

function custom_send_admin_email( $new_status, $old_status, $post ) {
    if ( 'post' === $post->post_type && 'publish' === $new_status && 'publish' !== $old_status ) {
        // Consider sending an email here.
    }
}

Taking this a bit further, we can set a post meta value that flags the post as having been sent to the administrator’s email address already. This makes it a bit smarter and capable of handling some trickier situations. Such as when a post moves from a trash status to a publish status.

We can also send an email on a status that changes to future, which indicates the post is scheduled to be published at a future date. This way the admin gets an email when it’s scheduled for publication ahead of time, not the day on which it is actually released for public viewing.

<?php
add_action( 'transition_post_status', 'custom_send_admin_email', 10, 3 );

function custom_send_admin_email( $new_status, $old_status, $post ) {
    if ( 'post' === $post->post_type && in_array( $new_status, array( 'publish', 'future' ), true ) && ! in_array( $old_status, array( 'publish', 'future' ), true ) ) {
        if ( ! get_post_meta( $post->ID, 'emailed_to_admin', true ) ) {

            // Consider sending an email here.
            // ...

            // Flag email as having been sent now.
            update_post_meta( $post->ID, 'emailed_to_admin', time() );
        }
    }
}