Index: src/bp-activity/bp-activity-notifications.php
===================================================================
--- src/bp-activity/bp-activity-notifications.php	(revision 10715)
+++ src/bp-activity/bp-activity-notifications.php	(working copy)
@@ -40,6 +40,7 @@
  * @param int $receiver_user_id The ID of the user who is receiving the update.
  */
 function bp_activity_at_message_notification( $activity_id, $receiver_user_id ) {
+
 	$notifications = BP_Core_Notification::get_all_for_user( $receiver_user_id, 'all' );
 
 	// Don't leave multiple notifications for the same activity item.
@@ -73,6 +74,13 @@
 			$group_name = bp_get_current_group_name();
 		}
 
+		$activity_link = bp_get_root_domain() . '/' . bp_get_activity_root_slug() . '/';
+		$unsubscribe_args = array( 
+						'uid' => (int)$receiver_user_id, 
+						'nt' => 'notification_activity_new_mention'
+					);
+		$unsubscribe_link = esc_url( bp_email_get_unsubscribe_link( $activity_link, $unsubscribe_args ) );
+
 		$args = array(
 			'tokens' => array(
 				'activity'         => $activity,
@@ -81,6 +89,7 @@
 				'mentioned.url'    => $message_link,
 				'poster.name'      => $poster_name,
 				'receiver-user.id' => $receiver_user_id,
+				'unsubscribe' 	   => $unsubscribe_link
 			),
 		);
 
@@ -152,6 +161,14 @@
 
 		// Send an email if the user hasn't opted-out.
 		if ( 'no' != bp_get_user_meta( $original_activity->user_id, 'notification_activity_new_reply', true ) ) {
+
+			$activity_link = bp_get_root_domain() . '/' . bp_get_activity_root_slug() . '/';
+			$unsubscribe_args = array( 
+				'uid' => (int)$original_activity->user_id, 
+				'nt' => 'notification_activity_new_reply'
+			);
+
+			$unsubscribe_link = esc_url( bp_email_get_unsubscribe_link( $activity_link, $unsubscribe_args ) );
 			$args = array(
 				'tokens' => array(
 					'comment.id'                => $comment_id,
@@ -160,6 +177,7 @@
 					'original_activity.user_id' => $original_activity->user_id,
 					'poster.name'               => $poster_name,
 					'thread.url'                => esc_url( $thread_link ),
+					'unsubscribe'				=> $unsubscribe_link
 				),
 			);
 
Index: src/bp-core/bp-core-actions.php
===================================================================
--- src/bp-core/bp-core-actions.php	(revision 10715)
+++ src/bp-core/bp-core-actions.php	(working copy)
@@ -108,3 +108,7 @@
 
 // Activation redirect.
 add_action( 'bp_activation', 'bp_add_activation_redirect' );
+
+// Email unsubscribe.
+add_action( 'bp_get_request_unsubscribe', 'bp_emails_unsubscribe' );
+
Index: src/bp-core/bp-core-filters.php
===================================================================
--- src/bp-core/bp-core-filters.php	(revision 10715)
+++ src/bp-core/bp-core-filters.php	(working copy)
@@ -1024,7 +1024,6 @@
 	$tokens['recipient.email']     = '';
 	$tokens['recipient.name']      = '';
 	$tokens['recipient.username']  = '';
-	$tokens['unsubscribe']         = site_url( 'wp-login.php' );
 
 
 	// Who is the email going to?
@@ -1041,12 +1040,6 @@
 		}
 
 		if ( $user_obj ) {
-			// Unsubscribe link.
-			$tokens['unsubscribe'] = esc_url( sprintf(
-				'%s%s/notifications/',
-				bp_core_get_user_domain( $user_obj->ID ),
-				function_exists( 'bp_get_settings_slug' ) ? bp_get_settings_slug() : 'settings'
-			) );
 			$tokens['recipient.username'] = $user_obj->user_login;
 		}
 	}
