diff --git a/commons_groups.features.inc b/commons_groups.features.inc
index 7d7bcef..07d67a5 100644
--- a/commons_groups.features.inc
+++ b/commons_groups.features.inc
@@ -114,14 +114,14 @@ function commons_groups_default_message_type() {
     "arguments" : null,
     "message_text" : { "und" : [
         {
-          "value" : "You have a Trusted-Contact request pending from [message:field-requesting-user:name]",
+          "value" : "\\u003Cp\\u003EYou have a Trusted-Contact request pending from [message:field-requesting-user:name]\\u003C\\/p\\u003E\\r\\n",
           "format" : "full_html",
-          "safe_value" : "You have a Trusted-Contact request pending from [message:field-requesting-user:name]"
+          "safe_value" : "\\u003Cp\\u003EYou have a Trusted-Contact request pending from [message:field-requesting-user:name]\\u003C\\/p\\u003E\\n"
         },
         {
-          "value" : "\\u003Cp\\u003EHello,\\u003C\\/p\\u003E\\r\\n\\r\\n\\u003Cp\\u003EYou have a Trusted-Contact request pending from [message:field-requesting-user:name]\\u003C\\/p\\u003E\\r\\n\\r\\n\\u003Cp\\u003EYou may approve\\u0026nbsp;or ignore.\\u003C\\/p\\u003E\\r\\n\\r\\n\\u003Cp\\u003E@{approve-url} | \\u003Cspan\\u003E@{ignore-url}\\u003C\\/span\\u003E\\u003C\\/p\\u003E",
+          "value" : "\\u003Cp\\u003EHello,\\u003C\\/p\\u003E\\r\\n\\r\\n\\u003Cp\\u003EYou have a Trusted-Contact request pending from [message:field-requesting-user:name]\\u003C\\/p\\u003E\\r\\n\\r\\n\\u003Cp\\u003EYou may approve or ignore.\\u003C\\/p\\u003E\\r\\n\\r\\n\\u003Cp\\u003E\\u003Ca href=\\u0022@{approve-url}\\u0022\\u003EApprove\\u003C\\/a\\u003E | \\u003Ca href=\\u0022@{ignore-url}\\u0022\\u003EIgnore\\u003C\\/a\\u003E\\u003C\\/p\\u003E\\r\\n",
           "format" : "full_html",
-          "safe_value" : "\\u003Cp\\u003EHello,\\u003C\\/p\\u003E\\n\\n\\u003Cp\\u003EYou have a Trusted-Contact request pending from [message:field-requesting-user:name]\\u003C\\/p\\u003E\\n\\n\\u003Cp\\u003EYou may approve\\u0026nbsp;or ignore.\\u003C\\/p\\u003E\\n\\n\\u003Cp\\u003E@{approve-url} | \\u003Cspan\\u003E@{ignore-url}\\u003C\\/span\\u003E\\u003C\\/p\\u003E"
+          "safe_value" : "\\u003Cp\\u003EHello,\\u003C\\/p\\u003E\\n\\n\\u003Cp\\u003EYou have a Trusted-Contact request pending from [message:field-requesting-user:name]\\u003C\\/p\\u003E\\n\\n\\u003Cp\\u003EYou may approve or ignore.\\u003C\\/p\\u003E\\n\\n\\u003Cp\\u003E\\u003Ca href=\\u0022@{approve-url}\\u0022\\u003EApprove\\u003C\\/a\\u003E | \\u003Ca href=\\u0022@{ignore-url}\\u0022\\u003EIgnore\\u003C\\/a\\u003E\\u003C\\/p\\u003E\\n"
         }
       ]
     },
diff --git a/commons_groups.info b/commons_groups.info
index 0186640..80289f3 100644
--- a/commons_groups.info
+++ b/commons_groups.info
@@ -92,13 +92,7 @@ features[views_view][] = commons_groups_contributors
 features[views_view][] = commons_groups_directory
 features[views_view][] = commons_groups_recent_content
 features[views_view][] = commons_groups_user_groups
-
-; Information added by drush on 2013-04-22
-version = "7.x-3.0+21-dev"
-core = "7.x"
-project = "commons_groups"
-datestamp = "1366616163"
-
+features[views_view][] = private_messages
 features[views_view][] = trusted_contacts
 features[views_view][] = trusted_contacts_invitations
 features_exclude[field][message-trusted_contact_request_approved-field_approving_user] = message-trusted_contact_request_approved-field_approving_user
diff --git a/commons_groups.module b/commons_groups.module
index d393f4c..d1486bc 100644
--- a/commons_groups.module
+++ b/commons_groups.module
@@ -24,6 +24,9 @@ function commons_groups_entity_view($entity, $type, $view_mode, $langcode) {
   }
 }
 
