You are here

function simplenews_mail_spool in Simplenews 6.2

Same name and namespace in other branches
  1. 6 simplenews.module \simplenews_mail_spool()
  2. 7.2 includes/simplenews.mail.inc \simplenews_mail_spool()
  3. 7 includes/simplenews.mail.inc \simplenews_mail_spool()

Send simplenews newsletters from the spool.

Individual newsletter emails are stored in database spool. Sending is triggered by cron or immediately when the node is saved. Mail data is retrieved from the spool, rendered and send one by one If sending is successful the message is marked as send in the spool.

TODO: Redesign API to allow language counter in multilingual sends.

2 calls to simplenews_mail_spool()
simplenews_cron in ./simplenews.module
Implementation of hook_cron().
simplenews_send_node in includes/simplenews.mail.inc
Send newsletter node to subscribers.
3 string references to 'simplenews_mail_spool'
simplenews_update_6004 in ./simplenews.install
Add spool table and remove cache table.
simplenews_update_6201 in ./simplenews.install
Correction of field size mismatch caused by simplenews_update_6009().
simplenews_update_6254 in ./simplenews.install
Add snid field to simplenews spool table.

File

includes/simplenews.mail.inc, line 282
Simplenews email send and spool handling

Code

function simplenews_mail_spool($nid = NULL, $vid = NULL, $limit = NULL) {

  // Send pending messages from database cache
  // A limited number of mails is retrieved from the spool
  $limit = isset($limit) ? $limit : variable_get('simplenews_throttle', 20);
  if ($messages = simplenews_get_spool(array(
    SIMPLENEWS_SPOOL_PENDING,
    SIMPLENEWS_SPOOL_IN_PROGRESS,
  ), $limit)) {
    $count_fail = $count_success = 0;

    // switch to anonymous user - needed in foreground spool sends, adopted from D7 drupal_cron_run().
    // see #471594 for issue about sending with higher permissions
    // note that private (non-public) fields might be invisible in newsletters now always.
    $original_user = $GLOBALS['user'];
    $GLOBALS['user'] = drupal_anonymous_user();

    // Get PHP maximum execution time. 30 seconds default.
    $max_execution_time = ini_get('max_execution_time') ? ini_get('max_execution_time') : SIMPLENEWS_MAX_EXECUTION_TIME;
    _simplenews_measure_usec(TRUE);
    $check_counter = 0;
    foreach ($messages as $key => $message) {
      $result = simplenews_mail_mail($message['nid'], $message['vid'], $message['mail']);

      // Update spool status.
      // This is not optimal for performance but prevents duplicate emails
      // in case of PHP execution time overrun.
      simplenews_update_spool(array(
        $key,
      ), $result);
      if ($result['status'] == SIMPLENEWS_SPOOL_DONE) {
        $count_success++;
      }
      if ($result['error']) {
        $count_fail++;
      }

      // Check every n emails if we exceed the limit.
      // When PHP maximum execution time is almost elapsed we interrupt
      // sending. The remainder will be sent during the next cron run.
      if (++$check_counter >= SIMPLENEWS_SEND_CHECK_INTERVAL) {
        $check_counter = 0;

        // Break the sending if a percentage of max execution time was exceeded.
        $elapsed = _simplenews_measure_usec();
        if ($max_execution_time && $elapsed > SIMPLENEWS_SEND_TIME_LIMIT * $max_execution_time) {
          watchdog('simplenews', 'Sending interrupted: PHP maximum execution time almost exceeded. Remaining newsletters will be sent during the next cron run. If this warning occurs regularly you should reduce the !cron_throttle_setting.', array(
            '!cron_throttle_setting' => l(t('Cron throttle setting'), 'admin/settings/simplenews/mail'),
          ), WATCHDOG_WARNING);
          break;
        }
      }
    }

    // Report sent result and elapsed time. On Windows systems getrusage() is
    // not implemented and hence no elapsed time is available.
    if (function_exists('getrusage')) {
      watchdog('simplenews', '%success emails sent in %sec seconds, %fail failed sending.', array(
        '%success' => $count_success,
        '%sec' => round(_simplenews_measure_usec(), 1),
        '%fail' => $count_fail,
      ));
    }
    else {
      watchdog('simplenews', '%success emails sent, %fail failed.', array(
        '%success' => $count_success,
        '%fail' => $count_fail,
      ));
    }
    variable_set('simplenews_last_cron', time());

    //@todo: set mail_sent from last batch
    variable_set('simplenews_last_sent', $count_success + $count_fail);

    // Restore the user.
    $GLOBALS['user'] = $original_user;
  }
}