Index: src/bp-core/bp-core-functions.php
===================================================================
--- src/bp-core/bp-core-functions.php	(revision 10715)
+++ src/bp-core/bp-core-functions.php	(working copy)
@@ -2898,6 +2898,7 @@
  *                       on the email delivery class you are using.
  */
 function bp_send_email( $email_type, $to, $args = array() ) {
+
 	static $is_default_wpmail = null;
 	static $wp_html_emails    = null;
 
@@ -2954,7 +2955,6 @@
 
 	if ( $must_use_wpmail ) {
 		$to = $email->get( 'to' );
-
 		return wp_mail(
 			array_shift( $to )->get_address(),
 			$email->get( 'subject', 'replace-tokens' ),
@@ -2989,6 +2989,7 @@
 	}
 
 	$delivery = new $delivery_class();
+
 	$status   = $delivery->bp_email( $email );
 
 	if ( is_wp_error( $status ) ) {
@@ -3292,3 +3293,125 @@
 		'groups-membership-request-rejected' => __( 'Recipient had requested to join a group, which was rejected.', 'buddypress' ),
 	);
 }
+
+/**
+ * Handles unsubscribe action to unsubscribe user from notification emails.
+ *
+ * @since 
+ *
+ */
+function bp_emails_unsubscribe(){
+
+	$request = $_GET;
+	$admin_email   = get_bloginfo( 'admin_email' );
+	$notifications_with_unsubscribe = array(
+		'notification_activity_new_mention'		=> __( 'You will no longer receive emails when someone mentions you in an update.', 'buddypress' ),
+		'notification_activity_new_reply'		=> __( 'You will no longer receive emails when someone replies to an update or comment you posted.', 'buddypress' ),
+		'notification_messages_new_message'		=> __( 'You will no longer receive emails when someone sends you a message.', 'buddypress' ),
+		'notification_friends_friendship_request'	=> __( 'You will no longer receive emails when someone sends you a friend request.', 'buddypress' ),
+		'notification_friends_friendship_accepted'	=> __( 'You will no longer receive emails when someone accepts your friendship request.', 'buddypress' ),
+		'notification_groups_invite'			=> __( 'You will no longer receive emails when you are invited to join a group.', 'buddypress' ),
+		'notification_groups_group_updated'		=> __( 'You will no longer receive emails when one of your groups is updated.', 'buddypress' ),
+		'notification_groups_membership_request'	=> __( 'You will no longer receive emails when someone requests to be a member of your group.', 'buddypress' ),
+		'notification_membership_request_completed'	=> __( 'You will no longer receive emails when your request to join a group has been accepted or denied.', 'buddypress' ),
+		'notification_groups_admin_promotion'		=> __( 'You will no longer receive emails when you have been promoted in a group.', 'buddypress' )
+	);
+
+	$user_id = ( isset( $request['uid'] ) && !empty( $request['uid'] ) ) ? $request['uid'] : '';
+	$notification_type = ( isset( $request['nt'] ) && !empty( $request['nt'] ) ) ? $request['nt'] : '';
+	$to_check = ( isset( $request['nn'] ) && !empty( $request['nn'] ) ) ? $request['nn'] : '';
+
+	$check_args = array(
+		'uid' => $user_id,
+		'nt'  => $notification_type
+	);
+
+	$check = bp_check( $check_args );
+
+	$current_user = is_user_logged_in() ? wp_get_current_user() : false;
+
+	if( empty( $user_id ) || empty( $notification_type ) || empty( $to_check ) || ! array_key_exists( $notification_type, $notifications_with_unsubscribe ) ){
+
+		$settings_link = site_url( 'wp-login.php' );
+		$result_message = __( 'Sorry, something has gone wrong.', 'buddypress' );
+		$how_to_unsubscribe_message = __( 'Please log in and go to your settings to unsubscribe from notifications.', 'buddypress' );
+	}
+	elseif(  ! hash_equals( $check, $to_check ) ){
+
+		$settings_link = site_url( 'wp-login.php' );
+		$result_message = __( 'Sorry the security check failed.', 'buddypress' );
+		$how_to_unsubscribe_message = __( 'Please log in and go to your settings to unsubscribe from notifications.', 'buddypress' );
+
+	}
+	elseif( is_user_logged_in() && (int)$current_user->ID !== (int)$user_id ){
+		
+		$settings_link = esc_url( sprintf(
+			'%s%s/notifications/',
+			bp_core_get_user_domain( (int)$current_user->ID ),
+			function_exists( 'bp_get_settings_slug' ) ? bp_get_settings_slug() : 'settings'
+		) );
+
+		$result_message = __( 'Something has gone wrong.', 'buddypress' );
+		$how_to_unsubscribe_message = __( 'Please go to your settings to unsubscribe from notifications.', 'buddypress' );
+	}
+	else{
+		
+		$settings_link = esc_url( sprintf(
+			'%s%s/notifications/',
+			bp_core_get_user_domain( $user_id ),
+			function_exists( 'bp_get_settings_slug' ) ? bp_get_settings_slug() : 'settings'
+		) );
+
+		// unsubscribe them by setting the usermeta to 'no'
+		$is_unsubscribed = bp_update_user_meta( $user_id, $notification_type, 'no' );
+		$result_message = ( empty( $is_unsubscribed ) && bp_get_user_meta( $user_id, $notification_type, true ) !== 'no' ) ? __( 'Sorry, something has gone wrong with unsubscribing you from these emails.', 'buddypress' ) : $notifications_with_unsubscribe[ $notification_type ];
+		$how_to_unsubscribe_message = __( 'You can change this or any other email notification preferences in your email settings.', 'buddypress' );
+	}
+
+	$message = sprintf(
+		'%1$s <a href="%2$s">%3$s</a>',
+		$result_message,
+		$settings_link,
+		$how_to_unsubscribe_message
+	);
+
+	bp_core_add_message( $message );
+	bp_core_redirect( esc_url( remove_query_arg( array_keys( $request ) ) ) );
+}
+
+/**
+ * Creates unsubscribe link for notification emails.
+ *
+ * @since 
+ *
+ * @param string 	$link 	URL to which the unsubscribe query string is appended.
+ * @param array 	$args 	Used to build unsubscribe query string.
+ *
+ * @return string The unsubscribe link.
+ */
+function bp_email_get_unsubscribe_link( $link = null, $args = null ){
+
+	if( ! is_array( $args ) ){
+		return site_url( 'wp-login.php' );	
+	}
+
+	$check = bp_check( $args );
+
+	$args['nn'] = $check;
+	$args['action'] = 'unsubscribe';
+
+	$unsubscribe_link = esc_url( add_query_arg( $args, $link ) );
+
+	$args['link'] = esc_url( $link );
+
+	/**
+	 * Filters the unsubscribe link.
+	 *
+	 * @since 
+	 *
+	 * @param string 	$link 	URL to which the unsubscribe query string is appended.
+	 * @param array 	$args 	Used to build unsubscribe query string.
+	 */
+	return apply_filters( 'bp_email_get_unsubscribe_link', $unsubscribe_link, $args );
+}
+
Index: src/bp-core/bp-core-options.php
===================================================================
--- src/bp-core/bp-core-options.php	(revision 10715)
+++ src/bp-core/bp-core-options.php	(working copy)
@@ -893,3 +893,39 @@
 	 */
 	return apply_filters( 'bp_get_theme_package_id', bp_get_option( '_bp_theme_package_id', $default ) );
 }
