diff --git pm_email_notify/pm_email_notify.admin.inc pm_email_notify/pm_email_notify.admin.inc
index 0b22274..82d4a3a 100644
--- pm_email_notify/pm_email_notify.admin.inc
+++ pm_email_notify/pm_email_notify.admin.inc
@@ -17,10 +17,24 @@ function pm_email_notify_admin_settings_form() {
     '#collapsible' => FALSE,
     '#collapsed' => FALSE,
   );
-  $form['pm_email']['pm_email_notify_default'] = array(
+  $form['pm_email']['pm_email_notify_default_level'] = array(
+    '#type' => 'radios',
+    '#title' => t('Send users e-mail notifications'),
+    '#options' => array(
+      PM_EMAIL_NOTIFY_LEVEL_DISABLED => t('Never.'),
+      PM_EMAIL_NOTIFY_LEVEL_THREAD => t('Only for new threads.'),
+      PM_EMAIL_NOTIFY_LEVEL_ACTIVE => t('Only for new threads and threads they are active in.'),
+      PM_EMAIL_NOTIFY_LEVEL_ALL => t('For every message they receive.'),
+    ),
+    '#default_value' => variable_get('pm_email_notify_default_level', PM_EMAIL_NOTIFY_LEVEL_ALL),
+    '#description' => t('Default notification level.  Users may override.'),
+    '#weight' => 0,
+  );
+  $form['pm_email']['pm_email_notify_only_user'] = array(
     '#type' => 'checkbox',
-    '#title' => t('Notify users of new private messages by default'),
-    '#default_value' => variable_get('pm_email_notify_default', TRUE),
+    '#title' => t('Only send e-mail notifications to \'user\' recipients.'),
+    '#default_value' => variable_get('pm_email_notify_only_user', FALSE),
+    '#description' => t('Users may NOT override if this is checked.'),
     '#weight' => 0,
   );
 
diff --git pm_email_notify/pm_email_notify.install pm_email_notify/pm_email_notify.install
index 0a2c66f..ab46182 100644
--- pm_email_notify/pm_email_notify.install
+++ pm_email_notify/pm_email_notify.install
@@ -19,12 +19,19 @@ function pm_email_notify_schema() {
         'not null'      => TRUE,
         'unsigned'      => TRUE,
       ),
-      'email_notify_is_enabled' => array(
-        'description'   => 'Email Notification Status (Enabled=1, Disabled=0)',
+      'email_notify_level' => array(
+        'description'   => 'Email Notification Level',
         'type'          => 'int',
         'not null'      => TRUE,
         'unsigned'      => TRUE,
       ),
+      'email_notify_only_user' => array(
+        'description'   => 'Email Notification \'only user\' setting.',
+        'type'          => 'int',
+        'size'          => 'tiny',
+        'not null'      => TRUE,
+        'unsigned'      => TRUE,
+      ),
     ),
     'unique keys' => array(
       'user_id' => array('user_id')
@@ -51,3 +58,52 @@ function pm_email_notify_uninstall() {
   variable_del('pm_email_notify_from');
   drupal_uninstall_schema('pm_email_notify');
 }
+
+/**
+ * Change the 'email_notify_is_enabled' field to 'email_notify_level'.
+ */
+function pm_email_notify_update_6201() {
+  $ret = array();
+
+  // Change the field.
+  $spec = array(
+    'description'   => 'Email Notification Level',
+    'type'          => 'int',
+    'not null'      => TRUE,
+    'unsigned'      => TRUE,
+  );
+  db_change_field($ret, 'pm_email_notify', 'email_notify_is_enabled', 'email_notify_level', $spec);
+
+  // Update existing user settings.
+  db_query("UPDATE {pm_email_notify} SET email_notify_level = %d WHERE email_notify_level = 1", PM_EMAIL_NOTIFY_LEVEL_ALL);
+
+  // Update the site-wide default setting.
+  if (variable_get('pm_email_notify_default', TRUE)) {
+    variable_set('pm_email_notify_default_level', PM_EMAIL_NOTIFY_LEVEL_ALL);
+  }
+  else {
+    variable_set('pm_email_notify_default_level', PM_EMAIL_NOTIFY_LEVEL_DISABLED);
+  }
+  variable_del('pm_email_notify_default');
+
+  return $ret;
+}
+
+/**
+ * Add the 'email_notify_only_user' field.
+ */
+function pm_email_notify_update_6202() {
+  $ret = array();
+  $spec = array(
+    'description'   => 'Email Notification \'only user\' setting.',
+    'type'          => 'int',
+    'size'          => 'tiny',
+    'not null'      => TRUE,
+    'unsigned'      => TRUE,
+  );
+  db_add_field($ret, 'pm_email_notify', 'email_notify_only_user', $spec);
+  return $ret;
+}
+
+
+
diff --git pm_email_notify/pm_email_notify.module pm_email_notify/pm_email_notify.module
index 79f6aa3..5a6e7ac 100644
--- pm_email_notify/pm_email_notify.module
+++ pm_email_notify/pm_email_notify.module
@@ -7,6 +7,24 @@
  */
 
 /**
+ * Define constants.
+ */
+
+// Disable e-mail notifications.
+define('PM_EMAIL_NOTIFY_LEVEL_DISABLED', 0);
+
+// Enable e-mail notifications only for new threads.
+define('PM_EMAIL_NOTIFY_LEVEL_THREAD', 4);
+
+// Enable e-mail notifications only for new threads and messages in threads the
+// user authored or replied to.
+define('PM_EMAIL_NOTIFY_LEVEL_ACTIVE', 8);
+
+// Enable e-mail notifications for all messages.
+define('PM_EMAIL_NOTIFY_LEVEL_ALL', 12);
+
+
+/**
  * Implements hook_menu().
  */
 function pm_email_notify_menu() {
@@ -24,26 +42,121 @@ function pm_email_notify_menu() {
 }
 
 /**
- * Retrieve notification setting of a user.
- *
- * This function retrieves user's pm notification preference from database,
+ * This function retrieves user's pm notification level from database,
  * if user preference doesn't exist - it uses default value instead
+ */
+function _pm_email_notify_user_level($uid) {
+  static $levels = array();
+  // Cache the user's level in case this method is executed in
+  // batched operation.
+  if (!isset($levels[$uid])) {
+    $levels[$uid] = db_result(db_query('SELECT email_notify_level FROM {pm_email_notify} WHERE user_id = %d', $uid));
+    if ($levels[$uid] === FALSE) {
+      // db_result() returns FALSE if result was not found.
+      $levels[$uid] = variable_get('pm_email_notify_default_level', PM_EMAIL_NOTIFY_LEVEL_ALL);
+    }
+  }
+  return $levels[$uid];
+}
+
+/**
+ * Check if a user should only receive notifications when they are a 'user'
+ * type recipient.
+ */
+function _pm_email_notify_only_user($uid = NULL) {
+  static $cache;
+  $only_user = variable_get('pm_email_notify_only_user', FALSE);
+
+  // The default setting should be honored if it is set.
+  if (!$only_user && $uid) {
+    if (!isset($cache[$uid])) {
+      $cache[$uid] = db_result(db_query("SELECT email_notify_only_user FROM {pm_email_notify} WHERE user_id = %d", $uid));
+      if ($cache[$uid] === FALSE) {
+        $cache[$uid] = $only_user;
+      }
+    }
+    $only_user = $cache[$uid];
+  }
+
+  return $only_user;
+}
+
+/**
+ * Retrieve notification setting of a user and check if they should receive
+ * an e-mail notification for a message.
+ *
+ * Note: This function tries to return as quickly as possible, to avoid extra
+ * processing in batch executions.
  *
  * @param $uid
  *   User uid
+ * @param $message
+ *   Message.
  */
-function _pm_email_notify_is_enabled($uid) {
+function _pm_email_notify_send_check($uid, $message) {
   static $notifications = array();
-  // Cache the result set in case this method is executed in batched operation which will perform many unnecessary repeated selects for the same user
-  if ( !isset($notifications[$uid]) ) {
-    $mail_notification = db_result(db_query('SELECT email_notify_is_enabled FROM {pm_email_notify} WHERE user_id = %d', $uid));
-    if ($mail_notification === FALSE) {
-      // db_result() returns FALSE if result was not found.
-      $mail_notification = variable_get('pm_email_notify_default', TRUE);
+  static $threads = array();
+
+  $mid = $message['mid'];
+  $thread_id = $message['thread_id'];
+  $level = _pm_email_notify_user_level($uid);
+
+  // If the user has notifications disabled, we can skip the rest.
+  if ($level == PM_EMAIL_NOTIFY_LEVEL_DISABLED) {
+    return FALSE;
+  }
+
+  // If the user has all notifications enabled, we can skip the rest.
+  if ($level == PM_EMAIL_NOTIFY_LEVEL_ALL) {
+    return TRUE;
+  }
+
+  // Cache the result set in case this method is executed in batched operation
+  // which will perform many unnecessary repeated processing.
+  if (!isset($notifications[$uid][$mid])) {
+    // Prime the setting to false.
+    $notifications[$uid][$mid] = FALSE;
+
+    if ($level == PM_EMAIL_NOTIFY_LEVEL_THREAD) {
+      // Is this the origin of a thread?
+      $notifications[$uid][$mid] = ($mid == $thread_id);
+    }
+    elseif ($level == PM_EMAIL_NOTIFY_LEVEL_ACTIVE) {
+      // Is this the origin of a thread?
+      if ($mid == $thread_id) {
+        $notifications[$uid][$mid] = TRUE;
+        return $notifications[$uid][$mid];
+      }
+
+      // Fetch the thread's original message.
+      if (!isset($threads[$thread_id])) {
+        $result = db_query("SELECT * FROM {pm_message} WHERE mid = %d", $thread_id);
+        $threads[$thread_id] = db_fetch_array($result);
+      }
+
+      // Is this user the thread author?
+      if ($uid == $threads[$thread_id]['author']) {
+        $notifications[$uid][$mid] = TRUE;
+        return $notifications[$uid][$mid];
+      }
+
+      // Fetch an array of users who have replied to this thread.
+      if (!isset($threads[$thread_id]['replied'])) {
+        $threads[$thread_id]['replied'] = array();
+        $result = db_query("SELECT pm.author FROM {pm_message} pm INNER JOIN {pm_index} pmi ON pm.mid = pmi.mid WHERE pmi.thread_id = %d", $thread_id);
+        while($recipient = db_result($result)) {
+          $threads[$thread_id]['replied'][$recipient] = $recipient;
+        }
+      }
+
+      // Has this user replied to this thread?
+      if (isset($threads[$thread_id]['replied']) && in_array($uid, $threads[$thread_id]['replied'])) {
+        $notifications[$uid][$mid] = TRUE;
+      }
     }
-    $notifications[$uid] = $mail_notification;
   }
-  return $notifications[$uid];
+
+  return $notifications[$uid][$mid];
 }
 
 /**
@@ -51,17 +164,47 @@ function _pm_email_notify_is_enabled($uid) {
  */
 function pm_email_notify_privatemsg_message_insert($message) {
   foreach ($message['recipients'] as $recipient) {
-    // check if recipient enabled email notifications
-    if (isset($recipient->uid) && _pm_email_notify_is_enabled($recipient->uid)) {
-      // send them a new pm notification email if they did
-      $params['recipient'] = $recipient;
-      $params['message'] = $message;
-      drupal_mail('pm_email_notify', 'notice', $recipient->mail, user_preferred_language($recipient), $params, variable_get('pm_email_notify_from',''));
+    pm_email_notify_send_mail($recipient, $message);
+  }
+}
+
+/**
+ * Implements hook_privatemsg_message_recipient_changed().
+ *
+ * Notifies users who were added to a message about new Private Messages
+ * via Email.
+ */
+function pm_email_notify_privatemsg_message_recipient_changed($mid, $thread_id, $recipient_id, $type, $added) {
+  $types = array('user');
+
+  // Only send mail if the recipient was added.
+  if ($added) {
+    if ($message = privatemsg_message_load($mid)) {
+      // Check if we should send an email to 'hidden' recipients.
+      if (!_pm_email_notify_only_user($recipient_id)) {
+        $types[] = 'hidden';
+      }
+      if (in_array($type, $types) && ($recipient = privatemsg_user_load($recipient_id))) {
+        pm_email_notify_send_mail($recipient, $message);
+      }
     }
   }
 }
 
 /**
+ * Send a pm notification email to a recipient.
+ */
+function pm_email_notify_send_mail($recipient, $message) {
+  // check if recipient enabled email notifications
+  if (isset($recipient->uid) && !empty($recipient->mail) && _pm_email_notify_send_check($recipient->uid, $message)) {
+    // send them a new pm notification email if they did
+    $params['recipient'] = $recipient;
+    $params['message'] = $message;
+    drupal_mail('pm_email_notify', 'notice', $recipient->mail, user_preferred_language($recipient), $params, variable_get('pm_email_notify_from',''));
+  }
+}
+
+/**
  * Implements hook_mail().
  */
 function pm_email_notify_mail($key, &$message, $params) {
@@ -148,27 +291,44 @@ function pm_email_notify_user($op, &$edit, &$account, $category = NULL) {
   switch ($op) {
     case 'form':
       if ($category == 'account' && privatemsg_user_access('read privatemsg')) {
-        $form['privatemsg']['pm_send_notifications'] = array(
-          '#type' => 'checkbox',
-          '#title' => t('Receive email notification for incoming private messages'),
-          '#default_value' => _pm_email_notify_is_enabled($account->uid),
+        $form['privatemsg']['pm_email_notify_level'] = array(
+          '#type' => 'radios',
+          '#title' => t('Send me e-mail notifications'),
+          '#options' => array(
+            PM_EMAIL_NOTIFY_LEVEL_DISABLED => t('Never.'),
+            PM_EMAIL_NOTIFY_LEVEL_THREAD => t('Only for new threads.'),
+            PM_EMAIL_NOTIFY_LEVEL_ACTIVE => t('Only for new threads and threads I am active in.'),
+            PM_EMAIL_NOTIFY_LEVEL_ALL => t('For every message I receive.'),
+          ),
+          '#default_value' => _pm_email_notify_user_level($account->uid),
         );
+
+        // Users can't even see this setting if the default is TRUE.
+        if (!_pm_email_notify_only_user()) {
+          $form['privatemsg']['pm_email_only_user'] = array(
+            '#type' => 'checkbox',
+            '#title' => t('Don\'t send me e-mail notifications for mass messages.'),
+            '#default_value' => _pm_email_notify_only_user($account->uid),
+          );
+        }
       }
       return $form;
 
     case 'submit':
-      if (isset($edit['pm_send_notifications']) && privatemsg_user_access('read privatemsg')) {
-        $pm_email_enabled = $edit['pm_send_notifications'];
-        unset($edit['pm_send_notifications']);
+      if (isset($edit['pm_email_notify_level']) && privatemsg_user_access('read privatemsg')) {
+        $email_notify_level = $edit['pm_email_notify_level'];
+        $email_only_user = $edit['pm_email_only_user'];
+        unset($edit['pm_email_notify_level']);
+        unset($edit['pm_email_only_user']);
         // Update database entry with user preference.
         $exists = db_result(db_query("SELECT 1 FROM {pm_email_notify} WHERE user_id = %d", $account->uid));
         if ($exists) {
           // If there is an existing entry, update.
-          db_query("UPDATE {pm_email_notify} SET email_notify_is_enabled = %d WHERE user_id = %d", $pm_email_enabled, $account->uid);
+          db_query("UPDATE {pm_email_notify} SET email_notify_level = %d, email_notify_only_user = %d WHERE user_id = %d", $email_notify_level, $email_notify_only_user, $account->uid);
         }
         else {
           // If not, create a new one.
-          db_query("INSERT INTO {pm_email_notify} (email_notify_is_enabled, user_id) VALUES (%d, %d)", $pm_email_enabled, $account->uid);
+          db_query("INSERT INTO {pm_email_notify} (email_notify_level, email_notify_only_user, user_id) VALUES (%d, %d, %d)", $email_notify_level, $email_notify_only_user, $account->uid);
         }
       }
       break;
diff --git privatemsg.api.php privatemsg.api.php
index 04a57d9..41e402a 100644
--- privatemsg.api.php
+++ privatemsg.api.php
@@ -371,14 +371,14 @@ function hook_privatemsg_message_insert($message) {
  *   Id of the message.
  * @param $thread_id
  *   Id of the thread the message belongs to.
- * @param $recipient
+ * @param $recipient_id
  *   Recipient id, a user id if type is user or hidden.
  * @param $type
  *   Type of the recipient.
  * @param $added
  *   TRUE if the recipient is added, FALSE if he is removed.
  */
-function hook_privatemsg_message_recipient_changed($mid, $thread_id, $recipient, $type, $added) {
+function hook_privatemsg_message_recipient_changed($mid, $thread_id, $recipient_id, $type, $added) {
   if ($added && ($type == 'user' || $type == 'hidden')) {
     privatemsg_filter_add_tags(array($thread_id), variable_get('privatemsg_filter_inbox_tag', ''), (object)array('uid' => $recipient));
   }
@@ -654,4 +654,4 @@ function hook_privatemsg_recipient_type_info_alter(&$types) {
 
 /**
  * @}
- */
\ No newline at end of file
+ */
diff --git privatemsg.module privatemsg.module
index 955d805..c28c11d 100644
--- privatemsg.module
+++ privatemsg.module
@@ -1852,11 +1852,13 @@ function privatemsg_get_link($recipients, $account = array(), $subject = NULL) {
  * @param $account
  *   For which account the message should be loaded.
  *   Defaults to the current user.
+ * @param $reset
+ *   Reset the static cache.
  *
  * @ingroup api
  */
-function privatemsg_message_load($pmid, $account = NULL) {
-  $messages = privatemsg_message_load_multiple(array($pmid), $account);
+function privatemsg_message_load($pmid, $account = NULL, $reset = FALSE) {
+  $messages = privatemsg_message_load_multiple(array($pmid), $account, $reset);
   return current($messages);
 }
 
@@ -1868,30 +1870,60 @@ function privatemsg_message_load($pmid, $account = NULL) {
  * @param $account
  *   For which account the message should be loaded.
  *   Defaults to the current user.
+ * @param $reset
+ *   Reset the static cache.
  *
  * @ingroup api
  */
-function privatemsg_message_load_multiple($pmids, $account = NULL) {
+function privatemsg_message_load_multiple($pmids, $account = NULL, $reset = FALSE) {
+  static $cache = array();
+  if ($reset) {
+    $cache = array();
+  }
+
   // Avoid SQL error that would happen with an empty pm.mid IN () clause.
   if (empty($pmids)) {
     return array();
   }
 
-  $query = _privatemsg_assemble_query('load', $pmids, $account);
-  $result = db_query($query['query']);
+  // If account is null, we need the current user's uid for caching.
+  if (isset($account->uid)) {
+    $uid = $account->uid;
+  }
+  else {
+    $uid = $GLOBALS['user']->uid;
+  }
+
+  // Collect cached messages and remove any pmids that were found.
   $messages = array();
-  while ($message = db_fetch_array($result)) {
-    // Load author of message.
-    if (!($message['author'] = privatemsg_user_load($message['author']))) {
-      // If user does not exist, load anonymous user.
-      $message['author'] = privatemsg_user_load(0);
+  foreach ($pmids as $key => $pmid) {
+    if (isset($cache[$uid][$pmid])) {
+      $messages[$pmid] = $cache[$uid][$pmid];
+      unset($pmids[$key]);
     }
-    $returned = module_invoke_all('privatemsg_message_load', $message);
-    if (!empty($returned)) {
-      $message = array_merge_recursive($returned, $message);
+  }
+
+  // Load any remaining uncached messages.
+  if (!empty($pmids)) {
+    $query = _privatemsg_assemble_query('load', $pmids, $account);
+    $result = db_query($query['query']);
+    while ($message = db_fetch_array($result)) {
+      // Load author of message.
+      if (!($message['author'] = privatemsg_user_load($message['author']))) {
+        // If user does not exist, load anonymous user.
+        $message['author'] = privatemsg_user_load(0);
+      }
+      $returned = module_invoke_all('privatemsg_message_load', $message);
+      if (!empty($returned)) {
+        $message = array_merge_recursive($returned, $message);
+      }
+
+      // Add to cache and to current result set.
+      $cache[$uid][$message['mid']] = $message;
+      $messages[$message['mid']] = $message;
     }
-    $messages[$message['mid']] = $message;
   }
+
   return $messages;
 }
 
