You are here

function simplenews_mail_spool in Simplenews 7

Same name and namespace in other branches
  1. 6.2 includes/simplenews.mail.inc \simplenews_mail_spool()
  2. 6 simplenews.module \simplenews_mail_spool()
  3. 7.2 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.

Parameters

$limit: (Optional) The maximum number of mails to send. Defaults to unlimited.

$conditions: (Optional) Array of spool conditions which are applied to the query.

Return value

Returns the amount of sent mails.

Related topics

10 calls to simplenews_mail_spool()
drush_simplenews_spool_send in ./simplenews.drush.inc
Drush command to send the mail spool queue.
SimplenewsSendTestCase::testProgrammaticNewsletter in tests/simplenews.test
Creates and sends a node using the API.
SimplenewsSourceTestCase::testSendCaching in tests/simplenews.test
Test sending a newsletter to 100 recipients with caching enabled.
SimplenewsSourceTestCase::testSendHidden in tests/simplenews.test
Send a newsletter with the category set to hidden.
SimplenewsSourceTestCase::testSendHTML in tests/simplenews.test
Send a newsletter with the HTML format.

... See full list

8 string references to 'simplenews_mail_spool'
d6_simplenews_61.php in tests/d6_simplenews_61.php
d6_simplenews_62.php in tests/d6_simplenews_62.php
simplenews_count_spool in includes/simplenews.mail.inc
Count data in mail spool table.
simplenews_delete_spool in includes/simplenews.mail.inc
Remove records from mail spool table according to the conditions.
simplenews_mail_attempt_immediate_send in includes/simplenews.mail.inc
Send mail spool immediatly if cron should not be used.

... See full list

File

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

Code

function simplenews_mail_spool($limit = SIMPLENEWS_UNLIMITED, array $conditions = array()) {
  $check_counter = 0;

  // Send pending messages from database cache.
  $spool_list = simplenews_get_spool($limit, $conditions);
  if ($spool_list) {

    // Switch to the anonymous user.
    simplenews_impersonate_user(drupal_anonymous_user());
    $count_fail = $count_success = 0;
    $sent = array();
    _simplenews_measure_usec(TRUE);
    $spool = new SimplenewsSpool($spool_list);
    while ($source = $spool
      ->nextSource()) {
      $source
        ->setKey('node');
      $result = simplenews_send_source($source);

      // Update spool status.
      // This is not optimal for performance but prevents duplicate emails
      // in case of PHP execution time overrun.
      foreach ($spool
        ->getProcessed() as $msid => $row) {
        $row_result = isset($row->result) ? $row->result : $result;
        simplenews_update_spool(array(
          $msid,
        ), $row_result);
        if ($row_result['status'] == SIMPLENEWS_SPOOL_DONE) {
          $count_success++;
          if (!isset($sent[$row->actual_nid])) {
            $sent[$row->actual_nid] = 1;
          }
          else {
            $sent[$row->actual_nid]++;
          }
        }
        if ($row_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 && ini_get('max_execution_time') > 0) {
        $check_counter = 0;

        // Break the sending if a percentage of max execution time was exceeded.
        $elapsed = _simplenews_measure_usec();
        if ($elapsed > SIMPLENEWS_SEND_TIME_LIMIT * ini_get('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/config/simplenews/mail'),
          ), WATCHDOG_WARNING);
          break;
        }
      }
    }

    // It is possible that all or at the end some results failed to get
    // prepared, report them separately.
    foreach ($spool
      ->getProcessed() as $msid => $row) {
      $row_result = $row->result;
      simplenews_update_spool(array(
        $msid,
      ), $row_result);
      if ($row_result['status'] == SIMPLENEWS_SPOOL_DONE) {
        $count_success++;
        if (isset($row->actual_nid)) {
          if (!isset($sent[$row->actual_nid])) {
            $sent[$row->actual_nid] = 1;
          }
          else {
            $sent[$row->actual_nid]++;
          }
        }
      }
      if ($row_result['error']) {
        $count_fail++;
      }
    }

    // Update subscriber count.
    foreach ($sent as $nid => $count) {
      db_update('simplenews_newsletter')
        ->condition('nid', $nid)
        ->expression('sent_subscriber_count', 'sent_subscriber_count + :count', array(
        ':count' => $count,
      ))
        ->execute();
    }

    // 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', REQUEST_TIME);
    variable_set('simplenews_last_sent', $count_success);
    simplenews_revert_user();
    return $count_success;
  }
}