+
+/** 
+ * Get a persistent salt not dependent on salts in wp-config.php.
+ *
+ * @return string 
+ * 
+ */
+function bp_get_salt(){
+
+	$salt = bp_get_option( 'bp_persistent_salt' );
+	if( ! $salt ){
+		$salt = base64_encode( mcrypt_create_iv(12, MCRYPT_DEV_URANDOM) );
+		bp_add_option( 'bp_persistent_salt', $salt );
+	}
+
+	return $salt;
+}
+
+/** 
+ * Get a function that makes a check for the given args.
+ *
+ * @param  array 	$args 	Any array.
+ *
+ * @return string 
+ * 
+ */
+function bp_check( $args ){
+
+	$salt = bp_get_salt();
+	$string = ( is_array( $args) ) ? implode( ':', $args ) : (string)$args;
+
+	// should this return a substring like the nonce does? It's quite long.
+	$check = hash_hmac( 'md5', $string, $salt );
+
+	return $check;
+}
Index: src/bp-friends/bp-friends-notifications.php
===================================================================
--- src/bp-friends/bp-friends-notifications.php	(revision 10715)
+++ src/bp-friends/bp-friends-notifications.php	(working copy)
@@ -32,6 +32,13 @@
 		return;
 	}
 
+	$friends_link = trailingslashit( esc_url( bp_core_get_user_domain( (int)$friend_id ) .  bp_get_friends_slug() ) );
+	$unsubscribe_args = array( 
+					'uid' => (int)$friend_id, 
+					'nt' => 'notification_friends_friendship_request'
+				);
+	$unsubscribe_link = esc_url( bp_email_get_unsubscribe_link( $friends_link, $unsubscribe_args ) );
+
 	$args = array(
 		'tokens' => array(
 			'friend-requests.url' => esc_url( bp_core_get_user_domain( $friend_id ) . bp_get_friends_slug() . '/requests/' ),
@@ -40,6 +47,7 @@
 			'initiator.id'        => $initiator_id,
 			'initiator.url'       => esc_url( bp_core_get_user_domain( $initiator_id ) ),
 			'initiator.name'      => bp_core_get_user_displayname( $initiator_id ),
+			'unsubscribe'		  => $unsubscribe_link
 		),
 	);
 	bp_send_email( 'friends-request', $friend_id, $args );
