diff --git a/includes/simplenews.admin.inc b/includes/simplenews.admin.inc
index dcf38f8..e30ce89 100644
--- a/includes/simplenews.admin.inc
+++ b/includes/simplenews.admin.inc
@@ -5,8 +5,6 @@
  * Newsletter admin, subscription admin, simplenews settings
  *
  * @ingroup simplenews
- * @todo Redo all database functions: http://drupal.org/node/224333#dbtng
- * @todo Where possible build re-usable functions wrapped around database calls.
  */
 
 /**
@@ -15,13 +13,6 @@
  * @see simplenews_admin_newsletter_submit()
  */
 function simplenews_admin_newsletter_issues($form, &$form_state, $action = 'sent') {
-/*
-  // @todo Fix the delete operation
-  if (isset($form_state['input']['operation']) && $form_state['input']['operation'] == 'delete') {
-    return simplenews_issue_multiple_delete_confirm($form, $form_state);
-  }
-*/
-
   $form['filter'] = simplenews_issue_filter_form();
   $form['#submit'][] = 'simplenews_issue_filter_form_submit';
   $form['filter']['#theme'] = 'simplenews_filter_form';
@@ -98,7 +89,7 @@ function _simplenews_issue_filter_default() {
 }
 
 /**
- * @todo
+ * Form submit callback for the newsletter issue filter.
  */
 function simplenews_issue_filter_form_submit($form, &$form_state) {
   switch ($form_state['values']['op']) {
@@ -223,7 +214,7 @@ function simplenews_simplenews_issue_operations() {
 }
 
 /**
- * @todo
+ * Form vaidate callback for the issue list operations.
  */
 function simplenews_admin_issues_validate($form, &$form_state) {
   if (isset($form_state['input']['operation'])) {
@@ -231,18 +222,11 @@ function simplenews_admin_issues_validate($form, &$form_state) {
     if (empty($nids)) {
       form_set_error('', t('No items selected.'));
     }
-    else {
-      switch ($form_state['input']['operation']) {
-        case 'send':
-        //@todo If 'send': check if selected items are un-sent.
-
-      }
-    }
   }
 }
 
 /**
- * @todo
+ * Form submit callback for the issue operations.
  */
 function simplenews_admin_issues_submit($form, &$form_state) {
   // Call operation functions as defined in hook_simplenews_issue_operations().
@@ -350,7 +334,7 @@ function simplenews_admin_categories() {
 }
 
 /**
- * @todo
+ * Form submit callback for the simplenews categories.
  */
 function simplenews_admin_categories_submit($form, &$form_state) {
   foreach ($form_state['values'] as $tid => $category) {
@@ -363,7 +347,7 @@ function simplenews_admin_categories_submit($form, &$form_state) {
 }
 
 /**
- * @todo
+ * Form builder function, display a list of simplenews categories.
  */
 function theme_simplenews_admin_categories($variables) {
   $form = $variables['form'];
@@ -613,7 +597,7 @@ function simplenews_admin_category_form($form, &$form_state, $edit = array()) {
 }
 
 /**
- * @todo
+ * Form validation callback for a newsletter category form.
  */
 function simplenews_admin_category_form_validate($form, &$form_state) {
   if ($form_state['clicked_button']['#value'] != t('Delete')) {
@@ -626,7 +610,7 @@ function simplenews_admin_category_form_validate($form, &$form_state) {
 }
 
 /**
- * @todo
+ * Form submit callback for a newsletter category form.
  */
 function simplenews_admin_category_form_submit($form, &$form_state) {
   //dpm($form_state);
@@ -690,7 +674,7 @@ function simplenews_admin_category_delete($form, &$form_state, $category) {
 }
 
 /**
- * @todo
+ * Form submit callback for deleting a simplenews category.
  */
 function simplenews_admin_category_delete_submit($form, &$form_state) {
   $tid = $form_state['values']['tid'];
@@ -781,17 +765,17 @@ function simplenews_subscription_list_add($form, &$form_state) {
     '#description' => t('Email addresses must be separated by comma, space or newline.'),
   );
 
-  $form['lists'] = array(
+  $form['newsletters'] = array(
     '#type' => 'fieldset',
     '#description' => t('Subscribe to'),
+    '#tree' => TRUE,
    );
 
   foreach (simplenews_get_mailing_lists(TRUE) as $list) {
-    $form['lists'][$list->tid] = array(
+    $form['newsletters'][$list->tid] = array(
       '#type' => 'checkbox',
       '#title' => check_plain(_simplenews_newsletter_name($list)),
       '#description'  => _simplenews_newsletter_description($list),
-      '#default_value' => FALSE,
     );
   }
 
@@ -834,8 +818,7 @@ function simplenews_subscription_list_add($form, &$form_state) {
 function simplenews_subscription_list_add_submit($form, &$form_state) {
   $added = array();
   $invalid = array();
-  // @todo redo filter
-  $checked_lists = array_keys(array_filter($form_state['values'],'_simplenews_checked'));
+  $checked_categories = array_keys(array_filter($form_state['values']['newsletters']));
   $langcode = $form_state['values']['language'];
 
   $emails = preg_split("/[\s,]+/", $form_state['values']['emails']);
@@ -845,8 +828,8 @@ function simplenews_subscription_list_add_submit($form, &$form_state) {
       continue;
     }
     if (valid_email_address($email)) {
-      foreach ($checked_lists as $tid) {
-        $category = simplenews_category_load($tid);
+      foreach (simplenews_categories_load_multiple($checked_categories) as $category) {
+
         simplenews_subscribe_user($email, $category->tid, FALSE, 'mass subscribe', $langcode);
         $added[] = $email;
       }
@@ -860,8 +843,7 @@ function simplenews_subscription_list_add_submit($form, &$form_state) {
     drupal_set_message(t('The following addresses were added or updated: %added.', array('%added' => $added)));
 
     $list_names = array();
-    foreach ($checked_lists as $tid) {
-      $category = simplenews_category_load($tid);
+    foreach (simplenews_categories_load_multiple($checked_categories) as $category) {
       $list_names[] = $category->name;
     }
     drupal_set_message(t('The addresses were subscribed to the following newsletters: %newsletters.', array('%newsletters' => implode(', ', $list_names))));
@@ -882,14 +864,12 @@ function simplenews_subscription_list_add_submit($form, &$form_state) {
  * Menu callback: Export email address of subscriptions.
  *
  * @see simplenews_admin_export_after_build()
- *
- * @todo Add checkboxes for subscribed and unsubscribed selection.
  */
 function simplenews_subscription_list_export($form, &$form_state) {
   // Get sensible default values for the form elements in this form.
   $default['states'] = isset($_GET['states']) ? $_GET['states'] : array('active' => 'active');
   $default['subscribed'] = isset($_GET['subscribed']) ? $_GET['subscribed'] : array('subscribed' => 'subscribed');
-  $default['lists'] = isset($_GET['lists']) ? $_GET['lists'] : array();
+  $default['newsletters'] = isset($_GET['newsletters']) ? $_GET['newsletters'] : array();
 
   $form['states'] = array(
     '#type' => 'checkboxes',
@@ -915,15 +895,12 @@ function simplenews_subscription_list_export($form, &$form_state) {
     '#required' => TRUE,
   );
 
-  $lists = array();
-  foreach (simplenews_get_mailing_lists(TRUE) as $list) {
-    $lists[$list->tid] = check_plain(_simplenews_newsletter_name($list));
-  }
-  $form['lists'] = array(
+  $options = simplenews_category_list();
+  $form['newsletters'] = array(
     '#type' => 'checkboxes',
     '#title' => t('Newsletter'),
-    '#options' => $lists,
-    '#default_value' => $default['lists'],
+    '#options' => $options,
+    '#default_value' => $default['newsletters'],
     '#description' => t('Subscriptions matching the selected newsletters will be exported.'),
     '#required' => TRUE,
   );
@@ -936,7 +913,7 @@ function simplenews_subscription_list_export($form, &$form_state) {
       '#title' => t('Export results'),
       '#cols' => 60,
       '#rows' => 5,
-      '#value' => _simplenews_subscription_list_export_get_emails($_GET['states'], $_GET['subscribed'], $_GET['lists']),
+      '#value' => _simplenews_subscription_list_export_get_emails($_GET['states'], $_GET['subscribed'], $_GET['newsletters']),
     );
   }
 
@@ -956,7 +933,7 @@ function simplenews_subscription_list_export_submit($form, &$form_state) {
   // Get data for query string and redirect back to the current page.
   $options['query']['states'] = array_filter($form_values['states']);
   $options['query']['subscribed'] = array_filter($form_values['subscribed']);
-  $options['query']['lists'] = array_keys(array_filter($form_values['lists']));
+  $options['query']['newsletters'] = array_keys(array_filter($form_values['newsletters']));
   $form_state['redirect'] = array('admin/people/simplenews/export', $options);
 }
 
@@ -967,12 +944,12 @@ function simplenews_subscription_list_export_submit($form, &$form_state) {
  *   Array of subscriber states to filter on.
  * @param $subscribed
  *   Array of subscription states to filter on.
- * @param $lists
+ * @param $newsletters
  *   Array of taxonomy ids to fitler on.
  * @return string
  *   Comma separated list of email adresses.
  */
-function _simplenews_subscription_list_export_get_emails($states, $subscribed, $lists) {
+function _simplenews_subscription_list_export_get_emails($states, $subscribed, $newsletters) {
 
   // Build conditions for active state, subscribed state and newsletter selection.
   if (isset($states['active'])) {
@@ -987,7 +964,6 @@ function _simplenews_subscription_list_export_get_emails($states, $subscribed, $
   if (isset($subscribed['unsubscribed'])) {
     $condition_subscribed[] = 0;
   }
-  $tids = $lists;
 
   // Get emails from the database.
   $query = db_select('simplenews_subscriber', 'ss');
@@ -995,7 +971,7 @@ function _simplenews_subscription_list_export_get_emails($states, $subscribed, $
   $query->fields('ss', array('mail'))
     ->condition('ss.activated', $condition_active)
     ->condition('si.status', $condition_subscribed)
-    ->condition('si.tid', $tids)
+    ->condition('si.tid', $newsletters)
     ->distinct();
   $mails = $query->execute()->fetchCol(0);
 
@@ -1022,17 +998,17 @@ function simplenews_subscription_list_remove($form, &$form_state) {
     '#description' => t('Email addresses must be separated by comma, space or newline.'),
   );
 
-  $form['lists'] = array(
+  $form['newsletters'] = array(
     '#type' => 'fieldset',
     '#description' => t('Unsubscribe from'),
+    '#tree' => TRUE,
   );
 
   foreach (simplenews_get_mailing_lists(TRUE) as $list) {
-    $form['lists'][$list->tid] = array(
+    $form['newsletters'][$list->tid] = array(
       '#type' => 'checkbox',
       '#title' => check_plain(_simplenews_newsletter_name($list)),
       '#description'  => _simplenews_newsletter_description($list),
-      '#default_value' => FALSE,
     );
   }
 
@@ -1049,8 +1025,7 @@ function simplenews_subscription_list_remove($form, &$form_state) {
 function simplenews_subscription_list_remove_submit($form, &$form_state) {
   $removed = array();
   $invalid = array();
-  // @todo redo filter
-  $checked_lists = array_keys(array_filter($form_state['values'],'_simplenews_checked'));
+  $checked_lists = array_keys(array_filter($form_state['values']['newsletters']));
 
   $emails = preg_split("/[\s,]+/", $form_state['values']['emails']);
   foreach ($emails as $email) {
@@ -1830,3 +1805,188 @@ function simplenews_get_priority() {
     SIMPLENEWS_PRIORITY_LOWEST => t('lowest'),
   );
 }
+
+
+/**
+ * Menu callback; Newsletter tab page.
+ */
+function simplenews_node_tab_page($node){
+  drupal_set_title(t('<em>Newsletter</em> @title', array('@title' => $node->title)), PASS_THROUGH);
+  return drupal_get_form('simplenews_node_tab_send_form', $node);
+}
+
+/**
+ * @todo
+ */
+function simplenews_node_tab_send_form($form, &$form_state, $node){
+  // First check if there already is a loaded simplenews object.
+  if (!empty($node->simplenews)) {
+    $simplenews_values = $node->simplenews;
+  }
+  // If not, try to load it based on the node id.
+  else if ($loaded = simplenews_newsletter_load($node->nid)) {
+    $simplenews_values = $loaded;
+  }
+  // If that fails too, fall back to the defaults.
+  else {
+    $simplenews_values = (object)_simplenews_get_node_form_defaults($node);
+  }
+
+  $form = array();
+  // We will need the node
+  $form['nid'] = array(
+    '#type' => 'value',
+    '#value' => $node->nid,
+  );
+
+  // @todo delete this fieldset?
+  $form['simplenews'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Send newsletter'),
+    '#collapsible' => FALSE,
+    '#collapsed' => FALSE,
+    '#tree' => TRUE,
+  );
+
+  // Translations of newsletters don't have the 'send' option. Only the
+  // translation source (and non translated) newsletters will get these options.
+  if (module_exists('translation') && translation_supported_type($node->type)
+    && (isset($node->translate) && ($node->tnid > 0) && ($node->tnid != $node->nid))) {
+    $form['simplenews']['#description'] = t('This newsletter issue is part of a translation set. Sending this set is controlled from the <a href="@link">translation source newsletter</a>.', array('@link' => url('node/' . $node->tnid)));
+    // @todo Translated nodes must also have the same Category!
+    //      Move the category in here and give the user feedback.
+  }
+  else {
+    // Show newsletter sending options if newsletter has not been send yet.
+    // If send a notification is shown.
+    if ($simplenews_values->status == SIMPLENEWS_STATUS_SEND_NOT || $simplenews_values->status == SIMPLENEWS_STATUS_SEND_PUBLISH) {
+
+      $options = array(
+        SIMPLENEWS_COMMAND_SEND_TEST => t('Send one test newsletter to the test address'),
+      );
+
+      // Add option to send on publish when the node is unpublished.
+      if ($node->status == NODE_NOT_PUBLISHED) {
+        $options[SIMPLENEWS_COMMAND_SEND_PUBLISH] = t('Send newsletter when published');
+      }
+      else {
+        $options[SIMPLENEWS_COMMAND_SEND_NOW] = t('Send newsletter');
+      }
+
+      if ($simplenews_values->status == SIMPLENEWS_STATUS_SEND_PUBLISH) {
+        $send_default = SIMPLENEWS_STATUS_SEND_PUBLISH;
+      }
+      else {
+        $send_default = variable_get('simplenews_send', SIMPLENEWS_COMMAND_SEND_TEST);
+      }
+      $form['simplenews']['send'] = array(
+        '#type' => 'radios',
+        '#title' => t('Send newsletter'),
+        '#default_value' => isset($simplenews_values->send) ? $simplenews_values->send : $send_default,
+        '#options' => $options,
+        '#attributes' => array(
+          'class' => array('simplenews-command-send'),
+        ),
+      );
+
+      $address_default = variable_get('site_mail', ini_get('sendmail_from'));
+      if (variable_get('simplenews_test_address_override', 0)) {
+        $form['simplenews']['test_address'] = array(
+          '#type' => 'textfield',
+          '#title' => t('Test email addresses'),
+          '#description' => t('A comma-separated list of email addresses to be used as test addresses.'),
+          '#default_value' => variable_get('simplenews_test_address', $address_default),
+          '#size' => 60,
+          '#maxlength' => 128,
+        );
+      }
+      else {
+        $form['simplenews']['test_address'] = array(
+          '#type' => 'value',
+          '#value' => variable_get('simplenews_test_address', $address_default),
+        );
+      }
+    }
+    else {
+      $form['simplenews']['none'] = array(
+        '#type' => 'checkbox',
+        '#return_value' => 0,
+        '#attributes' => array(
+          'checked' => 'checked',
+          'disabled' => 'disabled',
+        ),
+      );
+      $form['simplenews']['none']['#title'] = ($simplenews_values->status == SIMPLENEWS_STATUS_SEND_READY) ? t('This newsletter has been sent') : t('This newsletter is pending');
+      return $form;
+    }
+    $form['submit'] = array(
+      '#type' => 'submit',
+      '#value' => t('Submit'),
+    );
+  }
+  return $form;
+}
+
+/**
+ * @todo
+ */
+function simplenews_node_tab_send_form_validate($form, &$form_state) {
+  $values = $form_state['values'];
+  $node = node_load($values['nid']);
+
+  $default_address = variable_get('simplenews_test_address', variable_get('site_mail', ini_get('sendmail_from')));
+  $mails = array($default_address);
+  if (isset($values['simplenews']['send']) && $values['simplenews']['send'] == SIMPLENEWS_COMMAND_SEND_TEST && variable_get('simplenews_test_address_override', 0)) {
+   // @todo Can we simplify and use only two kind of messages?
+    if (!empty($values['simplenews']['test_address'])) {
+      $mails = explode(',', $values['simplenews']['test_address']);
+      foreach ($mails as $mail) {
+        $mail = trim($mail);
+        if ($mail == '') {
+          form_set_error('simplenews][test_address', t('Test email address is empty.'));
+        }
+        elseif (!valid_email_address($mail)) {
+          form_set_error('simplenews][test_address', t('Invalid email address "%mail".', array('%mail' => $mail)));
+        }
+      }
+    }
+    else {
+      form_set_error('simplenews][test_address', t('Missing test email address.'));
+    }
+  }
+  $form_state['test_addresses'] = $mails;
+}
+
+/**
+ * @todo
+ */
+function simplenews_node_tab_send_form_submit($form, &$form_state) {
+  $values = $form_state['values'];
+  $node = node_load($values['nid']);
+
+  // Send newsletter to all subscribers or send test newsletter
+  module_load_include('inc', 'simplenews', 'includes/simplenews.mail');
+  if ($values['simplenews']['send'] == SIMPLENEWS_COMMAND_SEND_NOW) {
+    $status = simplenews_add_node_to_spool($node);
+    if ($status == SIMPLENEWS_STATUS_SEND_READY) {
+      drupal_set_message(t('Newsletter %title sent.', array('%title' => $node->title)));
+    }
+    else {
+      drupal_set_message(t('Newsletter %title pending.', array('%title' => $node->title)));
+    }
+  }
+  elseif ($values['simplenews']['send'] == SIMPLENEWS_COMMAND_SEND_TEST) {
+    simplenews_send_test($node, $form_state['test_addresses']);
+  }
+
+  // If the selected command is send on publish, just set the newsletter status.
+  if ($values['simplenews']['send'] == SIMPLENEWS_COMMAND_SEND_PUBLISH) {
+    $newsletter = simplenews_newsletter_load($node->nid);
+    if (!$newsletter) {
+      $newsletter = simplenews_newsletter_defaults($node);
+    }
+    $newsletter->status = SIMPLENEWS_STATUS_SEND_PUBLISH;
+    simplenews_newsletter_save($newsletter);
+    drupal_set_message(t('The newsletter will be sent when the content is published.'));
+  }
+}
diff --git a/includes/simplenews.api.php b/includes/simplenews.api.php
deleted file mode 100644
index 7178080..0000000
--- a/includes/simplenews.api.php
+++ /dev/null
@@ -1,116 +0,0 @@
-<?php
-
-/**
- * @file
- * Hooks provided by the Simplenews module.
- */
-
-/**
- * @todo
- */
-function hook_simplenews_issue_operations() {
-
-}
-
-/**
- * @todo
- */
-function hook_simplenews_subscription_operations() {
-
-}
-
-/**
- * @todo
- */
-function hook_simplenews_category_insert($category) {
-
-}
-
-/**
- * @todo
- */
-function hook_simplenews_category_update($category) {
-
-}
-
-/**
- * @todo
- */
-function hook_simplenews_category_delete($category) {
-
-}
-
-/**
- * @todo
- */
-function hook_simplenews_mailing_list_insert($list) {
-
-}
-
-/**
- * @todo
- */
-function hook_simplenews_subscriber_update($subscriber) {
-
-}
-
-/**
- * @todo
- */
-function hook_simplenews_subscriber_insert($subscriber) {
-
-}
-
-/**
- * @todo
- */
-function hook_simplenews_subscriber_delete($subscriber) {
-
-}
-
-/**
- * Invoked if a user is subscribed to a newsletter.
- *
- * @param $subscriber
- *   The subscriber object including all subscriptions of this user.
- *
- * @param $subscription
- *   The subscription object for this specific subscribe action.
- */
-function hook_simplenews_subscribe_user($subscriber, $subscription) {
-
-}
-
-/**
- * Invoked if a user is unsubscribed from a newsletter.
- *
- * @param $subscriber
- *   The subscriber object including all subscriptions of this user.
- *
- * @param $subscription
- *   The subscription object for this specific unsubscribe action.
- */
-function hook_simplenews_unsubscribe_user($subscriber, $subscription) {
-
-}
-
-/**
- * Expose SimplenewsSource cache implementations.
- *
- * @return
- *   An array keyed by the name of the class that provides the implementation,
- *   the array value consists of another array with the keys label and
- *   description.
- */
-function hook_simplenews_source_cache_info() {
-  return array(
-    'SimplenewsSourceCacheNone' => array(
-      'label' => t('No caching'),
-      'description' => t('This allows to theme each newsletter separately.'),
-    ),
-    'SimplenewsSourceCacheBuild' => array(
-      'label' => t('Cached content source'),
-      'description' => t('This caches the rendered content to be sent for multiple recipients. It is not possible to use subscriber specific theming but tokens can be used for personalization.'),
-    ),
-  );
-}
\ No newline at end of file
diff --git a/includes/simplenews.mail.inc b/includes/simplenews.mail.inc
index 362c41d..5dd0948 100644
--- a/includes/simplenews.mail.inc
+++ b/includes/simplenews.mail.inc
@@ -78,7 +78,7 @@ function simplenews_send_test($node, $test_addresses) {
   foreach ($test_addresses as $mail) {
     $mail = trim($mail);
     if (!empty($mail)) {
-      $account = _simplenews_user_load($mail);
+      $account = simplenews_load_user_by_mail($mail);
       $subscriber = simplenews_get_subscription($account);
       if ($account->uid) {
         $recipients['user'][] = $account->name . ' <' . $mail . '>';
@@ -339,8 +339,7 @@ function simplenews_get_spool($status, $limit = SIMPLENEWS_UNLIMITED) {
         $message->data = unserialize($message->data);
       }
       else {
-        $mail = (object)array('mail' => $message->mail);
-        $message->data = simplenews_get_subscription($mail);
+        $message->data = simplenews_get_subscription(simplenews_load_user_by_mail($message->mail));
       }
       $messages[$message->msid] = $message;
     }
@@ -421,9 +420,9 @@ function simplenews_count_spool($nid, $status = array(SIMPLENEWS_SPOOL_PENDING,
  *
  * All records with status 'send' and time stamp before the expiration date
  * are removed from the spool.
- * @todo Replace time(): http://drupal.org/node/224333#time
  *
- * @return Count deleted
+ * @return
+ *   Number of deleted spool rows.
  */
 function simplenews_clear_spool() {
   $expiration_time = REQUEST_TIME - variable_get('simplenews_spool_expire', 0) * 86400;
@@ -758,4 +757,4 @@ class SimplenewsHTMLTestingMailSystem implements MailSystemInterface {
     variable_set('drupal_test_email_collector', $captured_emails);
     return TRUE;
   }
-}
\ No newline at end of file
+}
diff --git a/includes/simplenews.source.inc b/includes/simplenews.source.inc
index 443f55f..f9b01cc 100644
--- a/includes/simplenews.source.inc
+++ b/includes/simplenews.source.inc
@@ -280,7 +280,7 @@ class SimplenewsSpool implements SimplenewsSpoolInterface {
       $subscriber = $spool_data->data;
     }
     else {
-      $subscriber = simplenews_get_subscription(_simplenews_user_load($spool_data->mail));
+      $subscriber = simplenews_get_subscription(simplenews_load_user_by_mail($spool_data->mail));
     }
 
     $source_class = $this->getSourceImplementation($spool_data);
diff --git a/includes/simplenews.subscription.inc b/includes/simplenews.subscription.inc
index e06e0ff..39618cc 100644
--- a/includes/simplenews.subscription.inc
+++ b/includes/simplenews.subscription.inc
@@ -170,7 +170,7 @@ function simplenews_block_form_validate($form, &$form_state) {
  */
 function simplenews_block_form_submit($form, &$form_state) {
   $tid = $form['#tid'];
-  $account = _simplenews_user_load($form_state['values']['mail']);
+  $account = simplenews_load_user_by_mail($form_state['values']['mail']);
 
   $confirm = simplenews_require_double_opt_in($tid, $account);
 
@@ -291,15 +291,7 @@ function simplenews_subscriptions_page_form_validate($form, &$form_state) {
  * FAPI PAGE subscription form_submit.
  */
 function simplenews_subscriptions_page_form_submit($form, &$form_state) {
-  // Try to load user.
-  $account = user_load_by_mail($form_state['values']['mail']);
-  // If this fails, this is an anon user, fall back to the faked account object.
-  // @todo: Maybe update simplenews_get_subscription to only require the mail
-  // as the argument?
-  if (!$account) {
-    $account = (object)array('mail' => $form_state['values']['mail']);
-  }
-  $subscription = simplenews_get_subscription($account);
+  $account = simplenews_get_subscription(simplenews_load_user_by_mail($form_state['values']['mail']));
 
   switch ($form_state['values']['op']) {
     case t('Update'):
@@ -308,10 +300,10 @@ function simplenews_subscriptions_page_form_submit($form, &$form_state) {
       arsort($form_state['values']['newsletters'], SORT_NUMERIC);
       foreach ($form_state['values']['newsletters'] as $tid => $checked) {
         if ($checked) {
-          simplenews_subscribe_user($form_state['values']['mail'], $tid, FALSE, 'website');
+          simplenews_subscribe_user($account->mail, $tid, FALSE, 'website');
         }
         else {
-          simplenews_unsubscribe_user($form_state['values']['mail'], $tid, FALSE, 'website');
+          simplenews_unsubscribe_user($account->mail, $tid, FALSE, 'website');
         }
       }
       drupal_set_message(t('The newsletter subscriptions for %mail have been updated.', array('%mail' => $form_state['values']['mail'])));
@@ -322,7 +314,7 @@ function simplenews_subscriptions_page_form_submit($form, &$form_state) {
         if ($checked) {
           $confirm = simplenews_require_double_opt_in($tid, $account);
           $confirm_any |= $confirm;
-          simplenews_subscribe_user($form_state['values']['mail'], $tid, $confirm, 'website');
+          simplenews_subscribe_user($account->mail, $tid, $confirm, 'website');
         }
       }
       if ($confirm_any) {
@@ -338,7 +330,7 @@ function simplenews_subscriptions_page_form_submit($form, &$form_state) {
         if ($checked) {
           $confirm = simplenews_require_double_opt_in($tid, $account);
           $confirm_any |= $confirm;
-          simplenews_unsubscribe_user($form_state['values']['mail'], $tid, $confirm, 'website');
+          simplenews_unsubscribe_user($account->mail, $tid, $confirm, 'website');
         }
       }
       if ($confirm_any) {
@@ -684,8 +676,7 @@ function simplenews_subscriptions_admin_form($form, &$form_state, $snid) {
  * FAPI ADMIN subscription form_validate.
  */
 function simplenews_subscriptions_admin_form_validate($form, &$form_state) {
-  $account = (object) array('mail' => $form_state['values']['mail']);
-  $subscription = simplenews_get_subscription($account);
+  $subscription = simplenews_get_subscription(simplenews_load_user_by_mail($form_state['values']['mail']));
 
   $valid_email = valid_email_address($form_state['values']['mail']);
   if (!$valid_email) {
@@ -706,8 +697,7 @@ function simplenews_subscriptions_admin_form_validate($form, &$form_state) {
  * FAPI ADMIN subscription form_submit.
  */
 function simplenews_subscriptions_admin_form_submit($form, &$form_state) {
-  $account = (object) array('mail' => $form_state['values']['mail']);
-  $subscription = simplenews_get_subscription($account);
+  $subscription = simplenews_get_subscription(simplenews_load_user_by_mail($form_state['values']['mail']));
 
   // update subscriptions
   arsort($form_state['values']['newsletters'], SORT_NUMERIC);
diff --git a/simplenews.api.php b/simplenews.api.php
new file mode 100644
index 0000000..7178080
--- /dev/null
+++ b/simplenews.api.php
@@ -0,0 +1,116 @@
+<?php
+
+/**
+ * @file
+ * Hooks provided by the Simplenews module.
+ */
+
+/**
+ * @todo
+ */
+function hook_simplenews_issue_operations() {
+
+}
+
+/**
+ * @todo
+ */
+function hook_simplenews_subscription_operations() {
+
+}
+
+/**
+ * @todo
+ */
+function hook_simplenews_category_insert($category) {
+
+}
+
+/**
+ * @todo
+ */
+function hook_simplenews_category_update($category) {
+
+}
+
+/**
+ * @todo
+ */
+function hook_simplenews_category_delete($category) {
+
+}
+
+/**
+ * @todo
+ */
+function hook_simplenews_mailing_list_insert($list) {
+
+}
+
+/**
+ * @todo
+ */
+function hook_simplenews_subscriber_update($subscriber) {
+
+}
+
+/**
+ * @todo
+ */
+function hook_simplenews_subscriber_insert($subscriber) {
+
+}
+
+/**
+ * @todo
+ */
+function hook_simplenews_subscriber_delete($subscriber) {
+
+}
+
+/**
+ * Invoked if a user is subscribed to a newsletter.
+ *
+ * @param $subscriber
+ *   The subscriber object including all subscriptions of this user.
+ *
+ * @param $subscription
+ *   The subscription object for this specific subscribe action.
+ */
+function hook_simplenews_subscribe_user($subscriber, $subscription) {
+
+}
+
+/**
+ * Invoked if a user is unsubscribed from a newsletter.
+ *
+ * @param $subscriber
+ *   The subscriber object including all subscriptions of this user.
+ *
+ * @param $subscription
+ *   The subscription object for this specific unsubscribe action.
+ */
+function hook_simplenews_unsubscribe_user($subscriber, $subscription) {
+
+}
+
+/**
+ * Expose SimplenewsSource cache implementations.
+ *
+ * @return
+ *   An array keyed by the name of the class that provides the implementation,
+ *   the array value consists of another array with the keys label and
+ *   description.
+ */
+function hook_simplenews_source_cache_info() {
+  return array(
+    'SimplenewsSourceCacheNone' => array(
+      'label' => t('No caching'),
+      'description' => t('This allows to theme each newsletter separately.'),
+    ),
+    'SimplenewsSourceCacheBuild' => array(
+      'label' => t('Cached content source'),
+      'description' => t('This caches the rendered content to be sent for multiple recipients. It is not possible to use subscriber specific theming but tokens can be used for personalization.'),
+    ),
+  );
+}
\ No newline at end of file
diff --git a/simplenews.install b/simplenews.install
index ded51fa..367db5b 100644
--- a/simplenews.install
+++ b/simplenews.install
@@ -6,7 +6,7 @@
  */
 
 /**
- * Implement hook_schema().
+ * Implements hook_schema().
  */
 function simplenews_schema() {
   $schema['simplenews_category'] = array(
@@ -331,7 +331,7 @@ function simplenews_schema() {
 }
 
 /**
- * Implement hook_install().
+ * Implements hook_install().
  */
 function simplenews_install() {
   _simplenews_init_simplenews_vocabulary();
@@ -342,7 +342,7 @@ function simplenews_install() {
 }
 
 /**
- * Implement hook_uninstall().
+ * Implements hook_uninstall().
  */
 function simplenews_uninstall() {
   db_query("DELETE FROM {variable} WHERE name LIKE 'simplenews_%%'");
@@ -502,9 +502,6 @@ function _simplenews_convert_tokens_in_variable($variables) {
  * Delete deprecated simplenews variables.
  */
 function simplenews_update_7000() {
-  // @todo Test schema update !!
-  // See: http://api.drupal.org/api/function/db_change_field/7
-  // @todo Test data update !!
 
   // Convert tokens in variables to D7 format.
   $variables = array('simplenews_confirm_subscribe_subject', 'simplenews_confirm_subscribe_unsubscribed', 'simplenews_confirm_subscribe_subscribed', 'simplenews_confirm_unsubscribe_subscribed', 'simplenews_confirm_unsubscribe_unsubscribed');
diff --git a/simplenews.module b/simplenews.module
index a0271bb..626dfa6 100644
--- a/simplenews.module
+++ b/simplenews.module
@@ -12,9 +12,7 @@
  *
  * @ingroup simplenews
  * @todo Where possible build re-usable functions wrapped around database calls.
- * @todo Change documentation of hook_foo implementations: http://drupal.org/node/224333#implementation_hook_comment
  * @todo Consider context support for t(): http://drupal.org/node/224333#locale_context
- * @todo Language code in t() now as array: http://drupal.org/node/224333#locale_context
  * @todo Coding standards: type hinting
  * @todo Implement hook_requirements()?; http://api.drupal.org/api/function/hook_requirements/7
  * @todo Separate token function into simplenews.tokens.inc
@@ -87,14 +85,12 @@ define('SIMPLENEWS_OPT_INOUT_DOUBLE', 'double');
 define('SIMPLENEWS_UNLIMITED', -1);
 
 /**
- * Implementation of hook_permission().
+ * Implements hook_permission().
  *
  * @todo Change sort order where required: http://drupal.org/node/224333#sorting_permissions
- * @todo Review the use of 'administer nodes': http://drupal.org/node/224333#bypass_node_access
  */
 function simplenews_permission() {
   return array(
-    // @todo Change to administer newsletter categories. And update existing permissions in hook_update_N.
     'administer newsletters' => array(
       'title' => t('Administer newsletters'),
     ),
@@ -114,17 +110,16 @@ function simplenews_permission() {
 }
 
 /**
- * Implementation of hook_init().
+ * Implements hook_init().
  *
- * @todo Check parameters of drupal_add_css: http://drupal.org/node/224333#drupal_add_js_options
  * @todo move this to a specific form theme function ?
  */
 function simplenews_init() {
-  drupal_add_css(drupal_get_path('module', 'simplenews') . '/simplenews.css');
+  drupal_add_css(drupal_get_path('module', 'simplenews') . '/simplenews.css', array('every_page' => TRUE));
 }
 
 /**
- * Implementation of hook_menu().
+ * Implements hook_menu().
  */
 function simplenews_menu() {
     $items['admin/content/simplenews'] = array(
@@ -302,6 +297,7 @@ function simplenews_menu() {
     'page arguments' => array(1),
     'theme callback' => '_node_custom_theme',
     'context' => MENU_LOCAL_TASK,
+    'file' => 'includes/simplenews.admin.inc',
     'weight' => 2,
   );
 
@@ -309,7 +305,7 @@ function simplenews_menu() {
 }
 
 /**
- * Implementation of hook_admin_paths().
+ * Implements hook_admin_paths().
  */
 function simplenews_admin_paths() {
   $paths = array(
@@ -319,14 +315,14 @@ function simplenews_admin_paths() {
 }
 
 /**
- * Implementation of hook_node_type_delete().
+ * Implements hook_node_type_delete().
  */
 function simplenews_node_type_delete($info) {
   drupal_static_reset('simplenews_get_content_types');
 }
 
 /**
- * Implementation of hook_node_type_update().
+ * Implements hook_node_type_update().
  */
 function simplenews_node_type_update($info) {
   drupal_static_reset('simplenews_get_content_types');
@@ -406,7 +402,7 @@ function simplenews_get_term_values($node) {
 }
 
 /**
- * Implementation of hook_node_validate().
+ * Implements hook_node_validate().
  */
 function simplenews_node_validate($node, $form) {
   if (!simplenews_check_node_types($node->type)) {
@@ -432,7 +428,25 @@ function simplenews_node_validate($node, $form) {
 }
 
 /**
- * Implementation of hook_node_insert().
+ * Implements hook_node_presave().
+ */
+function simplenews_node_presave($node) {
+  if (!simplenews_check_node_types($node->type)) {
+    return;
+  }
+
+  // Note that $node is NO full node object, see node_form_validate().
+  // Complete $node!
+  $newsletter = simplenews_newsletter_load($node->nid);
+  //$newsletter = simplenews_newsletter_load($node->nid, $node->vid);
+  if (!$newsletter) {
+    $newsletter = (object)simplenews_newsletter_defaults($node);
+  }
+  $node->simplenews = $newsletter;
+}
+
+/**
+ * Implements hook_node_insert().
  */
 function simplenews_node_insert($node) {
   if (!simplenews_check_node_types($node->type)) {
@@ -464,7 +478,7 @@ function simplenews_newsletter_defaults($node = NULL) {
 }
 
 /**
- * Implementation of hook_node_update().
+ * Implements hook_node_update().
  */
 function simplenews_node_update($node) {
   if (!simplenews_check_node_types($node->type)) {
@@ -494,7 +508,7 @@ function simplenews_node_update($node) {
 }
 
 /**
- * Implementation of hook_node_delete().
+ * Implements hook_node_delete().
  */
 function simplenews_node_delete($node) {
   if (!simplenews_check_node_types($node->type)) {
@@ -518,7 +532,7 @@ function simplenews_node_delete($node) {
 }
 
 /**
- * Implementation of hook_node_load().
+ * Implements hook_node_load().
  */
 function simplenews_node_load($nodes, $types) {
   // We only support Simplenews enabled content types.
@@ -688,7 +702,7 @@ function simplenews_get_category_field($bundle_name) {
 }
 
 /**
- * Implementation of hook_form_FORM_ID_alter().
+ * Implements hook_form_FORM_ID_alter().
  *
  * Add checkbox to the content type form to use the content type as newsletter.
  */
@@ -702,11 +716,9 @@ function simplenews_form_node_type_form_alter(&$form, $form_state) {
 }
 
 /**
- * Implementation of hook_form_FORM_ID_alter().
+ * Implements hook_form_FORM_ID_alter().
  *
  * Add a warning message to taxonomy term delete form.
- *
- * @todo move this function to a .inc file.
  */
 function simplenews_form_taxonomy_form_term_alter(&$form, $form_state) {
   if (isset($form_state['confirm_delete']) && $form_state['confirm_delete']) {
@@ -718,11 +730,9 @@ function simplenews_form_taxonomy_form_term_alter(&$form, $form_state) {
 }
 
 /**
- * Implementation of hook_taxonomy_term_delete().
+ * Implements hook_taxonomy_term_delete().
  *
  * Delete simplenews category if taxonomy term is delete.
- *
- * @todo move this function to a .inc file.
  */
 function simplenews_taxonomy_term_delete($term) {
   // A simplenews newsletter category can not exist without the associated
@@ -738,7 +748,7 @@ function simplenews_taxonomy_term_delete($term) {
 }
 
 /**
- * Implementation of hook_form_alter().
+ * Implements hook_form_alter().
  */
 function simplenews_form_alter(&$form, &$form_state, $form_id) {
   // Add Simplenews settings to simplenews newsletter node form.
@@ -779,7 +789,7 @@ function _simplenews_node_form(&$form, $form_state) {
 }
 
 /**
- * Implementation of hook_entity_info_alter().
+ * Implements hook_entity_info_alter().
  */
 function simplenews_entity_info_alter(&$info) {
   // Add the 'Plain', 'HTML' and 'Text alternative' view mode for nodes in email.
@@ -800,7 +810,7 @@ function simplenews_entity_info_alter(&$info) {
 }
 
 /**
- * Implementation of hook_field_ui_view_modes_tabs().
+ * Implements hook_field_ui_view_modes_tabs().
  */
 function simplenews_field_ui_view_modes_tabs() {
   $modes = array(
@@ -814,7 +824,7 @@ function simplenews_field_ui_view_modes_tabs() {
 
 
 /**
- * Implementation of hook_cron().
+ * Implements hook_cron().
  */
 function simplenews_cron() {
   module_load_include('inc', 'simplenews', 'includes/simplenews.mail');
@@ -825,7 +835,7 @@ function simplenews_cron() {
 }
 
 /**
- * Implementation of hook_simplenews_category_delete().
+ * Implements hook_simplenews_category_delete().
  *
  * For the time being we use mailing list and category in sync.
  * Deletes the newsletter list when category is deleted.
@@ -844,7 +854,7 @@ function simplenews_simplenews_category_delete($category) {
 }
 
 /**
- * Implementation of hook_form_FORM_ID_alter().
+ * Implements hook_form_FORM_ID_alter().
  *
  * Add simplenews subscription fields to user register form.
  * @todo mode this function to another place in the module.
@@ -878,7 +888,6 @@ function simplenews_form_user_register_form_alter(&$form, &$form_state) {
       '#description' => t('Select the newsletter(s) to which you wish to subscribe.'),
       '#weight' => 5,
     );
-    // @todo Change 'newsletters' to 'list'.
     $form['simplenews']['newsletters'] = array(
       '#type' => 'checkboxes',
       '#options' => $options,
@@ -895,7 +904,7 @@ function simplenews_form_user_register_form_alter(&$form, &$form_state) {
 
 
 /**
- * Implementation of hook_user_insert().
+ * Implements hook_user_insert().
  *
  * Update uid and preferred language when the new account was already subscribed.
  */
@@ -904,8 +913,7 @@ function simplenews_user_insert(&$edit, $account, $category) {  // Use the email
   $subscriber->mail = $edit['mail'];
   $subscription = simplenews_get_subscription($subscriber);
   // If the user is subscribed, we update the subscriber with uid and language.
-  if ($subscription->snid) {
-    // @todo Write a function to save/update a subscription and use it here.
+  if (!empty($subscription->snid)) {
     $subscriber->uid = $edit['uid'];
     $subscriber->language = $edit['language'];
     $subscriber->activated = 1;
@@ -945,7 +953,7 @@ function simplenews_user_insert(&$edit, $account, $category) {  // Use the email
 }
 
 /**
- * Implementation of hook_user_login().
+ * Implements hook_user_login().
  *
  * Subscribe user to a newsletter as per registration form.
  */
@@ -961,7 +969,7 @@ function simplenews_user_login(&$edit, $account) {
 }
 
 /**
- * Implementation of hook_user_presave().
+ * Implements hook_user_presave().
  *
  * User data (mail, status, language) is synchronized with subscriber.
  * This function handles existing user account, simplenews_user_insert takes
@@ -976,24 +984,19 @@ function simplenews_user_presave(&$edit, $account, $category) {
         $subscription = simplenews_get_subscription((object)array('uid' => $account->uid));
         // Only process existing subscriptions.
         if ($subscription->snid) {
+          $subscriber = simplenews_subscriber_load($subscription->snid);
           // Update mail, status and language if they are changed.
-          // @todo convert this code to simplenews_subscriber_save().
           $fields = array();
           if (isset($edit['mail'])) {
-            $fields['mail'] = $edit['mail'];
+            $subscriber->mail = $edit['mail'];
           }
           if (isset($edit['status']) && variable_get('simplenews_sync_account', TRUE)) {
-            $fields['activated'] = $edit['status'];
+            $subscriber->activated = $edit['status'];
           }
           if (isset($edit['language'])) {
-            $fields['language'] = $edit['language'];
-          }
-          if (!empty($fields)) {
-            $query = db_update('simplenews_subscriber')
-              ->condition('snid', $subscription->snid)
-              ->fields($fields)
-              ->execute();
+            $subscriber->language = $edit['language'];
           }
+          simplenews_subscriber_save($subscriber);
         }
       }
       break;
@@ -1001,7 +1004,7 @@ function simplenews_user_presave(&$edit, $account, $category) {
 }
 
 /**
- * Implementation of hook_user_cancel().
+ * Implements hook_user_cancel().
  */
 function simplenews_user_cancel($edit, $account, $method) {
  // Deactivate subscriber when account is disabled via cancel user.
@@ -1015,7 +1018,7 @@ function simplenews_user_cancel($edit, $account, $method) {
 }
 
 /**
- * Implementation of hook_user_delete().
+ * Implements hook_user_delete().
  */
 function simplenews_user_delete($account) {
   // Delete subscription and all newsletter subscriptions when account is removed.
@@ -1031,7 +1034,7 @@ function simplenews_user_delete($account) {
 }
 
 /**
- * Implementation of hook_user_categories().
+ * Implements hook_user_categories().
  */
 function simplenews_user_categories() {
   $output[] = array(
@@ -1045,7 +1048,7 @@ function simplenews_user_categories() {
 }
 
 /**
- * Implementation of hook_form_FORM_ID_alter().
+ * Implements hook_form_FORM_ID_alter().
  *
  * Add simplenews subscription management form to account category 'Newsletters'
  */
@@ -1060,9 +1063,7 @@ function simplenews_form_user_profile_form_alter(&$form, &$form_state) {
 }
 
 /**
- * Implementation of hook_user_view().
- *
- * @todo Check if hidden newsletters are not listed.
+ * Implements hook_user_view().
  */
 function simplenews_user_view($account, $build_mode) {
   global $user;
@@ -1109,7 +1110,7 @@ function simplenews_user_view($account, $build_mode) {
 }
 
 /**
- * Implementation of hook_block_info().
+ * Implements hook_block_info().
  */
 function simplenews_block_info() {
   $blocks = array();
@@ -1132,7 +1133,7 @@ function simplenews_block_info() {
 }
 
 /**
- * Implementation of hook_block_configure().
+ * Implements hook_block_configure().
  */
 function simplenews_block_configure($delta = '') {
   // Special block for multi
@@ -1190,7 +1191,7 @@ function simplenews_block_configure($delta = '') {
 }
 
 /**
- * Implementation of hook_block_save().
+ * Implements hook_block_save().
  */
 function simplenews_block_save($delta = '', $edit = array()) {
   if ($delta == 0) {
@@ -1207,7 +1208,7 @@ function simplenews_block_save($delta = '', $edit = array()) {
 }
 
 /**
- * Implementation of hook_block_view().
+ * Implements hook_block_view().
  */
 function simplenews_block_view($delta = '') {
   // Special block for multi
@@ -1239,7 +1240,7 @@ function simplenews_block_view($delta = '') {
 }
 
 /**
- * Implementation of hook_forms().
+ * Implements hook_forms().
  *
  * All form blocks are build using simplenews_block_form().
  * hook_forms() is required to provide unique form id for each block form.
@@ -1260,15 +1261,12 @@ function simplenews_forms($form_id, $args) {
 /**
  * Load a user or creates a dummy anonymous user.
  *
- * @return account
- *   object (
- *     mail,   email address
- *     uid,    uid or 0 for anonymous
- *   )
+ * @return
+ *   A user object if a user with that mail address exists, otherwise an object
+ *   with the properties mail and uid (set to 0).
  *
- * @todo Rewrite to use the new user_load(): http://drupal.org/node/224333#user_load_multiple
  */
-function _simplenews_user_load($mail) {
+function simplenews_load_user_by_mail($mail) {
   $account = user_load_by_mail($mail);
   if ($account === FALSE) {
     // Construct anonymous user since we don't have a user that matches that e-mail.
@@ -1308,10 +1306,7 @@ function simplenews_subscribe_user($mail, $tid, $confirm = TRUE, $source = 'unkn
   global $language;
 
   // Get current subscriptions if any.
-  $account = (object) array(
-    'mail' => $mail,
-  );
-  $subscriber = simplenews_get_subscription($account);
+  $subscriber = simplenews_get_subscription(simplenews_load_user_by_mail($mail));
 
   // If user is not subscribed to ANY newsletter, create a subscription account
   if ($subscriber->snid == 0) {
@@ -1321,7 +1316,7 @@ function simplenews_subscribe_user($mail, $tid, $confirm = TRUE, $source = 'unkn
     //   - Add the user to the database.
     //   - Get the full subscription object based on the mail address.
     // Note that step 3 gets subscription data based on mail address because the uid can be 0 (for anonymous users)
-    $account = _simplenews_user_load($mail);
+    $account = simplenews_load_user_by_mail($mail);
 
     // If the site is multilingual:
     //  - Anonymous users are subscribed with their preferred language
@@ -1383,13 +1378,13 @@ function simplenews_subscribe_user($mail, $tid, $confirm = TRUE, $source = 'unkn
  *   FALSE = The user is unsubscribed
  *   TRUE  = User receives an email to verify the address and complete the subscription cancellation
  *
- * @param string $mail
+ * @param $mail
  *   The email address to unsubscribe from the mailing list.
- * @param integer $tid
+ * @param $tid
  *   The term ID of the list.
- * @param boolean $confirm
+ * @param $confirm
  *   If TRUE, send a confirmation mail; if FALSE, unsubscribe immediately.
- * @param string $source
+ * @param $source
  *   Indicates the unsubscribe source. Simplenews uses these sources:
  *   - website: Via any website form (with or without confirmation email).
  *   - mass subscribe: Mass admin UI.
@@ -1397,10 +1392,7 @@ function simplenews_subscribe_user($mail, $tid, $confirm = TRUE, $source = 'unkn
  *   - action: Drupal actions.
  */
 function simplenews_unsubscribe_user($mail, $tid, $confirm = TRUE, $source = 'unknown') {
-  $account = (object) array(
-    'mail' => $mail,
-  );
-  $subscriber = simplenews_get_subscription($account);
+  $subscriber = simplenews_get_subscription(simplenews_load_user_by_mail($mail));
 
   // The unlikely case that a user is unsubscribed from a non existing mailing list is logged
   if (!$category = simplenews_category_load($tid)) {
@@ -1454,7 +1446,7 @@ function simplenews_user_is_subscribed($mail, $tid) {
   $subscribed = &drupal_static(__FUNCTION__, array());
 
   if (!isset($subscribed[$mail][$tid])) {
-    $subscription = simplenews_get_subscription((object)array('mail' => $mail));
+    $subscription = simplenews_get_subscription(simplenews_load_user_by_mail($mail));
     $subscribed[$mail][$tid] = isset($subscription->tids[$tid]);
   }
   return $subscribed[$mail][$tid];
@@ -1574,7 +1566,6 @@ function simplenews_get_subscription($account) {
  * @todo
  */
 function simplenews_get_subscriptions_by_list($tid) {
-  $subscriptions = array();
   $query = db_select('simplenews_subscriber', 'sn');
   $query->innerJoin('simplenews_subscription', 'ss', 'ss.snid = sn.snid');
   $query->fields('sn', array('mail', 'uid', 'language', 'snid'))
@@ -1714,85 +1705,13 @@ function simplenews_subscriber_save(&$subscriber) {
  * Delete subscriber from the database.
  *
  * @param $snid
- *   Simplenews subscriber object or subscriber ID.
- */
-function simplenews_subscriber_delete($subscriber) {
-  if (!is_object($subscriber)) {
-    // @todo What's the purpose of this test? Eventually loading the subscriber?
-  }
-
-  if ($subscriber) {
-    db_delete('simplenews_subscriber')
-      ->condition('snid', $subscriber->snid)
-      ->execute();
-    module_invoke_all('simplenews_subscriber_delete', $subscriber);
-  }
-}
-
-/**
- * Build subscription manager form.
- *
- * @param object $subscription
- *   The subscription object.
+ *   Simplenews subscriber object.
  */
-function _simplenews_subscription_manager_form($subscription) {
-  $form = array();
-  $options = array();
-  $default_value = array();
-  global $language;
-
-  $form['subscriptions'] = array(
-    '#type' => 'fieldset',
-    '#description' => t('Select the newsletter(s) to which you want to subscribe or unsubscribe.'),
-  );
-
-  // Get newsletters for subscription form checkboxes.
-  // Newsletters with opt-in/out method 'hidden' will not be listed.
-  foreach (simplenews_get_mailing_lists(user_access('administer simplenews subscriptions')) as $newsletter) {
-    $form['subscriptions']['newsletter-' . $newsletter->tid] = array(
-      '#type' => 'checkbox',
-      '#title' => check_plain(_simplenews_newsletter_name($newsletter)),
-      '#description' => check_plain(_simplenews_newsletter_description($newsletter)),
-      '#default_value' => in_array($newsletter->tid, $subscription->tids),
-    );
-  }
-
-  // If current user is logged in, just display email.
-  // Anonymous users see an email box and will receive confirmations
-  if ($subscription->mail) {
-    $form['subscriptions']['#title'] = t('Subscriptions for %mail', array('%mail' => $subscription->mail));
-    $form['subscriptions']['mail'] = array(
-      '#type' => 'value',
-      '#value' => $subscription->mail,
-    );
-    $form['update'] = array(
-      '#type' => 'submit',
-      '#value' => t('Update'),
-      '#weight' => 20,
-    );
-  }
-  else {
-    $form['subscriptions']['#title'] = t('Manage your newsletter subscriptions');
-    $form['subscriptions']['mail'] = array(
-      '#type' => 'textfield',
-      '#title' => t('Email'),
-      '#size' => 20,
-      '#maxlength' => 128,
-      '#weight' => 10,
-      '#required' => TRUE,
-    );
-    $form['subscribe'] = array(
-      '#type' => 'submit',
-      '#value' => t('Subscribe'),
-      '#weight' => 20,
-    );
-    $form['unsubscribe'] = array(
-      '#type' => 'submit',
-      '#value' => t('Unsubscribe'),
-      '#weight' => 30,
-    );
-  }
-  return $form;
+function simplenews_subscriber_delete(stdClass $subscriber) {
+  db_delete('simplenews_subscriber')
+    ->condition('snid', $subscriber->snid)
+    ->execute();
+  module_invoke_all('simplenews_subscriber_delete', $subscriber);
 }
 
 /**
@@ -1803,8 +1722,6 @@ function _simplenews_subscription_manager_form($subscription) {
  * @param integer $count
  *   The number of newsletters.
  *
- * @todo Replace 'class' string by array.
- * @see http://drupal.org/node/224333#class_attribute_array
  * @todo Replace this list by a View.
  */
 function simplenews_recent_newsletters($tid, $count = 5) {
@@ -1876,17 +1793,6 @@ function simplenews_views_api() {
 }
 
 /**
- * Get path to simplenews category page.
- *
- * @param $category
- *   Newsletter category object.
- * @return drupal path
- */
-function simplenews_category_path($category) {
-  return 'simplenews/category/' . $category->tid;
-}
-
-/**
  * Get a simplenews newsletter category object.
  *
  * @param $tid
@@ -1913,7 +1819,7 @@ function simplenews_category_list() {
   $categories = simplenews_categories_load_multiple();
   $cats = array();
   foreach ($categories as $key => $category) {
-    $cats[$key] = _simplenews_newsletter_name($category);
+    $cats[$key] = check_plain(_simplenews_newsletter_name($category));
   }
   return $cats;
 }
@@ -1997,12 +1903,6 @@ function simplenews_category_delete($category) {
       ->condition('tid', $category->tid)
       ->execute();
     module_invoke_all('simplenews_category_delete', $category);
-    variable_del('simplenews_from_name_' . $category->tid);
-    variable_del('simplenews_email_subject_' . $category->tid);
-    variable_del('simplenews_from_address_' . $category->tid);
-    variable_del('simplenews_hyperlinks_' . $category->tid);
-    variable_del('simplenews_new_account_' . $category->tid);
-    variable_del('simplenews_opt_inout_' . $category->tid);
   }
 }
 
@@ -2097,10 +1997,9 @@ function simplenews_newsletter_delete($newsletter) {
 }
 
 /**
- * Implementation of hook_token_info().
+ * Implements hook_token_info().
  */
 function simplenews_token_info() {
-  // @todo Add desription to the types and extend available tokens.
   $types['simplenews-subscriber'] = array(
     'name' => t('Simplenews subscriber'),
     'description' => t('Tokens related to the newsletter recipient'),
@@ -2157,7 +2056,7 @@ function simplenews_token_info() {
 }
 
 /**
- * Implementation of hook_tokens().
+ * Implements hook_tokens().
  *
  */
 function simplenews_tokens($type, $tokens, $data = array(), $options = array()) {
@@ -2230,50 +2129,6 @@ function simplenews_tokens($type, $tokens, $data = array(), $options = array())
 }
 
 /**
- * Array merge with callback.
- *
- * Merge arrays as array_merge() but only
- * if callback permits merge of elements with the same key.
- *
- * @param $array1
- *   Initial array to merge
- * @param $array2
- *   Array to merge
- * @param $callback
- *   Callback function. Array elements with matching keys will be merged
- *   if callback function returns true for the matching $array2 element.
- * @return array
- *   Resulting array
- */
-function simplenews_array_merge($array1, $array2, $callback) {
-  if (!function_exists($callback)) {
-    return array_merge($array1, $array2);
-  }
-  foreach ($array1 as $key => $data) {
-    if (isset($array2[$key])) {
-      if ($callback($data)) {
-        $array1[$key] = $array2[$key];
-      }
-    }
-  }
-  $array1 += array_diff_key($array2, $array1);
-  return $array1;
-}
-
-/**
- * Check recipient status.
- *
- * @param $recipient
- *   Subscriber object
- * @return boolean
- *   TRUE: status is 1; may receive email; subscribed
- *   FALSE: status is 0; should not to receive email; unsubscribed
- */
-function simplenews_check_status($recipient) {
-  return (bool)$recipient->status;
-}
-
-/**
  * Create a 32 character identifier.
  */
 function simplenews_private_key() {
@@ -2287,7 +2142,7 @@ function simplenews_private_key() {
 }
 
 /**
- * Implementation of hook_help().
+ * Implements hook_help().
  *
  * @todo Rewrite help text to match the new terminology, the new data architecture, the new admin pages, the news node-form interface.
  */
@@ -2419,7 +2274,7 @@ function simplenews_format_options() {
 }
 
 /**
- * Implementation of hook_locale().
+ * Implements hook_locale().
  */
 function simplenews_locale($op = 'groups', $group = NULL) {
   switch ($op) {
@@ -2511,9 +2366,8 @@ function _simplenews_get_node_form_defaults() {
 }
 
 /**
- * Implementation of hook_theme().
+ * Implements hook_theme().
  *
- * @todo Theme definitions must register how it integrates with drupal_render(): http://drupal.org/node/224333#hook_theme_render_changes
  */
 function simplenews_theme() {
   $path = drupal_get_path('module', 'simplenews');
@@ -2548,6 +2402,8 @@ function simplenews_theme() {
         'language' => NULL,
       ),
       'path' => $path . '/theme',
+      'template' => 'simplenews-newsletter-body',
+      'pattern' => 'simplenews-newsletter-body__',
     ),
     'simplenews_newsletter_footer' => array(
       'variables' => array(
@@ -2558,6 +2414,8 @@ function simplenews_theme() {
         'language' => NULL,
       ),
       'path' => $path . '/theme',
+      'template' => 'simplenews-newsletter-footer',
+      'pattern' => 'simplenews-newsletter-footer__',
     ),
     'simplenews_filter_form' => array(
       'render element' => 'form',
@@ -2579,7 +2437,6 @@ function simplenews_theme() {
  *
  * @see simplenews-block.tpl.php
  * @see theme_simplenews-block()
- * @todo use drupal_render() with drupal_get_form(): http://drupal.org/node/224333#unrendered
  */
 function template_preprocess_simplenews_block(&$variables) {
   global $user;
@@ -2621,7 +2478,7 @@ function template_preprocess_simplenews_block(&$variables) {
 }
 
 /**
- * Process variables to format the simplenews newsletter footer.
+ * Process variables for the multi subscription block.
  *
  * $variables are empty:
  *
@@ -2734,15 +2591,6 @@ function template_preprocess_simplenews_newsletter_body(&$variables) {
 }
 
 /**
- * @todo
- */
-function theme_simplenews_newsletter_body($variables) {
-  $output  = '<h2>' . $variables['title'] . "</h2>\n";
-  $output .= drupal_render($variables['build']);
-  return $output;
-}
-
-/**
  * Process variables to format the simplenews newsletter footer.
  *
  * $variables contains:
@@ -2773,46 +2621,6 @@ function template_preprocess_simplenews_newsletter_footer(&$variables) {
 }
 
 /**
- * @todo
- */
-function theme_simplenews_newsletter_footer($variables) {
-  if ($variables['format'] == 'html') {
-    $output = '<p class="newsletter-footer"><a href="[simplenews-subscriber:unsubscribe-url]">' . $variables['unsubscribe_text'] . '</a></p>';
-  }
-  else {
-    $output = $variables['unsubscribe_text'] . ': [simplenews-subscriber:unsubscribe-url]';
-  }
-  if ($variables['key'] == 'test') {
-    $output .= '- - - ' . $variables['test_message'] . ' - - -';
-  }
-
-  // Do not display the unsubscribe link by default for hidden categories.
-  $variables['opt_out_hidden'] = $variables['category']->opt_inout == 'hidden';
-  return $output;
-}
-
-
-/**
- * Helper function to filter checked boxes from form values.
- */
-function _simplenews_checked($value) {
-  return ($value === 1);
-}
-
-/**
- * Following 5 functions are for separated newsletter tab
- *
- */
-
-/**
- * Menu callback; Newsletter tab page.
- */
-function simplenews_node_tab_page($node){
-  drupal_set_title(t('<em>Newsletter</em> @title', array('@title' => $node->title)), PASS_THROUGH);
-  return drupal_get_form('simplenews_node_tab_send_form', $node);
-}
-
-/**
  * Access callback; Acces to Newsletter tab page.
  */
 function simplenews_node_tab_access($node) {
@@ -2820,182 +2628,6 @@ function simplenews_node_tab_access($node) {
 }
 
 /**
- * @todo
- */
-function simplenews_node_tab_send_form($form, &$form_state, $node){
-  // First check if there already is a loaded simplenews object.
-  if (!empty($node->simplenews)) {
-    $simplenews_values = $node->simplenews;
-  }
-  // If not, try to load it based on the node id.
-  else if ($loaded = simplenews_newsletter_load($node->nid)) {
-    $simplenews_values = $loaded;
-  }
-  // If that fails too, fall back to the defaults.
-  else {
-    $simplenews_values = (object)_simplenews_get_node_form_defaults($node);
-  }
-
-  $form = array();
-  // We will need the node
-  $form['nid'] = array(
-    '#type' => 'value',
-    '#value' => $node->nid,
-  );
-
-  // @todo delete this fieldset?
-  $form['simplenews'] = array(
-    '#type' => 'fieldset',
-    '#title' => t('Send newsletter'),
-    '#collapsible' => FALSE,
-    '#collapsed' => FALSE,
-    '#tree' => TRUE,
-  );
-
-  // Translations of newsletters don't have the 'send' option. Only the
-  // translation source (and non translated) newsletters will get these options.
-  if (module_exists('translation') && translation_supported_type($node->type)
-    && (isset($node->translate) && ($node->tnid > 0) && ($node->tnid != $node->nid))) {
-    $form['simplenews']['#description'] = t('This newsletter issue is part of a translation set. Sending this set is controlled from the <a href="@link">translation source newsletter</a>.', array('@link' => url('node/' . $node->tnid)));
-    // @todo Translated nodes must also have the same Category!
-    //      Move the category in here and give the user feedback.
-  }
-  else {
-    // Show newsletter sending options if newsletter has not been send yet.
-    // If send a notification is shown.
-    if ($simplenews_values->status == SIMPLENEWS_STATUS_SEND_NOT || $simplenews_values->status == SIMPLENEWS_STATUS_SEND_PUBLISH) {
-
-      $options = array(
-        SIMPLENEWS_COMMAND_SEND_TEST => t('Send one test newsletter to the test address'),
-      );
-
-      // Add option to send on publish when the node is unpublished.
-      if ($node->status == NODE_NOT_PUBLISHED) {
-        $options[SIMPLENEWS_COMMAND_SEND_PUBLISH] = t('Send newsletter when published');
-      }
-      else {
-        $options[SIMPLENEWS_COMMAND_SEND_NOW] = t('Send newsletter');
-      }
-
-      if ($simplenews_values->status == SIMPLENEWS_STATUS_SEND_PUBLISH) {
-        $send_default = SIMPLENEWS_STATUS_SEND_PUBLISH;
-      }
-      else {
-        $send_default = variable_get('simplenews_send', SIMPLENEWS_COMMAND_SEND_TEST);
-      }
-      $form['simplenews']['send'] = array(
-        '#type' => 'radios',
-        '#title' => t('Send newsletter'),
-        '#default_value' => isset($simplenews_values->send) ? $simplenews_values->send : $send_default,
-        '#options' => $options,
-        '#attributes' => array(
-          'class' => array('simplenews-command-send'),
-        ),
-      );
-
-      $address_default = variable_get('site_mail', ini_get('sendmail_from'));
-      if (variable_get('simplenews_test_address_override', 0)) {
-        $form['simplenews']['test_address'] = array(
-          '#type' => 'textfield',
-          '#title' => t('Test email addresses'),
-          '#description' => t('A comma-separated list of email addresses to be used as test addresses.'),
-          '#default_value' => variable_get('simplenews_test_address', $address_default),
-          '#size' => 60,
-          '#maxlength' => 128,
-        );
-      }
-      else {
-        $form['simplenews']['test_address'] = array(
-          '#type' => 'value',
-          '#value' => variable_get('simplenews_test_address', $address_default),
-        );
-      }
-    }
-    else {
-      $form['simplenews']['none'] = array(
-        '#type' => 'checkbox',
-        '#return_value' => 0,
-        '#attributes' => array(
-          'checked' => 'checked',
-          'disabled' => 'disabled',
-        ),
-      );
-      $form['simplenews']['none']['#title'] = ($simplenews_values->status == SIMPLENEWS_STATUS_SEND_READY) ? t('This newsletter has been sent') : t('This newsletter is pending');
-      return $form;
-    }
-    $form['submit'] = array(
-      '#type' => 'submit',
-      '#value' => t('Submit'),
-    );
-  }
-  return $form;
-}
-
-/**
- * @todo
- */
-function simplenews_node_tab_send_form_validate($form, &$form_state) {
-  $values = $form_state['values'];
-  $node = node_load($values['nid']);
-
-  $default_address = variable_get('simplenews_test_address', variable_get('site_mail', ini_get('sendmail_from')));
-  $mails = array($default_address);
-  if (isset($values['simplenews']['send']) && $values['simplenews']['send'] == SIMPLENEWS_COMMAND_SEND_TEST && variable_get('simplenews_test_address_override', 0)) {
-   // @todo Can we simplify and use only two kind of messages?
-    if (!empty($values['simplenews']['test_address'])) {
-      $mails = explode(',', $values['simplenews']['test_address']);
-      foreach ($mails as $mail) {
-        $mail = trim($mail);
-        if ($mail == '') {
-          form_set_error('simplenews][test_address', t('Test email address is empty.'));
-        }
-        elseif (!valid_email_address($mail)) {
-          form_set_error('simplenews][test_address', t('Invalid email address "%mail".', array('%mail' => $mail)));
-        }
-      }
-    }
-    else {
-      form_set_error('simplenews][test_address', t('Missing test email address.'));
-    }
-  }
-  $form_state['test_addresses'] = $mails;
-}
-
-/**
- * @todo
- */
-function simplenews_node_tab_send_form_submit($form, &$form_state) {
-  $values = $form_state['values'];
-  $node = node_load($values['nid']);
-
-  // Send newsletter to all subscribers or send test newsletter
-  module_load_include('inc', 'simplenews', 'includes/simplenews.mail');
-  if ($values['simplenews']['send'] == SIMPLENEWS_COMMAND_SEND_NOW) {
-    $status = simplenews_add_node_to_spool($node);
-    if ($status == SIMPLENEWS_STATUS_SEND_READY) {
-      drupal_set_message(t('Newsletter %title sent.', array('%title' => $node->title)));
-    }
-    else {
-      drupal_set_message(t('Newsletter %title pending.', array('%title' => $node->title)));
-    }
-  }
-  elseif ($values['simplenews']['send'] == SIMPLENEWS_COMMAND_SEND_TEST) {
-    simplenews_send_test($node, $form_state['test_addresses']);
-  }
-
-  // If the selected command is send on publish, just set the newsletter status.
-  if ($values['simplenews']['send'] == SIMPLENEWS_COMMAND_SEND_PUBLISH) {
-    $newsletter = simplenews_newsletter_load($node->nid);
-    if (!$newsletter) {
-      $newsletter = simplenews_newsletter_defaults($node);
-    }
-    $newsletter->status = SIMPLENEWS_STATUS_SEND_PUBLISH;
-    simplenews_newsletter_save($newsletter);
-    drupal_set_message(t('The newsletter will be sent when the content is published.'));
-  }
-}
-
-/**
  * Update the sent status of a node.
  *
  * If the node part of a translation set, all corresponding translations are
@@ -3054,7 +2686,7 @@ function simplenews_field_extra_fields() {
 
 
 /**
- * Implementation of hook_node_access().
+ * Implements hook_node_access().
  *
  * Don't allow deletion when a newsletter is pending
  */
diff --git a/simplenews_rules/simplenews_rules.rules.inc b/simplenews_rules/simplenews_rules.rules.inc
index 8838e6e..4ed2ca9 100755
--- a/simplenews_rules/simplenews_rules.rules.inc
+++ b/simplenews_rules/simplenews_rules.rules.inc
@@ -206,7 +206,7 @@ function simplenews_rules_map_confirmation($args) {
       $confirmation = FALSE;
       break;
     case SIMPLENEWS_RULES_CONFIRMATION_DEFAULT:
-      $account = _simplenews_user_load($args['mail']);
+      $account = simplenews_load_user_by_mail($args['mail']);
       $confirmation = simplenews_require_double_opt_in($args['tid'], $account);
       break;
   }
diff --git a/tests/simplenews.test b/tests/simplenews.test
index e94b831..fcc2eb0 100644
--- a/tests/simplenews.test
+++ b/tests/simplenews.test
@@ -5,8 +5,6 @@
  * Simplenews test functions.
  *
  * @ingroup simplenews
- * @todo Redo all database functions: http://drupal.org/node/224333#dbtng
- * @todo Where possible build re-usable functions wrapped around database calls.
  */
 
 class SimplenewsTestCase extends DrupalWebTestCase {
@@ -138,11 +136,29 @@ class SimplenewsTestCase extends DrupalWebTestCase {
     $this->drupalPost('admin/structure/block/manage/simplenews/' . $tid . '/configure', $edit, t('Save block'));
     $this->assertText('The block configuration has been saved.', 'The newsletter block configuration has been saved.');
   }
+
+  function setUpSubscribers($count = 100) {
+    // Subscribe users.
+    $this->subscribers = array();
+    for ($i = 0; $i < $count; $i++) {
+      $mail = $this->randomEmail();
+      $this->subscribers[$mail] = $mail;
+    }
+
+    $this->drupalGet('admin/people/simplenews');
+    $this->clickLink(t('Mass subscribe'));
+    $edit = array(
+      'emails' => implode(',', $this->subscribers),
+      // @todo: Don't hardcode the default tid.
+      'newsletters[1]' => TRUE,
+    );
+    $this->drupalPost(NULL, $edit, t('Subscribe'));
+  }
 }
 
 class SimplenewsSubscribeTestCase extends SimplenewsTestCase {
   /**
-   * Implementation of getInfo().
+   * Implement getInfo().
    */
   function getInfo() {
     return array(
@@ -557,7 +573,7 @@ class SimplenewsSubscribeTestCase extends SimplenewsTestCase {
 class SimpleNewsAdministrationTestCase extends SimplenewsTestCase {
 
   /**
-   * Implementation of getInfo().
+   * Implement getInfo().
    */
   function getInfo() {
     return array(
@@ -799,7 +815,7 @@ class SimpleNewsAdministrationTestCase extends SimplenewsTestCase {
         'emails' => implode($delimiters[$i++], $subscribers[$key]),
       );
       foreach ($group as $tid) {
-        $edit[$tid] = TRUE;
+        $edit['newsletters[' . $tid . ']'] = TRUE;
       }
       $this->drupalPost(NULL, $edit, t('Subscribe'));
     }
@@ -861,7 +877,7 @@ class SimpleNewsAdministrationTestCase extends SimplenewsTestCase {
     unset($subscribers[$first][$first_mail]);
     $edit = array(
       'emails' => $first_mail . ', ' . $all_mail,
-      $first => TRUE,
+      'newsletters[' . $first . ']' => TRUE,
     );
     $this->clickLink(t('Mass unsubscribe'));
     $this->drupalPost(NULL, $edit, t('Unsubscribe'));
@@ -883,7 +899,7 @@ class SimpleNewsAdministrationTestCase extends SimplenewsTestCase {
 
     // Check exporting.
     $this->clickLink(t('Export'));
-    $this->drupalPost(NULL, array('lists[' . $first . ']' => TRUE), t('Export'));
+    $this->drupalPost(NULL, array('newsletters[' . $first . ']' => TRUE), t('Export'));
     $export_field = $this->xpath($this->constructFieldXpath('name', 'emails'));
     $exported_mails = (string)$export_field[0];
     foreach ($subscribers[$first] as $mail) {
@@ -902,7 +918,7 @@ class SimpleNewsAdministrationTestCase extends SimplenewsTestCase {
     $edit = array(
       'subscribed[subscribed]' => FALSE,
       'subscribed[unsubscribed]' => TRUE,
-      'lists[' . $first . ']' => TRUE,
+      'newsletters[' . $first . ']' => TRUE,
     );
     $this->drupalPost(NULL, $edit, t('Export'));
 
@@ -1256,22 +1272,7 @@ class SimplenewsSendTestCase extends SimplenewsTestCase {
     $this->drupalLogin($this->user);
 
     // Subscribe a few users.
-    $this->subscribers = array();
-    for ($i = 0; $i < 5; $i++) {
-      $mail = $this->randomEmail();
-      $this->subscribers[$mail] = $mail;
-    }
-
-    $delimiters = array(',', ' ', "\n");
-
-    $this->drupalGet('admin/people/simplenews');
-    $this->clickLink(t('Mass subscribe'));
-    $edit = array(
-      'emails' => implode(',', $this->subscribers),
-      // @todo: Don't hardcode the default tid.
-      '1' => TRUE,
-    );
-    $this->drupalPost(NULL, $edit, t('Subscribe'));
+    $this->setUpSubscribers(5);
   }
 
   /**
@@ -1713,24 +1714,6 @@ class SimplenewsSourceTestCase extends SimplenewsTestCase {
     $this->drupalLogin($this->user);
   }
 
-  function subscribeUsers($count = 100) {
-    // Subscribe users.
-    $this->subscribers = array();
-    for ($i = 0; $i < $count; $i++) {
-      $mail = $this->randomEmail();
-      $this->subscribers[$mail] = $mail;
-    }
-
-    $this->drupalGet('admin/people/simplenews');
-    $this->clickLink(t('Mass subscribe'));
-    $edit = array(
-      'emails' => implode(',', $this->subscribers),
-      // @todo: Don't hardcode the default tid.
-      '1' => TRUE,
-    );
-    $this->drupalPost(NULL, $edit, t('Subscribe'));
-  }
-
   /**
    * Tests that sending a minimal implementation of the source interface works.
    */
@@ -1787,7 +1770,7 @@ class SimplenewsSourceTestCase extends SimplenewsTestCase {
    */
   function testSendCaching() {
 
-    $this->subscribeUsers(100);
+    $this->setUpSubscribers(100);
     // Enable build caching.
     $edit = array(
       'simplenews_source_cache' => 'SimplenewsSourceCacheBuild',
@@ -1830,7 +1813,7 @@ class SimplenewsSourceTestCase extends SimplenewsTestCase {
    * Send a newsletter with the HTML format.
    */
   function testSendHTML() {
-    $this->subscribeUsers(5);
+    $this->setUpSubscribers(5);
 
     // Use custom testing mail system to support HTML mails.
     variable_set('mail_system', array('default-system' => 'SimplenewsHTMLTestingMailSystem'));
@@ -1892,7 +1875,7 @@ class SimplenewsSourceTestCase extends SimplenewsTestCase {
    * Send a newsletter with the category set to hidden.
    */
   function testSendHidden() {
-    $this->subscribeUsers(5);
+    $this->setUpSubscribers(5);
 
     // Set the format to HTML.
     $this->drupalGet('admin/config/services/simplenews');
@@ -1931,7 +1914,7 @@ class SimplenewsSourceTestCase extends SimplenewsTestCase {
    * Test with disabled caching.
    */
   function testSendNoCaching() {
-    $this->subscribeUsers(100);
+    $this->setUpSubscribers(100);
     // Disable caching.
     $edit = array(
       'simplenews_source_cache' => 'SimplenewsSourceCacheNone',
diff --git a/theme/simplenews-newsletter-body.tpl.php b/theme/simplenews-newsletter-body.tpl.php
index a77df85..2ddfef0 100644
--- a/theme/simplenews-newsletter-body.tpl.php
+++ b/theme/simplenews-newsletter-body.tpl.php
@@ -18,7 +18,6 @@
  * - $view_mode: Active view mode.
  *
  * @see template_preprocess_simplenews_newsletter_body()
- * @see theme_simplenews_newsletter_body()
  */
 ?>
 <h2><?php print $title; ?></h2>
diff --git a/theme/simplenews-newsletter-footer.tpl.php b/theme/simplenews-newsletter-footer.tpl.php
index a51e7c3..b6f80cc 100644
--- a/theme/simplenews-newsletter-footer.tpl.php
+++ b/theme/simplenews-newsletter-footer.tpl.php
@@ -23,7 +23,6 @@
  * and 'simplenews-list'
  *
  * @see template_preprocess_simplenews_newsletter_footer()
- * @see theme_simplenews_newsletter_footer()
  */
 ?>
 <?php if (!$opt_out_hidden): ?>
