diff --git a/inc/actions.php b/inc/actions.php
index a856b79197e755aa954bb8d339ec4ff42b1d693e..222ac89dd54ec5c1ed55fccf3aec678f9b251b84 100644
--- a/inc/actions.php
+++ b/inc/actions.php
@@ -558,29 +558,69 @@ function act_export($act){
  * @author Adrian Lang <lang@cosmocode.de>
  */
 function act_subscription($act){
-    global $lang;
-    global $INFO;
-
     if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
         // No post to handle, let tpl_subscribe manage the request.
         return $act;
     }
 
+    // Get and preprocess data.
+    $params = array();
+    foreach(array('target', 'style', 'action') as $param) {
+        if (isset($_POST["subscribe_$param"])) {
+            $params[$param] = $_POST["subscribe_$param"];
+        }
+    }
+
+    // Handle POST data, may throw exception.
+    trigger_event('ACTION_HANDLE_SUBSCRIBE', $params, 'subscription_handle_post');
+
+    $target = $params['target'];
+    $style  = $params['style'];
+    $data   = $params['data'];
+    $action = $params['action'];
+
+    global $lang;
+    global $INFO;
+
+    // Perform action.
+    require_once DOKU_INC . 'inc/subscription.php';
+    if (!subscription_set($_SERVER['REMOTE_USER'], $target, $style, $data)) {
+        throw new Exception(sprintf($lang["subscr_{$action}_error"],
+                                    hsc($INFO['userinfo']['name']),
+                                    prettyprint_id($target)));
+    }
+    $INFO['subscribed'] = get_info_subscribed();
+    msg(sprintf($lang["subscr_{$action}_success"], hsc($INFO['userinfo']['name']),
+                prettyprint_id($target)), 1);
+    return $act;
+}
+
+/**
+ * Validate POST data
+ *
+ * Validates POST data for a subscribe or unsubscribe request. This is the
+ * default action for the event ACTION_HANDLE_SUBSCRIBE.
+ *
+ * @author Adrian Lang <lang@cosmocode.de>
+ */
+function subscription_handle_post($params) {
+    global $INFO;
+    global $lang;
+
     // Get and validate parameters.
-    if (!isset($_POST['subscribe_target'])) {
+    if (!isset($params['target'])) {
         throw new Exception($lang['subscr_no_target']);
     }
-    $target = $_POST['subscribe_target'];
+    $target = $params['target'];
     $valid_styles = array('every', 'digest');
     if (substr($target, -1, 1) === ':') {
         // Allow “list” subscribe style since the target is a namespace.
         $valid_styles[] = 'list';
     }
-    $style  = valid_input_set('subscribe_style', $valid_styles, $_POST,
+    $style  = valid_input_set('style', $valid_styles, $params,
                               $lang['subscr_invalid_style']);
-    $action = valid_input_set('subscribe_action', array('subscribe',
-                                                        'unsubscribe'),
-                              $_POST, $lang['subscr_invalid_action']);
+    $action = valid_input_set('action', array('subscribe', 'unsubscribe'),
+                              $params, $lang['subscr_invalid_action']);
 
     // Check other conditions.
     if ($action === 'subscribe') {
@@ -602,17 +642,8 @@ function act_subscription($act){
         $style = null;
     }
 
-    // Perform action.
-    require_once DOKU_INC . 'inc/subscription.php';
-    if (!subscription_set($target, $_SERVER['REMOTE_USER'], $style)) {
-        throw new Exception(sprintf($lang["subscr_{$action}_error"],
-                                    hsc($INFO['userinfo']['name']),
-                                    prettyprint_id($target)));
-    }
-    $INFO['subscribed'] = get_info_subscribed();
-    msg(sprintf($lang["subscr_{$action}_success"], hsc($INFO['userinfo']['name']),
-                prettyprint_id($target)), 1);
-    return $act;
+    $data = in_array($style, array('list', 'digest')) ? time() : null;
+    $params = compact('target', 'style', 'data', 'action');
 }
 
 //Setup VIM: ex: et ts=2 enc=utf-8 :
diff --git a/inc/common.php b/inc/common.php
index 2cc279844b37629ab341fa2b035fab199fefaffb..9cadb56fdb7ed5f7a348e71c619b291bc56e68fb 100644
--- a/inc/common.php
+++ b/inc/common.php
@@ -1061,7 +1061,10 @@ function notify($id,$who,$rev='',$summary='',$minor=false,$replace=array()){
     }elseif($who == 'subscribers'){
         if(!$conf['subscribers']) return; //subscribers enabled?
         if($conf['useacl'] && $_SERVER['REMOTE_USER'] && $minor) return; //skip minors
-        $bcc  = subscription_addresslist($id,false);
+        $data = array('id' => $id, 'addresslist' => '', 'self' => false);
+        trigger_event('COMMON_NOTIFY_ADDRESSLIST', $data,
+                      'subscription_addresslist');
+        $bcc = $data['addresslist'];
         if(empty($bcc)) return;
         $to   = '';
         $text = rawLocale('subscr_single');
diff --git a/inc/subscription.php b/inc/subscription.php
index 1dcecf6f56a8f71e5e4e80477eac8d37ce53effb..12f0a4b8277c579beb4ab19a821847c679f89d82 100644
--- a/inc/subscription.php
+++ b/inc/subscription.php
@@ -50,18 +50,18 @@ function subscription_filename($id) {
  * returned if a subscription should be deleted but the user is not subscribed
  * and the subscription meta file exists.
  *
+ * @param string $user      The subscriber or unsubscriber
  * @param string $page      The target object (page or namespace), specified by
  *                          id; Namespaces are identified by a trailing colon.
- * @param string $user      The user
  * @param string $style     The subscribe style; DokuWiki currently implements
  *                          “every”, “digest”, and “list”.
+ * @param string $data      An optional data blob
  * @param bool   $overwrite Whether an existing subscription may be overwritten
- * @param string $data      An optional data blob; For list and digest, this
- *                          defaults to time().
  *
  * @author Adrian Lang <lang@cosmocode.de>
  */
-function subscription_set($page, $user, $style, $overwrite = false, $data = null) {
+function subscription_set($user, $page, $style, $data = null,
+                          $overwrite = false) {
     global $lang;
     if (is_null($style)) {
         // Delete subscription.
@@ -88,15 +88,15 @@ function subscription_set($page, $user, $style, $overwrite = false, $data = null
             return false;
         }
         // Fail if deletion failed, else continue.
-        if (!subscription_set($page, $user, null)) {
+        if (!subscription_set($user, $page, null)) {
             return false;
         }
     }
 
     $file = subscription_filename($page);
     $content = auth_nameencode($user) . ' ' . $style;
-    if (in_array($style, array('list', 'digest'))) {
-        $content .= ' ' . (!is_null($data) ? $data : time());
+    if (!is_null($data)) {
+        $content .= ' ' . $data;
     }
     return io_saveFile($file, $content . "\n", true);
 }
@@ -116,7 +116,7 @@ function subscription_set($page, $user, $style, $overwrite = false, $data = null
  */
 function subscription_find($page, $pre) {
     // Construct list of files which may contain relevant subscriptions.
-    $filenames = array();
+    $filenames = array(':' => subscription_filename(':'));
     do {
         $filenames[$page] = subscription_filename($page);
         $page = getNS(rtrim($page, ':')) . ':';
@@ -210,16 +210,23 @@ function subscription_regex($pre = array()) {
  * Return a string with the email addresses of all the
  * users subscribed to a page
  *
- * @param string $id   The id of the changed page
- * @param bool   $self Whether a notice should be sent to the editor if he is
- *                     subscribed
+ * This is the default action for COMMON_NOTIFY_ADDRESSLIST.
+ *
+ * @param array $data Containing $id (the page id), $self (whether the author
+ *                    should be notified, $addresslist (current email address
+                      list)
  *
  * @author Steven Danz <steven-danz@kc.rr.com>
+ * @author Adrian Lang <lang@cosmocode.de>
  */
-function subscription_addresslist($id, $self=true){
+function subscription_addresslist($data){
     global $conf;
     global $auth;
 
+    $id = $data['id'];
+    $self = $data['self'];
+    $addresslist = $data['addresslist'];
+
     if (!$conf['subscribers']) {
         return '';
     }
@@ -242,7 +249,7 @@ function subscription_addresslist($id, $self=true){
             }
         }
     }
-    return implode(',', $emails);
+    $data['addresslist'] = trim($addresslist . ',' . implode(',', $emails), ',');
 }
 
 /**
diff --git a/lib/exe/indexer.php b/lib/exe/indexer.php
index eb1556e1d3266c635ba14ea6f610a260883ddaab..70aa607a91a7f41b33172e643ea94c73b93a0334 100644
--- a/lib/exe/indexer.php
+++ b/lib/exe/indexer.php
@@ -399,7 +399,7 @@ function sendDigest() {
                                          $lastupdate);
             }
             // Update notification time.
-            subscription_set($id, $user, $style, true);
+            subscription_set($user, $id, $style, time(), true);
         }
     }
 }