@@ -63,6 +71,13 @@
 		return;
 	}
 
+	$friends_link = trailingslashit( esc_url( bp_core_get_user_domain( (int)$initiator_id ) .  bp_get_friends_slug() ) );
+	$unsubscribe_args = array( 
+					'uid' => (int)$initiator_id, 
+					'nt' => 'notification_friends_friendship_accepted'
+				);
+	$unsubscribe_link = esc_url( bp_email_get_unsubscribe_link( $friends_link, $unsubscribe_args ) );
+
 	$args = array(
 		'tokens' => array(
 			'friend.id'      => $friend_id,
@@ -70,6 +85,7 @@
 			'friend.name'    => bp_core_get_user_displayname( $friend_id ),
 			'friendship.id'  => $friendship_id,
 			'initiator.id'   => $initiator_id,
+			'unsubscribe'	 => $unsubscribe_link
 		),
 	);
 	bp_send_email( 'friends-request-accepted', $initiator_id, $args );
Index: src/bp-groups/bp-groups-notifications.php
===================================================================
--- src/bp-groups/bp-groups-notifications.php	(revision 10715)
+++ src/bp-groups/bp-groups-notifications.php	(working copy)
@@ -68,6 +68,13 @@
 			continue;
 		}
 
+		$user_groups_link = bp_core_get_user_domain( (int)$user_id ) . bp_get_groups_slug();
+		$unsubscribe_args = array( 
+						'uid' => (int)$user_id, 
+						'nt' => 'notification_groups_group_updated'
+					);
+		$unsubscribe_link = esc_url( bp_email_get_unsubscribe_link( $user_groups_link, $unsubscribe_args ) );
+
 		$args = array(
 			'tokens' => array(
 				'changed_text' => $changed_text,
@@ -75,6 +82,7 @@
 				'group.id'     => $group_id,
 				'group.url'    => esc_url( bp_get_group_permalink( $group ) ),
 				'group.name'   => $group->name,
+				'unsubscribe'  => $unsubscribe_link
 			),
 		);
 		bp_send_email( 'groups-details-updated', (int) $user_id, $args );
