Index: src/bp-groups/bp-groups-functions.php
===================================================================
--- src/bp-groups/bp-groups-functions.php
+++ src/bp-groups/bp-groups-functions.php
@@ -1037,29 +1037,88 @@
 /**
  * Send all pending invites by a single user to a specific group.
  *
- * @param int $user_id ID of the inviting user.
+ * @param int $inviter_id ID of the inviting user.
  * @param int $group_id ID of the group.
+ * @return bool False if there's actually a problem, true if the invitations that need to be sent are sent successfully (or if there's nothing to do).
  */
-function groups_send_invites( $user_id, $group_id ) {
+function groups_send_invites( $inviter_id, $group_id ) {
 
-	if ( empty( $user_id ) )
-		$user_id = bp_loggedin_user_id();
+	if ( empty( $inviter_id ) ) {
+		$inviter_id = bp_loggedin_user_id();
+	}
+	if ( empty( $group_id ) ) {
+		$group_id = bp_get_current_group_id();
+	}
 
-	// Send friend invites.
-	$invited_users = groups_get_invites_for_group( $user_id, $group_id );
-	$group = groups_get_group( array( 'group_id' => $group_id ) );
+	// If the inviter can't extend invitations to this group, bail.
+	if ( ! bp_groups_user_can_send_invites( $group_id, $inviter_id ) ) {
+		return false;
+	}
 
-	for ( $i = 0, $count = count( $invited_users ); $i < $count; ++$i ) {
-		$member = new BP_Groups_Member( $invited_users[$i], $group_id );
+	// Get outstanding invites to the group from this user.
+	$invited_users = groups_get_invites_for_group( $inviter_id, $group_id );
+	$success = 0;
 
-		// Send the actual invite
-		groups_notification_group_invites( $group, $member, $user_id );
+	foreach ( $invited_users as $invitee_id ) {
+		if ( groups_send_invite_by_invitee( $group_id, $invitee_id, $inviter_id, $resend = false ) ) {
+			$success++;
+		}
+	}
 
-		$member->invite_sent = 1;
-		$member->save();
+	// If all invitations were successfully sent, return success.
+	if ( count( $invited_users ) == $success ) {
+		return true;
+	} else {
+		return false;
 	}
 
-	do_action( 'groups_send_invites', $group_id, $invited_users );
+}
+
+/**
+ * Send specific pending group invitations keyed by group and invitee id
+ *
+ * @param int 	$group_id 	ID of the group.
+ * @param int 	$invitee_id ID of the invited user.
+ * @param int 	$inviter_id ID of the user who created the invitation.
+ * @param bool 	$resend 	Whether to resend notification email if already sent.
+ *
+ * @since BuddyPress (2.2.0)
+ */
+function groups_send_invite_by_invitee( $group_id, $invitee_id, $inviter_id, $resend = false ) {
+
+	if ( empty( $group_id ) || empty( $invitee_id ) || empty( $inviter_id ) ) {
+		return false;
+	}
+
+	// Check that an invitation exists for this user/group combination.
+	// $type = 'all' checks for sent or unsent invitations.
+	// @TODO: If #5911 is adopted, add $inviter_id argument.
+	if ( ! groups_check_user_has_invite( $invitee_id, $group_id, $type = 'all' ) ) {
+		return false;
+	}
+
+	$group = groups_get_group( array( 'group_id' => $group_id ) );
+	$member = new BP_Groups_Member( $invitee_id, $group_id );
+
+	// Send the invitation email.
+	$sent = groups_notification_group_invites( $group, $member, $inviter_id, $resend );
+	// Save the invite_sent property if applicable.
+	$saved = false;
+
+	if ( $sent ) {
+		if ( ! empty( $member->invite_sent ) ) {
+			// Nothing to update
+			$saved = true;
+		} else {
+			$member->invite_sent = 1;
+			$saved = $member->save();
+		}
+	}
+
+	do_action( 'groups_send_invites', $group_id, array( $invitee_id ) );
+
+	$success = ( $sent && $saved ) ? true : false;
+	return $success;
 }
 
 /**
Index: src/bp-groups/bp-groups-notifications.php
===================================================================
--- src/bp-groups/bp-groups-notifications.php
+++ src/bp-groups/bp-groups-notifications.php
@@ -354,16 +354,28 @@
  *
  * @since BuddyPress (1.0.0)
  *
- * @param BP_Groups_Group $group Group object.
- * @param BP_Groups_Member $member Member object.
- * @param int $inviter_user_id ID of the user who sent the invite.
- * @return bool|null False on failure.
+ * @param 	BP_Groups_Group  $group  Group object.
+ * @param 	BP_Groups_Member  $member  Member object.
+ * @param 	int  $inviter_user_id  ID of the user who sent the invite.
+ * @param 	bool  $resend  Whether to resend notification email if already sent.
+ * @return 	bool False on failure, true if success or nothing needed to be done.
  */
-function groups_notification_group_invites( &$group, &$member, $inviter_user_id ) {
+function groups_notification_group_invites( &$group, &$member, $inviter_user_id, $resend = false ) {
 
-	// Bail if member has already been invited
-	if ( ! empty( $member->invite_sent ) ) {
-		return;
+	// Bail if the group and member objects are not populated.
+	if ( empty( $group->id ) || empty( $member->id ) ) {
+		return false;
+	}
+
+	// Bail if the passed $inviter_user_id isn't the inviter as recorded in the BP_Groups_Member object.
+	// @TODO: This will be resolved by #5911's change to groups_check_user_has_invite()
+	if ( $inviter_user_id != $member->inviter_id ) {
+		return false;
+	}
+
+	// Bail if member has already been invited and $resend isn't specified.
+	if ( ! $resend && ! empty( $member->invite_sent ) ) {
+		return true;
 	}
 
 	// @todo $inviter_ud may be used for caching, test without it
@@ -421,9 +433,11 @@
 	$subject = apply_filters_ref_array( 'groups_notification_group_invites_subject', array( $subject, &$group ) );
 	$message = apply_filters_ref_array( 'groups_notification_group_invites_message', array( $message, &$group, $inviter_name, $inviter_link, $invites_link, $group_link, $settings_link ) );
 
-	wp_mail( $to, $subject, $message );
+	$success = wp_mail( $to, $subject, $message );
 
 	do_action( 'bp_groups_sent_invited_email', $invited_user_id, $subject, $message, $group );
+
+	return $success;
 }
 
 /** Notifications *************************************************************/
Index: tests/phpunit/testcases/groups/class-bp-groups-member.php
===================================================================
--- tests/phpunit/testcases/groups/class-bp-groups-member.php
+++ tests/phpunit/testcases/groups/class-bp-groups-member.php
@@ -12,19 +12,33 @@
 		parent::tearDown();
 	}
 
-	public static function invite_user_to_group( $user_id, $group_id, $inviter_id ) {
+	public static function invite_user_to_group( $user_id, $group_id, $inviter_id, $draft = false ) {
 		$invite                = new BP_Groups_Member;
 		$invite->group_id      = $group_id;
 		$invite->user_id       = $user_id;
 		$invite->date_modified = bp_core_current_time();
 		$invite->inviter_id    = $inviter_id;
 		$invite->is_confirmed  = 0;
-		$invite->invite_sent   = 1;
+		$invite->invite_sent   = $draft ? 0 : 1;
 
 		$invite->save();
 		return $invite->id;
 	}
 
+	public static function create_group_membership_request( $user_id, $group_id ) {
+		// Pending membership requests have inviter_id = 0, is_confirmed = 0
+		$request                = new BP_Groups_Member;
+		$request->group_id      = $group_id;
+		$request->user_id       = $user_id;
+		$request->date_modified = bp_core_current_time();
+		$request->inviter_id    = 0;
+		$request->is_confirmed  = 0;
+		$request->is_admin  = 0;
+
+		$request->save();
+		return $request->id;
+	}
+
 	public function test_get_recently_joined_with_filter() {
 		$g1 = $this->factory->group->create( array(
 			'name' => 'Tab',
@@ -217,5 +231,156 @@
 
 		$this->set_current_user( $old_current_user );
 	}
+
+	public function test_groups_send_invite_by_invitee() {
+		$g1 = $this->factory->group->create();
+
+		$u1 = $this->factory->user->create();
+		$u2 = $this->factory->user->create();
+		$u3 = $this->factory->user->create();
+		$u4 = $this->factory->user->create();
+		self::add_user_to_group( $u1, $g1 );
+
+		// Test expected functionality
+		self::invite_user_to_group( $u2, $g1, $u1, $draft = true );
+		$this->assertTrue( is_null( groups_check_user_has_invite( $u2, $g1, $type = 'sent' ) ) );
+
+		$success = groups_send_invite_by_invitee( $g1, $u2, $u1 );
+
+		$this->assertTrue( $success );
+		$this->assertTrue( is_numeric( groups_check_user_has_invite( $u2, $g1, $type = 'sent' ) ) );
+		unset( $success );
+
+		// Test when user doesn't have invitation.
+		$this->assertTrue( is_null( groups_check_user_has_invite( $u3, $g1, $type = 'sent' ) ) );
+
+		$success = groups_send_invite_by_invitee( $g1, $u3, $u1 );
+
+		$this->assertFalse( $success );
+		unset( $success );
+
+		// Test when user has submitted a request for membership, but has not been invited
+		self::create_group_membership_request( $u3, $g1 );
+		$this->assertTrue( is_numeric( groups_check_for_membership_request( $u3, $g1 ) ) );
+		$this->assertTrue( is_null( groups_check_user_has_invite( $u3, $g1, $type = 'all' ) ) );
+
+		$success = groups_send_invite_by_invitee( $g1, $u3, $u1 );
+
+		$this->assertFalse( $success );
+		unset( $success );
+
+		// Test when user already belongs to the group
+		self::add_user_to_group( $u4, $g1 );
+
+		$success = groups_send_invite_by_invitee( $g1, $u4, $u1 );
+
+		$this->assertFalse( $success );
+		unset( $success );
+
+		// Test when user/group isn't specified
+		$success = groups_send_invite_by_invitee( null, $u2, $u1 );
+
+		$this->assertFalse( $success );
+		unset( $success );
+
+		$success = groups_send_invite_by_invitee( $g1, null, $u1 );
+
+		$this->assertFalse( $success );
+		unset( $success );
+
+		// Test when user/group doesn't exist
+		// Bad group ID
+		$success = groups_send_invite_by_invitee( 457819810, $u2, $u1 );
+
+		$this->assertFalse( $success );
+		unset( $success );
+
+		// Bad invitee ID
+		$success = groups_send_invite_by_invitee( $g1, 47161302, $u1 );
+
+		$this->assertFalse( $success );
+		unset( $success );
+
+		// Bad inviter ID
+		$success = groups_send_invite_by_invitee( $g1, $u2, 472816989 );
+
+		$this->assertFalse( $success );
+		unset( $success );
+	}
+
+	public function test_groups_send_invites() {
+		$g1 = $this->factory->group->create();
+		$g1_obj = groups_get_group( array( 'group_id' => $g1 ) );
+
+		$u1 = $this->factory->user->create();
+		$u2 = $this->factory->user->create();
+		$u3 = $this->factory->user->create();
+		$u4 = $this->factory->user->create();
+		$u5 = $this->factory->user->create();
+
+		$old_current_user = get_current_user_id();
+
+		self::add_user_to_group( $u1, $g1 );
+
+		// Test expected functionality
+		// Create some draft invitations that we can send
+		self::invite_user_to_group( $u2, $g1, $u1, $draft = true );
+		self::invite_user_to_group( $u3, $g1, $u1, $draft = true );
+
+		$success = groups_send_invites( $u1, $g1 );
+
+		$this->assertTrue( $success );
+		unset( $success );
+
+		// User has no outstanding invites to send.
+		self::add_user_to_group( $u4, $g1 );
+		$success = groups_send_invites( $u4, $g1 );
+
+		$this->assertTrue( $success );
+		unset( $success );
+
+		// User doesn't belong to group.
+		$success = groups_send_invites( $u5, $g1 );
+
+		$this->assertFalse( $success );
+		unset( $success );
+
+		// Test when user/group isn't specified
+		// User isn't specified, but current user does have outstanding invites.
+		$this->set_current_user( $u1 );
+
+		$success = groups_send_invites( null, $g1 );
+
+		$this->assertTrue( $success );
+		unset( $success );
+		$this->set_current_user( $old_current_user );
+
+		// Group isn't specified, we're not in a group context
+		$success = groups_send_invites( $u1, null );
+
+		$this->assertFalse( $success );
+		unset( $success );
+
+		// Group isn't specified, we are in a group context
+		$this->go_to( bp_get_group_permalink( $g1_obj ) );
+
+		$success = groups_send_invites( $u1, null );
+
+		$this->assertTrue( $success );
+		unset( $success );
+
+		// Test when user/group doesn't exist
+		// Bad user ID
+		$success = groups_send_invites( 569845135, $g1 );
+
+		$this->assertFalse( $success );
+		unset( $success );
+
+		// Bad group ID
+		$success = groups_send_invites( $u1, 586234125 );
+
+		$this->assertFalse( $success );
+		unset( $success );
+	}
 }
 
