Index: src/wp-includes/comment.php
===================================================================
--- src/wp-includes/comment.php	(revision 26352)
+++ src/wp-includes/comment.php	(working copy)
@@ -1376,15 +1376,18 @@
  * that it is properly set, such as in wp-config.php, for your environment.
  * See {@link http://core.trac.wordpress.org/ticket/9235}
  *
- * @since 1.5.0
- * @uses apply_filters() Calls 'preprocess_comment' hook on $commentdata parameter array before processing
- * @uses do_action() Calls 'comment_post' hook on $comment_ID returned from adding the comment and if the comment was approved.
- * @uses wp_filter_comment() Used to filter comment before adding comment.
- * @uses wp_allow_comment() checks to see if comment is approved.
- * @uses wp_insert_comment() Does the actual comment insertion to the database.
- *
- * @param array $commentdata Contains information on the comment.
- * @return int The ID of the comment after adding.
+ * @since  1.5.0
+ * @param  array $commentdata Contains information on the comment.
+ * @uses   apply_filters
+ * @uses   wp_get_comment_status
+ * @uses   wp_filter_comment
+ * @uses   wp_allow_comment
+ * @uses   wp_insert_comment
+ * @uses   do_action
+ * @uses   wp_notify_moderator
+ * @uses   get_option
+ * @uses   wp_notify_postauthor
+ * @return int                The ID of the comment after adding.
  */
 function wp_new_comment( $commentdata ) {
 	$commentdata = apply_filters('preprocess_comment', $commentdata);
@@ -1417,10 +1420,10 @@
 		if ( '0' == $commentdata['comment_approved'] )
 			wp_notify_moderator($comment_ID);
 
-		$post = get_post($commentdata['comment_post_ID']); // Don't notify if it's your own comment
-
-		if ( get_option('comments_notify') && $commentdata['comment_approved'] && ( ! isset( $commentdata['user_id'] ) || $post->post_author != $commentdata['user_id'] ) )
-			wp_notify_postauthor($comment_ID, isset( $commentdata['comment_type'] ) ? $commentdata['comment_type'] : '' );
+		// wp_notify_postauthor() checks if notifying the author of his/her own comment.
+		// By default, it won't, but filters can override this.
+		if ( get_option( 'comments_notify' ) && $commentdata['comment_approved'] )
+			wp_notify_postauthor( $comment_ID, isset( $commentdata['comment_type'] ) ? $commentdata['comment_type'] : '' );
 	}
 
 	return $comment_ID;
Index: src/wp-includes/pluggable.php
===================================================================
--- src/wp-includes/pluggable.php	(revision 26352)
+++ src/wp-includes/pluggable.php	(working copy)
@@ -1000,37 +1000,67 @@
 
 if ( ! function_exists('wp_notify_postauthor') ) :
 /**
- * Notify an author of a comment/trackback/pingback to one of their posts.
+ * Notify an author and/or others of a comment/trackback/pingback on a posts.
  *
  * @since 1.0.0
  *
- * @param int $comment_id Comment ID
- * @param string $comment_type Optional. The comment type either 'comment' (default), 'trackback', or 'pingback'
- * @return bool False if user email does not exist. True on completion.
+ * @param  int $comment_id      Comment ID
+ * @param  string $comment_type Optional. The comment type either 'comment' (default), 'trackback', or 'pingback'
+ * @uses   get_comment
+ * @uses   get_post
+ * @uses   get_userdata
+ * @uses   apply_filters
+ * @uses   wp_specialchars_decode
+ * @uses   get_option
+ * @uses   __
+ * @uses   get_permalink
+ * @uses   admin_url
+ * @uses   wp_mail
+ * @return bool                 True on completion. False if no email addresses were specified.
  */
 function wp_notify_postauthor( $comment_id, $comment_type = '' ) {
 	$comment = get_comment( $comment_id );
-	if ( empty( $comment ) )
+	if ( empty( $comment ) ) {
 		return false;
+	}
 
 	$post    = get_post( $comment->comment_post_ID );
 	$author  = get_userdata( $post->post_author );
 
-	// The comment was left by the author
-	if ( $comment->user_id == $post->post_author )
+	// Who to notify? By default, just the post author, but others can be added.
+	$emails = array( $author->user_email );
+	$emails = apply_filters( 'comment_notification_recipients', $emails, $comment_id );
+	$emails = array_filter( $emails );
+
+	// If there are no addresses to send the comment to, bail.
+	if ( ! count( $emails ) ) {
 		return false;
+	}
 
+	// Facilitate unsetting below without knowing the keys.
+	$emails = array_flip( $emails );
+
+	// The comment was left by the author
+	if ( ! apply_filters( 'comment_notification_notify_author', false, $comment_id ) && $comment->user_id == $post->post_author ) {
+		unset( $emails[ $author->user_email ] );
+	}
+
 	// The author moderated a comment on his own post
-	if ( $post->post_author == get_current_user_id() )
-		return false;
+	if ( ! apply_filters( 'comment_notification_author_moderated', false, $comment_id ) && $post->post_author == get_current_user_id() ) {
+		unset( $emails[ $author->user_email ] );
+	}
 
 	// The post author is no longer a member of the blog
-	if ( ! user_can( $post->post_author, 'read_post', $post->ID ) )
-		return false;
+	if ( ! apply_filters( 'comment_notification_notify_author_not_on_blog', false, $comment_id ) && ! user_can( $post->post_author, 'read_post', $post->ID ) ) {
+		unset( $emails[ $author->user_email ] );
+	}
 
-	// If there's no email to send the comment to
-	if ( '' == $author->user_email )
+	// If there's no email to send the comment to, bail, otherwise flip array back around for use below
+	if ( ! count( $emails ) ) {
 		return false;
+	} else {
+		$emails = array_flip( $emails );
+	}
 
 	$comment_author_domain = @gethostbyaddr($comment->comment_author_IP);
 
@@ -1038,7 +1068,9 @@
 	// we want to reverse this for the plain text arena of emails.
 	$blogname = wp_specialchars_decode(get_option('blogname'), ENT_QUOTES);
 
-	if ( empty( $comment_type ) ) $comment_type = 'comment';
+	if ( empty( $comment_type ) ) {
+		$comment_type = 'comment';
+	}
 
 	switch ( $comment_type ) {
 		case 'trackback':
@@ -1078,10 +1110,12 @@
 	$notify_message .= sprintf( __('Permalink: %s'), get_permalink( $comment->comment_post_ID ) . '#comment-' . $comment_id ) . "\r\n";
 
 	if ( user_can( $post->post_author, 'edit_comment', $comment_id ) ) {
-		if ( EMPTY_TRASH_DAYS )
+		if ( EMPTY_TRASH_DAYS ) {
 			$notify_message .= sprintf( __('Trash it: %s'), admin_url("comment.php?action=trash&c=$comment_id") ) . "\r\n";
-		else
+		} else {
 			$notify_message .= sprintf( __('Delete it: %s'), admin_url("comment.php?action=delete&c=$comment_id") ) . "\r\n";
+		}
+
 		$notify_message .= sprintf( __('Spam it: %s'), admin_url("comment.php?action=spam&c=$comment_id") ) . "\r\n";
 	}
 
@@ -1089,23 +1123,23 @@
 
 	if ( '' == $comment->comment_author ) {
 		$from = "From: \"$blogname\" <$wp_email>";
-		if ( '' != $comment->comment_author_email )
+		if ( '' != $comment->comment_author_email ) {
 			$reply_to = "Reply-To: $comment->comment_author_email";
+		}
 	} else {
 		$from = "From: \"$comment->comment_author\" <$wp_email>";
-		if ( '' != $comment->comment_author_email )
+		if ( '' != $comment->comment_author_email ) {
 			$reply_to = "Reply-To: \"$comment->comment_author_email\" <$comment->comment_author_email>";
+		}
 	}
 
 	$message_headers = "$from\n"
 		. "Content-Type: text/plain; charset=\"" . get_option('blog_charset') . "\"\n";
 
-	if ( isset($reply_to) )
+	if ( isset( $reply_to ) ) {
 		$message_headers .= $reply_to . "\n";
+	}
 
-	$emails = array( $author->user_email );
-
-	$emails          = apply_filters( 'comment_notification_recipients', $emails,          $comment_id );
 	$notify_message  = apply_filters( 'comment_notification_text',       $notify_message,  $comment_id );
 	$subject         = apply_filters( 'comment_notification_subject',    $subject,         $comment_id );
 	$message_headers = apply_filters( 'comment_notification_headers',    $message_headers, $comment_id );