@@ -124,6 +132,14 @@
 		return;
 	}
 
+	$user_groups_link = bp_core_get_user_domain( (int)$admin_id ) . bp_get_groups_slug();
+
+	$unsubscribe_args = array( 
+					'uid' => (int)$admin_id, 
+					'nt' => 'notification_groups_membership_request'
+				);
+	$unsubscribe_link = esc_url( bp_email_get_unsubscribe_link( $user_groups_link, $unsubscribe_args ) );
+
 	$group = groups_get_group( array( 'group_id' => $group_id ) );
 	$args  = array(
 		'tokens' => array(
@@ -136,6 +152,7 @@
 			'profile.url'          => esc_url( bp_core_get_user_domain( $requesting_user_id ) ),
 			'requesting-user.id'   => $requesting_user_id,
 			'requesting-user.name' => bp_core_get_user_displayname( $requesting_user_id ),
+			'unsubscribe'		   => $unsubscribe_link
 		),
 	);
 	bp_send_email( 'groups-membership-request', (int) $admin_id, $args );
@@ -172,6 +189,14 @@
 		return;
 	}
 
+	$user_groups_link = bp_core_get_user_domain( (int)$requesting_user_id ) . bp_get_groups_slug();
+
+	$unsubscribe_args = array( 
+					'uid' => (int)$requesting_user_id, 
+					'nt' => 'notification_membership_request_completed'
+				);
+	$unsubscribe_link = esc_url( bp_email_get_unsubscribe_link( $user_groups_link, $unsubscribe_args ) );
+
 	$group = groups_get_group( array( 'group_id' => $group_id ) );
 	$args  = array(
 		'tokens' => array(
@@ -180,6 +205,7 @@
 			'group.name'         => $group->name,
 			'group.url'          => esc_url( bp_get_group_permalink( $group ) ),
 			'requesting-user.id' => $requesting_user_id,
+			'unsubscribe'		 => $unsubscribe_link
 		),
 	);
 
@@ -226,6 +252,14 @@
 		return;
 	}
 
+	$user_groups_link = bp_core_get_user_domain( (int)$user_id ) . bp_get_groups_slug();
+
+	$unsubscribe_args = array( 
+					'uid' => (int)$user_id, 
+					'nt' => 'notification_groups_admin_promotion'
+				);
+	$unsubscribe_link = esc_url( bp_email_get_unsubscribe_link( $user_groups_link, $unsubscribe_args ) );
+
 	$group = groups_get_group( array( 'group_id' => $group_id ) );
 	$args  = array(
 		'tokens' => array(
@@ -235,6 +269,7 @@
 			'group.name'  => $group->name,
 			'promoted_to' => $promoted_to,
 			'user.id'     => $user_id,
+			'unsubscribe' => $unsubscribe_link
 		),
 	);
 	bp_send_email( 'groups-member-promoted', (int) $user_id, $args );
@@ -276,7 +311,13 @@
 		return;
 	}
 
-	$invited_link = bp_core_get_user_domain( $invited_user_id ) . bp_get_groups_slug();
+	$invited_link = bp_core_get_user_domain( (int)$invited_user_id ) . bp_get_groups_slug();
+	$unsubscribe_args = array( 
+					'uid' => (int)$invited_user_id, 
+					'nt' => 'notification_groups_invite'
+				);
+	$unsubscribe_link = esc_url( bp_email_get_unsubscribe_link( $invited_link, $unsubscribe_args ) );
+
 	$args         = array(
 		'tokens' => array(
 			'group'        => $group,
@@ -286,6 +327,7 @@
 			'inviter.url'  => bp_core_get_user_domain( $inviter_user_id ),
 			'inviter.id'   => $inviter_user_id,
 			'invites.url'  => esc_url( $invited_link . '/invites/' ),
+			'unsubscribe'  => $unsubscribe_link
 		),
 	);
 	bp_send_email( 'groups-invitation', (int) $invited_user_id, $args );
