Send transactional email: first user’s post

You’re close – let’s take a look at this line:

if( 'post' == $post->post_type && count_user_posts(the_author_meta('ID') == 1); )
  1. That semicolon is a syntax error, PHP will barf – let it go
  2. the_author_meta() prints data, it does not return anything – use get_the_author_meta() for comparisons and passing things around
  3. The post count comparison needs to be outside the function call – note the difference in parentheses positions: count_user_posts( $id ) == 1, not count_user_posts( $id == 1 )

Having said all that, I get the impression this condition (when corrected) is the reverse of what you want – at the moment you’re trying to say “if the post type is post and the author has one post, do nothing“, when actually you want the opposite(?)

In which case, here’s what I think you’re after:

if ( 'post' !== $post->post_type || count_user_posts( $post->post_author ) > 1 )
   return; // If the post is NOT a post, or the author has more than one post, bail

See how I’ve used $post->post_author too? That’s the user ID. It’s part of the post object, no need to use a function here (despite what I said about get_the_author_meta() earlier).

Lastly, the email: you can either use said author function, or grab the user object directly (which is what the former is wrapper around anyway):

$user_email = get_user_by( 'id', $post->post_author )->user_email;

All together now:

function author_publish_notice( $ID, $post ) {
    if ( 'post' !== $post->post_type || count_user_posts( $post->post_author ) > 1 )
        return;

    $to = get_user_by( 'id', $post->post_author )->user_email;
    $subject="Your Article Is Online";
    $headers = array(
        'Content-Type: text/html',
        'From: [email protected]',
    );

    $message="<h1>Congratulations!</h1> <p>Your article is now online and 
    is sure to receives trillions of comments. Please do hang around and answer any questions
    viewers may have!</p> <p><a href="" . get_permalink( $ID ) . '">' . $post->post_title . '</a></p>';

    wp_mail( $to, $subject, $message, $headers ); 
}

You’ll see I’ve also removed the content type filter – you can pass mail headers as a fourth parameter to wp_mail(), either line-break separated or as an array.