Index: wp-includes/comment.php
===================================================================
--- wp-includes/comment.php	(revision 22018)
+++ wp-includes/comment.php	(working copy)
@@ -1371,10 +1371,7 @@
 		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( $comment_ID, isset( $commentdata['comment_type'] ) ? $commentdata['comment_type'] : '' );
 	}
 
 	return $comment_ID;
@@ -1406,10 +1403,6 @@
 		case 'approve':
 		case '1':
 			$status = '1';
-			if ( get_option('comments_notify') ) {
-				$comment = get_comment($comment_id);
-				wp_notify_postauthor($comment_id, $comment->comment_type);
-			}
 			break;
 		case 'spam':
 			$status = 'spam';
@@ -1434,6 +1427,9 @@
 
 	$comment = get_comment($comment_id);
 
+	if ( '1' == $status )
+		wp_notify_postauthor( $comment_id, $comment->comment_type );
+
 	do_action('wp_set_comment_status', $comment_id, $comment_status);
 	wp_transition_comment_status($comment_status, $comment_old->comment_approved, $comment);
 
Index: wp-includes/pluggable.php
===================================================================
--- wp-includes/pluggable.php	(revision 22018)
+++ wp-includes/pluggable.php	(working copy)
@@ -980,6 +980,7 @@
  * Notify an author of a comment/trackback/pingback to one of their posts.
  *
  * @since 1.0.0
+ * @uses apply_filters() Calls 'wp_notify_postauthor' hook on get_option('comments_notify') and comment_approved value before processing
  *
  * @param int $comment_id Comment ID
  * @param string $comment_type Optional. The comment type either 'comment' (default), 'trackback', or 'pingback'
@@ -1002,6 +1003,13 @@
 	if ( '' == $author->user_email )
 		return false;
 
+	// Possibly notify if get_option( 'comments_notify' ) is true, comment is
+	// approved, and filter 'wp_notify_postauthor' doesn't override those values
+	$maybe_notify = get_option( 'comments_notify' ) && ( '1' == $comment->comment_approved );
+	$maybe_notify = apply_filters( 'wp_notify_postauthor', $maybe_notify, $comment );
+	if ( ! $maybe_notify )
+		return false;
+
 	$comment_author_domain = @gethostbyaddr($comment->comment_author_IP);
 
 	// The blogname option is escaped with esc_html on the way into the database in sanitize_option