Index: src/bp-groups/bp-groups-screens.php
===================================================================
--- src/bp-groups/bp-groups-screens.php	(revision 10715)
+++ src/bp-groups/bp-groups-screens.php	(working copy)
@@ -1423,8 +1423,11 @@
 		$group_promo   = 'yes';
 
 	if ( !$group_request = bp_get_user_meta( bp_displayed_user_id(), 'notification_groups_membership_request', true ) )
-		$group_request = 'yes'; ?>
+		$group_request = 'yes'; 
 
+	if ( !$group_request_completed = bp_get_user_meta( bp_displayed_user_id(), 'notification_membership_request_completed', true ) )
+		$group_request_completed = 'yes'; ?>
+
 	<table class="notification-settings" id="groups-notification-settings">
 		<thead>
 			<tr>
@@ -1460,6 +1463,12 @@
 				<td class="yes"><input type="radio" name="notifications[notification_groups_membership_request]" id="notification-groups-membership-request-yes" value="yes" <?php checked( $group_request, 'yes', true ) ?>/><label for="notification-groups-membership-request-yes" class="bp-screen-reader-text"><?php _e( 'Yes, send email', 'buddypress' ); ?></label></td>
 				<td class="no"><input type="radio" name="notifications[notification_groups_membership_request]" id="notification-groups-membership-request-no" value="no" <?php checked( $group_request, 'no', true ) ?>/><label for="notification-groups-membership-request-no" class="bp-screen-reader-text"><?php _e( 'No, do not send email', 'buddypress' ); ?></label></td>
 			</tr>
+			<tr id="groups-notification-settings-request-completed">
+				<td></td>
+				<td><?php _ex( 'Your request to join a group has been approved or denied', 'group settings on notification settings page', 'buddypress' ) ?></td>
+				<td class="yes"><input type="radio" name="notifications[notification_membership_request_completed]" id="notification-groups-membership-request-completed-yes" value="yes" <?php checked( $group_request_completed, 'yes', true ) ?>/><label for="notification-groups-membership-request-completed-yes" class="bp-screen-reader-text"><?php _e( 'Yes, send email', 'buddypress' ); ?></label></td>
+				<td class="no"><input type="radio" name="notifications[notification_membership_request_completed]" id="notification-groups-membership-request-completed-no" value="no" <?php checked( $group_request_completed, 'no', true ) ?>/><label for="notification-groups-membership-request-completed-no" class="bp-screen-reader-text"><?php _e( 'No, do not send email', 'buddypress' ); ?></label></td>
+			</tr>
 
 			<?php
 
Index: src/bp-messages/bp-messages-notifications.php
===================================================================
--- src/bp-messages/bp-messages-notifications.php	(revision 10715)
+++ src/bp-messages/bp-messages-notifications.php	(working copy)
@@ -58,6 +58,13 @@
 			continue;
 		}
 
+		$messages_link = bp_get_root_domain() . '/' .  bp_get_activity_root_slug() . '/';
+		$unsubscribe_args = array( 
+						'uid' => (int)$recipient->user_id, 
+						'nt' => 'notification_messages_new_message'
+					);
+		$unsubscribe_link = esc_url( bp_email_get_unsubscribe_link( $messages_link, $unsubscribe_args ) );
+
 		$args = array(
 			'tokens' => array(
 				'usermessage' => wp_strip_all_tags( stripslashes( $message ) ),
@@ -64,6 +71,7 @@
 				'message.url' => esc_url( bp_core_get_user_domain( $recipient->user_id ) . bp_get_messages_slug() . '/view/' . $thread_id . '/' ),
 				'sender.name' => $sender_name,
 				'usersubject' => sanitize_text_field( stripslashes( $subject ) ),
+				'unsubscribe' => $unsubscribe_link
 			),
 		);
 		bp_send_email( 'messages-unread', $ud, $args );