+/**
+ * Implements hook_menu().
+ */
 function commons_groups_menu() {
   $items = array();
 
@@ -31,7 +34,7 @@ function commons_groups_menu() {
     'page callback' => 'commons_groups_request_trust',
     'page arguments' => array(1, 3),
     'access callback' => 'commons_groups_request_trust_access',
-    'access arguments'	=>	array(1,2),
+    'access arguments' => array(1,2),
     'type' => MENU_CALLBACK,
   );
 
@@ -39,7 +42,7 @@ function commons_groups_menu() {
     'page callback' => 'commons_groups_un_trust',
     'page arguments' => array(1, 3),
     'access callback' => 'commons_groups_un_trust_access',
-    'access arguments'	=>	array(1,2),
+    'access arguments' => array(1,2),
     'type' => MENU_CALLBACK,
   );
 
@@ -48,7 +51,7 @@ function commons_groups_menu() {
     'page callback' => 'commons_groups_approve_trust',
     'page arguments' => array(1),
     'access callback' => 'commons_groups_approve_trust_access',
-    'access arguments'	=>	array(1, 2),
+    'access arguments' => array(1, 2),
     'type' => MENU_CALLBACK,
   );
 
@@ -57,7 +60,15 @@ function commons_groups_menu() {
     'page callback' => 'commons_groups_ignore_trust',
     'page arguments' => array(1),
     'access callback' => 'commons_groups_ignore_trust_access',
-    'access arguments'	=>	array(1, 2),
+    'access arguments' => array(1, 2),
+    'type' => MENU_CALLBACK,
+  );
+
+  $items['contacts/messages/popup/%user'] = array(
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('commons_groups_messages_popup', 3),
+    'access callback' => 'commons_groups_privatemsg_write_access',
+    'access arguments' => array(2),
     'type' => MENU_CALLBACK,
   );
 
@@ -78,6 +89,17 @@ function commons_groups_menu_alter(&$items) {
 }
 
 /**
+ * Implements hook_admin_paths().
+ */
+function commons_groups_admin_paths() {
+  $paths = array(
+    'contacts/messages/popup/*' => TRUE,
+  );
+
+  return $paths;
+}
+
+/**
  * Implements hook_block_info().
  */
 function commons_groups_block_info() {
@@ -154,7 +176,6 @@ function commons_groups_commons_entity_integration() {
   );
 }
 
-
 function commons_groups_group_contributors_count_topics($group) {
 
   // Format the count of contributors.
@@ -196,7 +217,11 @@ function commons_groups_group_contributors_count_topics($group) {
   return $output;
 }
 
-/* set commons_Groups form alter to happen after views bulk operations */
+/**
+ * Implement hook_module_implements_alter().
+ *
+ * Set commons_Groups form alter to happen after views bulk operations.
+ */
 function commons_groups_module_implements_alter(&$implementations, $hook) {
   if ($hook == 'form_alter') {
     $group = $implementations['commons_groups'];
@@ -204,9 +229,10 @@ function commons_groups_module_implements_alter(&$implementations, $hook) {
     $implementations['commons_groups'] = $group;
   }
 }
+
 /**
-* Implements hook_form_alter().
-*/
+ * Implements hook_form_alter().
+ */
 function commons_groups_form_alter(&$form, &$form_state, $form_id) {
   if($form_id == 'views_exposed_form' && strstr($form['#id'], 'views-exposed-form-commons-groups-directory')) {
     $form['groups-keys']['#attributes'] = array(
@@ -249,7 +275,7 @@ function commons_groups_form_alter(&$form, &$form_state, $form_id) {
 }
 
 /**
- * Submit handler called if the form is for a node enabled as group content.
+ * Submit handler; Called if the form is for a node enabled as group content.
  */
 function commons_groups_node_in_group_submit(&$form, &$form_state) {
   if (isset($form_state['values']['og_group_ref'][LANGUAGE_NONE][0])) {
@@ -257,6 +283,7 @@ function commons_groups_node_in_group_submit(&$form, &$form_state) {
     $form_state['redirect'] = 'node/' . $group;
   }
 }
+
 /**
 * Implements hook_system_info_alter().
 */
@@ -352,7 +379,6 @@ function commons_groups_token_info() {
   );
 }
 
-
 /**
  * Implements hook_tokens().
  */
@@ -494,8 +520,8 @@ function commons_groups_entityreference_default_value($entity_type, $entity, $fi
 }
 
 /**
-* Implements hook_strongarm_alter().
-*/
+ * Implements hook_strongarm_alter().
+ */
  function commons_groups_strongarm_alter(&$items) {
   // Expose the Group content type for integration with Commons Radioactivity.
   if (isset($items['commons_radioactivity_entity_types'])) {
@@ -513,24 +539,24 @@ function commons_groups_default_rules_configuration_alter(&$configs) {
 }
 
 /**
-* Implements hook_node_update().
-*/
+ * Implements hook_node_update().
+ */
 function commons_groups_node_update($node) {
   $account = user_load($node->uid);
   commons_groups_first_contribution($account, $node);
 }
 
 /**
-* Implements hook_node_insert().
-*/
+ * Implements hook_node_insert().
+ */
 function commons_groups_node_insert($node) {
   $account = user_load($node->uid);
   commons_groups_first_contribution($account, $node);
 }
 
 /**
-* Returns an array of entity types that are enabled via Commons Groups.
-*/
+ * Returns an array of entity types that are enabled via Commons Groups.
+ */
 function commons_groups_get_group_content_entity_types() {
   // Find all Commons Entity integrations.
   $commons_entity_integrations = module_invoke_all('commons_entity_integration');
@@ -555,9 +581,9 @@ function commons_groups_get_group_content_entity_types() {
 }
 
 /**
-* When a user first creates content within a group,
-* grant her the contributor role within that group.
-*/
+ * When a user first creates content within a group,
+ * grant her the contributor role within that group.
+ */
 function commons_groups_first_contribution($account, $node) {
   // Find the groups that this piece of content belongs to.
   $groups = og_get_entity_groups('node', $node);
@@ -584,8 +610,8 @@ function commons_groups_first_contribution($account, $node) {
 }
 
 /**
-* Implements hook_commons_bw_group_widget().
-*/
+ * Implements hook_commons_bw_group_widget().
+ */
 function commons_groups_commons_bw_group_widget() {
   return array(
     'commons_all' => array(
@@ -653,7 +679,7 @@ function commons_groups_field_formatter_view($entity_type, $entity, $field, $ins
       list($id,, $bundle) = entity_extract_ids($entity_type, $entity);
       if (og_is_member($entity_type, $id, 'user', $account, array(OG_STATE_ACTIVE))) {
         $links['title'] = t('Message');
-        $links['href'] = "messages/new/$id";
+        $links['href'] = "contacts/messages/popup/$id";
       }
       else
         if (og_is_member($entity_type, $id, 'user', $account, array(OG_STATE_PENDING))) {
@@ -727,8 +753,8 @@ function commons_groups_field_formatter_view($entity_type, $entity, $field, $ins
 
     case 'approve_ignore':
 
-      $approve = l('Approve', 'approve-trust/' . $entity->id . '/' . $items[0]['value']);
-      $ignore = l('Ignore', 'ignore-trust/' . $entity->id . '/' . $items[0]['value']);
+      $approve = l(t('Approve'), 'approve-trust/' . $entity->id . '/' . $items[0]['value']);
+      $ignore = l(t('Ignore'), 'ignore-trust/' . $entity->id . '/' . $items[0]['value']);
 
       $element[0] = array(
         '#markup' =>  "$approve $ignore",
@@ -741,19 +767,22 @@ function commons_groups_field_formatter_view($entity_type, $entity, $field, $ins
 
 /**
  * Implements hook_og_membership_insert().
- *
- * @param OgMembership $og_membership
  */
 function commons_groups_og_membership_insert(OgMembership $og_membership) {
   if ($og_membership->type != 'trusted_contacts' || $og_membership->group_type != 'user') {
+    // Not a Trusted-Contact membership type.
     return;
   }
 
   if (!empty($og_membership->_skip_membership_insert)) {
+    // Prevent recursion.
     return;
   }
 
-  $token = md5(substr(str_shuffle('12458cdefghrstuvwxABCWXYZ'), 0, 10) . rand(100000, 999999));
+  // We're using a custom token because Drupal provides a token that relies on
+  // logged-in user, and here we want the token to be used by the responding
+  // user when approving/ignoring the logged-in user's request.
+  $token = md5(rand(100000000, 9999999999));
 
   $wrapper = entity_metadata_wrapper('og_membership', $og_membership);
   $wrapper->field_my_request->set(1);
@@ -764,6 +793,8 @@ function commons_groups_og_membership_insert(OgMembership $og_membership) {
     'field_name' => 'user_trusted_contacts',
     'state' => $og_membership->state,
   );
+
+  // Get a non-saved OG Membership object.
   $og_membership2 = og_group('user', $og_membership->etid, $values, FALSE);
 
   $wrapper2 = entity_metadata_wrapper('og_membership', $og_membership2);
@@ -776,7 +807,7 @@ function commons_groups_og_membership_insert(OgMembership $og_membership) {
   $wrapper2->save();
 
 
-  // Make sure OG membership is updated.
+  // Make sure OG membership is updated, and not re-inserted.
   unset($og_membership->is_new);
 
   $wrapper->save();
@@ -784,15 +815,15 @@ function commons_groups_og_membership_insert(OgMembership $og_membership) {
 
 /**
  * Implements hook_og_membership_update().
- *
- * @param OgMembership $og_membership
  */
 function commons_groups_og_membership_update(OgMembership $og_membership) {
   if ($og_membership->type != 'trusted_contacts' || $og_membership->group_type != 'user') {
+    // Not a Trusted-Contact membership type.
     return;
   }
 
   if (!empty($og_membership->_skip_membership_update)) {
+    // Prevent recursion.
     return;
   }
 
@@ -848,16 +879,12 @@ function commons_groups_og_membership_update(OgMembership $og_membership) {
   $wrapper2->save();
 }
 
-
 /**
  * Implements hook_og_membership_delete().
- *
- * @param OgMembership $og_membership
- *
- * @param $type
  */
 function commons_groups_og_membership_delete(OgMembership $og_membership, $type) {
   if ($og_membership->type != 'trusted_contacts' || $og_membership->group_type != 'user') {
+    // Not a Trusted-Contact membership type.
     return;
   }
 
@@ -870,11 +897,18 @@ function commons_groups_og_membership_delete(OgMembership $og_membership, $type)
   og_ungroup('user', $og_membership->etid, 'user', $og_membership->gid);
 }
 
+/**
+ * Menu callback; Creates a Trusted-Contact Invitation by adding two users to
+ * each-other's groups, and setting the memberships' states to 'Pending'.
+ *
+ * @param $account
+ *    The group in which the logged-in user wants to join.
+ */
 function commons_groups_request_trust($account, $ajax) {
   global $user;
 
   if ($account->uid == $user->uid) {
-    // User cannot join his own group.
+    // Users cannot join their own group.
     return;
   }
 
@@ -883,9 +917,12 @@ function commons_groups_request_trust($account, $ajax) {
 
   // Notify.
 
+  $wrapper = entity_metadata_wrapper('og_membership', $og_membership);
+  $token = $wrapper->field_membership_token->value();
+
   $arguments = array(
-    '@{approve-url}' => l('Approve', 'approve-trust/' . $og_membership->id . '/' . $token),
-    '@{ignore-url}' => l('Ignore', 'ignore-trust/' . $og_membership->id . '/' . $token),
+    '@{approve-url}' => 'approve-trust/' . $og_membership->id . '/' . $token,
+    '@{ignore-url}' => 'ignore-trust/' . $og_membership->id . '/' . $token,
   );
   $message = message_create('trusted_contact_request_pending', array('uid' => $account->uid, 'arguments' => $arguments));
 
@@ -908,10 +945,18 @@ function commons_groups_request_trust($account, $ajax) {
   }
 }
 
+/**
+ * Menu callback; "Breaks" a Trusted-Contact relation between two users by
+ * ungrouping each of them from the other's group.
+ *
+ * @param $account
+ *    The account which the logged-in user wants to break contact with.
+ */
 function commons_groups_un_trust($account, $ajax) {
   global $user;
 
-  // This actually deletes 2 OG memberships - one for each user.
+  // This actually deletes 2 OG memberships, one for each user,
+  // in commons_groups_og_membership_delete().
   og_ungroup('user', $account->uid);
 
   // Ajax
@@ -930,11 +975,19 @@ function commons_groups_un_trust($account, $ajax) {
   }
 }
 
+/**
+ * Menu callback; Approving a Trusted-Contact Invitation by setting each user's
+ * membership state to 'Active'.
+ *
+ * @param $og_membership
+ *    The membership in which the logged-in user is the group and the requesting
+ *    user is the member.
+ */
 function commons_groups_approve_trust(OgMembership $og_membership) {
   global $user;
 
   if ($og_membership->gid != $user->uid) {
-    // User can only approve his requests.
+    // Users can only approve their requests.
     return;
   }
 
@@ -960,11 +1013,19 @@ function commons_groups_approve_trust(OgMembership $og_membership) {
   drupal_goto('contacts/invitations');
 }
 
-function commons_groups_ignore_trust($og_membership) {
+/**
+ * Menu callback; Ignoring a Trusted-Contact Invitation by setting each user's
+ * membership state to 'Blocked'.
+ *
+ * @param $og_membership
+ *    The membership in which the logged-in user is the group and the requesting
+ *    user is the member.
+ */
+function commons_groups_ignore_trust(OgMembership $og_membership) {
   global $user;
 
   if ($og_membership->gid != $user->uid) {
-    // User can only ignore his requests.
+    // Users can only ignore their requests.
     return;
   }
 
@@ -977,25 +1038,55 @@ function commons_groups_ignore_trust($og_membership) {
   drupal_goto('contacts/invitations');
 }
 
+/**
+ * Access callback for creating a Trusted-Contact request; Makes sure that the
+ * token is correct.
+ *
+ * @param $account
+ *    The group in which the logged-in user wants to join.
+ */
 function commons_groups_request_trust_access($account, $token) {
   global $user;
 
   return drupal_valid_token($token, 'request' . ':' . $account->uid . ':' . $user->uid);
 }
 
+/**
+ * Access callback for breaking a Trusted-Contact relation; Makes sure that the
+ * token is correct.
+ *
+ * @param $account
+ *    The account which the logged-in user wants to break contact with.
+ */
 function commons_groups_un_trust_access($account, $token) {
   global $user;
 
-  return drupal_valid_token($token, 'un' . ':' . $account->uid . ':' . $user->uid);
+  return drupal_valid_token($token, 'untrust' . ':' . $account->uid . ':' . $user->uid);
 }
 
-function commons_groups_approve_trust_access($og_membership, $token) {
+/**
+ * Access callback for approving an invitation; Makes sure that the token is
+ * correct.
+ *
+ * @param $og_membership
+ *    The membership in which the logged-in user is the group and the requesting
+ *    user is the member.
+ */
+function commons_groups_approve_trust_access(OgMembership $og_membership, $token) {
   $wrapper = entity_metadata_wrapper('og_membership', $og_membership);
 
   return ($wrapper->field_membership_token->value() == $token);
 }
 
-function commons_groups_ignore_trust_access($og_membership, $token) {
+/**
+ * Access callback for ignoring an invitation; Makes sure that the token is
+ * correct.
+ *
+ * @param $og_membership
+ *    The membership in which the logged-in user is the group and the requesting
+ *    user is the member.
+ */
+function commons_groups_ignore_trust_access(OgMembership $og_membership, $token) {
   $wrapper = entity_metadata_wrapper('og_membership', $og_membership);
 
   return ($wrapper->field_membership_token->value() == $token);
@@ -1007,7 +1098,7 @@ function commons_groups_ignore_trust_access($og_membership, $token) {
  * @param $uid
  *    User ID.
  *
- * @param $uid2
+ * @param $account
  *    Optional; Other user's object. If not provided, current user will be used.
  */
 function commons_group_is_trusted_contact($uid, $account = NULL) {
@@ -1020,9 +1111,21 @@ function commons_group_is_trusted_contact($uid, $account = NULL) {
 }
 
 /**
- * Access callback.
+ * Access callback for writing a private message to another user;
+ * Checks permissions and makes sure that the given user and the logged-in user
+ * are Trusted-Contacts.
+ *
+ * @param $uid
+ *    Addressee's User ID.
  */
 function commons_groups_privatemsg_write_access($uid) {
+  global $user;
+
+  if ($user->uid == 1) {
+    // Always allow admin to send private messages.
+    return true;
+  }
+
   return (privatemsg_user_access('write privatemsg') && commons_group_is_trusted_contact($uid));
 }
 
@@ -1030,7 +1133,7 @@ function commons_groups_privatemsg_write_access($uid) {
  * Implement hook_form_FORM_alter().
  */
 function commons_groups_form_privatemsg_new_alter(&$form, &$form_state) {
-  $form['body']['#format'] = 'plain_text';
+  $form['body']['#type'] = 'plain_text';
 }
 
 /**
@@ -1067,6 +1170,7 @@ function commons_groups_operations_load_action_includes() {
   $files = array(
     'set_state_active.action.inc',
     'set_state_blocked.action.inc',
+    'mark_as_read.action.inc',
   );
 
   if (!$loaded) {
@@ -1078,3 +1182,41 @@ function commons_groups_operations_load_action_includes() {
 
   return $files;
 }
+
+/**
+ * Menu callback; Write Private Message popup form.
+ *
+ * @param $account
+ *    The addressee's account.
+ */
+function commons_groups_messages_popup($form, &$form_state, $account) {
+  $wrapper = entity_metadata_wrapper('user', $account);
+  $picture_path = empty($account->picture) ? variable_get('user_picture_default') : $wrapper->value()->picture->uri;
+
+  $form['user_picture'] = array(
+    '#theme' => 'image_style',
+    '#style_name' => '50x50_avatar',
+    '#path' => $picture_path,
+    '#prefix' => '<div class="user-picture">',
+    '#suffix' => '</div>',
+  );
+
+  $form['body'] = array(
+    '#type' => 'textarea',
+    '#rows' => 6,
+  );
+
+  $form['actions'] = array('#type' => 'actions');
+
+  $form['actions']['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Send'),
+  );
+
+  $form['actions']['full_form'] = array(
+    '#type' => 'markup',
+    '#markup' => l(t('Go to full form'), 'messages/new/' . $account->uid),
+  );
+
+  return $form;
+}
diff --git a/commons_groups.views_default.inc b/commons_groups.views_default.inc
index 62c20ac..6c2c58f 100644
--- a/commons_groups.views_default.inc
+++ b/commons_groups.views_default.inc
@@ -1116,6 +1116,150 @@ function commons_groups_views_default_views() {
   $export['commons_groups_user_groups'] = $view;
 
   $view = new view();
+  $view->name = 'private_messages';
+  $view->description = '';
+  $view->tag = 'default';
+  $view->base_table = 'pm_message';
+  $view->human_name = 'Private Messages';
+  $view->core = 7;
+  $view->api_version = '3.0';
+  $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */
+
+  /* Display: Master */
+  $handler = $view->new_display('default', 'Master', 'default');
+  $handler->display->display_options['title'] = 'Messages';
+  $handler->display->display_options['use_more_always'] = FALSE;
+  $handler->display->display_options['access']['type'] = 'none';
+  $handler->display->display_options['cache']['type'] = 'none';
+  $handler->display->display_options['query']['type'] = 'views_query';
+  $handler->display->display_options['exposed_form']['type'] = 'basic';
+  $handler->display->display_options['pager']['type'] = 'full';
+  $handler->display->display_options['pager']['options']['items_per_page'] = '10';
+  $handler->display->display_options['style_plugin'] = 'table';
+  /* Relationship: Privatemsg: Message author */
+  $handler->display->display_options['relationships']['privatemsg_author']['id'] = 'privatemsg_author';
+  $handler->display->display_options['relationships']['privatemsg_author']['table'] = 'pm_message';
+  $handler->display->display_options['relationships']['privatemsg_author']['field'] = 'privatemsg_author';
+  /* Field: Privatemsg: Thread ID */
+  $handler->display->display_options['fields']['thread_id']['id'] = 'thread_id';
+  $handler->display->display_options['fields']['thread_id']['table'] = 'pm_index';
+  $handler->display->display_options['fields']['thread_id']['field'] = 'thread_id';
+  $handler->display->display_options['fields']['thread_id']['label'] = '';
+  $handler->display->display_options['fields']['thread_id']['exclude'] = TRUE;
+  $handler->display->display_options['fields']['thread_id']['element_label_colon'] = FALSE;
+  /* Field: Privatemsg: Message ID */
+  $handler->display->display_options['fields']['privatemsg_id']['id'] = 'privatemsg_id';
+  $handler->display->display_options['fields']['privatemsg_id']['table'] = 'pm_message';
+  $handler->display->display_options['fields']['privatemsg_id']['field'] = 'privatemsg_id';
+  $handler->display->display_options['fields']['privatemsg_id']['label'] = '';
+  $handler->display->display_options['fields']['privatemsg_id']['exclude'] = TRUE;
+  $handler->display->display_options['fields']['privatemsg_id']['element_label_colon'] = FALSE;
+  /* Field: Bulk operations: Privatemsg */
+  $handler->display->display_options['fields']['views_bulk_operations']['id'] = 'views_bulk_operations';
+  $handler->display->display_options['fields']['views_bulk_operations']['table'] = 'pm_message';
+  $handler->display->display_options['fields']['views_bulk_operations']['field'] = 'views_bulk_operations';
+  $handler->display->display_options['fields']['views_bulk_operations']['label'] = '';
+  $handler->display->display_options['fields']['views_bulk_operations']['element_label_colon'] = FALSE;
+  $handler->display->display_options['fields']['views_bulk_operations']['vbo_settings']['display_type'] = '1';
+  $handler->display->display_options['fields']['views_bulk_operations']['vbo_settings']['enable_select_all_pages'] = 0;
+  $handler->display->display_options['fields']['views_bulk_operations']['vbo_settings']['force_single'] = 0;
+  $handler->display->display_options['fields']['views_bulk_operations']['vbo_settings']['entity_load_capacity'] = '10';
+  $handler->display->display_options['fields']['views_bulk_operations']['vbo_operations'] = array(
+    'action::views_bulk_operations_delete_item' => array(
+      'selected' => 1,
+      'postpone_processing' => 0,
+      'skip_confirmation' => 1,
+      'override_label' => 1,
+      'label' => 'Delete',
+    ),
+    'action::views_bulk_operations_script_action' => array(
+      'selected' => 0,
+      'postpone_processing' => 0,
+      'skip_confirmation' => 0,
+      'override_label' => 0,
+      'label' => '',
+    ),
+    'action::commons_groups_mark_as_read_action' => array(
+      'selected' => 1,
+      'postpone_processing' => 0,
+      'skip_confirmation' => 1,
+      'override_label' => 0,
+      'label' => '',
+    ),
+    'action::views_bulk_operations_modify_action' => array(
+      'selected' => 0,
+      'postpone_processing' => 0,
+      'skip_confirmation' => 0,
+      'override_label' => 0,
+      'label' => '',
+      'settings' => array(
+        'show_all_tokens' => 1,
+        'display_values' => array(
+          '_all_' => '_all_',
+        ),
+      ),
+    ),
+    'action::views_bulk_operations_argument_selector_action' => array(
+      'selected' => 0,
+      'skip_confirmation' => 0,
+      'override_label' => 0,
+      'label' => '',
+      'settings' => array(
+        'url' => '',
+      ),
+    ),
+    'action::system_send_email_action' => array(
+      'selected' => 0,
+      'postpone_processing' => 0,
+      'skip_confirmation' => 0,
+      'override_label' => 0,
+      'label' => '',
+    ),
+    'action::panelizer_set_status_action' => array(
+      'selected' => 0,
+      'postpone_processing' => 0,
+      'skip_confirmation' => 0,
+      'override_label' => 0,
+      'label' => '',
+    ),
+  );
+  /* Field: Privatemsg: Subject */
+  $handler->display->display_options['fields']['privatemsg_subject']['id'] = 'privatemsg_subject';
+  $handler->display->display_options['fields']['privatemsg_subject']['table'] = 'pm_message';
+  $handler->display->display_options['fields']['privatemsg_subject']['field'] = 'privatemsg_subject';
+  $handler->display->display_options['fields']['privatemsg_subject']['alter']['make_link'] = TRUE;
+  $handler->display->display_options['fields']['privatemsg_subject']['alter']['path'] = 'http://localhost/commons/messages/view/[thread_id]#privatemsg-mid-[privatemsg_id]';
+  $handler->display->display_options['fields']['privatemsg_subject']['element_label_colon'] = FALSE;
+  /* Field: User: Name */
+  $handler->display->display_options['fields']['name']['id'] = 'name';
+  $handler->display->display_options['fields']['name']['table'] = 'users';
+  $handler->display->display_options['fields']['name']['field'] = 'name';
+  $handler->display->display_options['fields']['name']['relationship'] = 'privatemsg_author';
+  $handler->display->display_options['fields']['name']['label'] = 'Author';
+  $handler->display->display_options['fields']['name']['element_label_colon'] = FALSE;
+  /* Field: Privatemsg: Privatemsg Send Date */
+  $handler->display->display_options['fields']['privatemsg_senddate']['id'] = 'privatemsg_senddate';
+  $handler->display->display_options['fields']['privatemsg_senddate']['table'] = 'pm_message';
+  $handler->display->display_options['fields']['privatemsg_senddate']['field'] = 'privatemsg_senddate';
+  $handler->display->display_options['fields']['privatemsg_senddate']['label'] = 'Recieved';
+  $handler->display->display_options['fields']['privatemsg_senddate']['element_label_colon'] = FALSE;
+  $handler->display->display_options['fields']['privatemsg_senddate']['date_format'] = 'time ago';
+  /* Contextual filter: Privatemsg: Recipient */
+  $handler->display->display_options['arguments']['recipient']['id'] = 'recipient';
+  $handler->display->display_options['arguments']['recipient']['table'] = 'pm_index';
+  $handler->display->display_options['arguments']['recipient']['field'] = 'recipient';
+  $handler->display->display_options['arguments']['recipient']['default_action'] = 'default';
+  $handler->display->display_options['arguments']['recipient']['default_argument_type'] = 'current_user';
+  $handler->display->display_options['arguments']['recipient']['summary']['number_of_records'] = '0';
+  $handler->display->display_options['arguments']['recipient']['summary']['format'] = 'default_summary';
+  $handler->display->display_options['arguments']['recipient']['summary_options']['items_per_page'] = '25';
+
+  /* Display: Page */
+  $handler = $view->new_display('page', 'Page', 'page');
+  $handler->display->display_options['path'] = 'contacts/messages';
+  $export['private_messages'] = $view;
+
+  $view = new view();
   $view->name = 'trusted_contacts';
   $view->description = '';
   $view->tag = 'default';
diff --git a/includes/actions/mark_as_read.action.inc b/includes/actions/mark_as_read.action.inc
new file mode 100644
index 0000000..1ce46b4
--- /dev/null
+++ b/includes/actions/mark_as_read.action.inc
@@ -0,0 +1,21 @@
+<?php
+/**
+ * @file
+ * Action to set the state of a user in a group.
+ */
+
+function commons_groups_mark_as_read_action_info() {
+  return array('commons_groups_mark_as_read_action' => array(
+    'type' => 'privatemsg_message',
+    'label' => t('Mark as read'),
+    'configurable' => FALSE,
+  ));
+}
+
+function commons_groups_mark_as_read_action($privatemsg_message) {
+  db_update('pm_index')
+    ->fields(array('is_new' => PRIVATEMSG_READ))
+    ->condition('mid', $privatemsg_message->mid)
+    ->execute();
+}
+
diff --git a/views/handlers/commons_groups_handler_send_message.inc b/views/handlers/commons_groups_handler_send_message.inc
index 001cac6..55ec4e8 100644
--- a/views/handlers/commons_groups_handler_send_message.inc
+++ b/views/handlers/commons_groups_handler_send_message.inc
@@ -3,6 +3,6 @@
 class commons_groups_handler_send_message extends views_handler_field {
 
   function render($values) {
-    return l('Send private message', 'messages/new/' . $values->og_membership_etid);
+    return l(t('Send private message'), 'contacts/messages/popup/' . $values->og_membership_etid);
   }
 }
