<?php
/**
 * @file
 * Mass e-mail module for Drupal 7.
 *
 * @see http://drupal.org/project/manymail
 */

define('MANYMAIL_RECIPIENT_STATUS_IN_QUEUE', 0);
define('MANYMAIL_RECIPIENT_STATUS_BOUNCED', 1);
define('MANYMAIL_RECIPIENT_STATUS_FAILURE', 2);
define('MANYMAIL_RECIPIENT_STATUS_SUCCESS', 3);

/**
 * E-mail recipients retrieval function.
 *
 * Retrieves all e-mail recipients.
 *
 * @return ManyMailRecipientList
 *   A list of all recipients in the user database.
 */
function manymail_get_all_addresses() {
  $list = new ManyMailRecipientList();
  $list->addAll();

  return $list;
}

/**
 * E-mail recipients retrieval function.
 *
 * Retrieves all e-mail recipients of (a) certain role(s).
 *
 * @param int $role
 *   A role id (rid) or array of rids.
 *
 * @return ManyMailRecipientList
 *   A list of all recipients for (a) certain role(s).
 */
function manymail_get_role_addresses($role) {
  $list = new ManyMailRecipientList();
  $list->addRole($role);

  return $list;
}

/**
 * Gathers all information about recipient retrieval.
 *
 * Modules can implement hook_manymail_recipients() to specify which function
 * should be called to generate a ManyMailRecipientList as well as what values
 * they need from the $form_state variable.
 *
 * @return array
 *   Associative array of all hook_manymail_recipients() implementations.
 */
function manymail_recipients() {
  $recipients = module_invoke_all('manymail_recipients');

  $recipients['manymail_send_all_form'] = array(
    'callback' => 'manymail_get_all_addresses',
  );

  $recipients['manymail_send_role_form'] = array(
    'callback' => 'manymail_get_role_addresses',
    'values' => array('roles'),
  );

  drupal_alter('manymail_recipients', $recipients);

  return $recipients;
}

/**
 * Retrieves all recipients for any form.
 *
 * @var array $form_state
 *   The $form_state array of the submitted send form.
 *
 * @return ManyMailRecipientList
 *   The recipient list generated by the function specified in
 *   hook_manymail_recipients().
 *
 * @see manymail_recipients()
 */
function manymail_get_recipients($form_state) {
  $recipient_funcs = manymail_recipients();
  $arguments = array();

  $form_id = $form_state['complete form']['#form_id'];

  if (isset($recipient_funcs[$form_id])) {
    if (empty($recipient_funcs[$form_id]['callback'])) {
      return FALSE;
    }

    if (!empty($recipient_funcs[$form_id]['values']) && is_array($recipient_funcs[$form_id]['values'])) {
      foreach ($recipient_funcs[$form_id]['values'] as $value) {
        if (!empty($form_state['values'][$value])) {
          $arguments[] = $form_state['values'][$value];
        }
      }
    }

    if (function_exists($recipient_funcs[$form_id]['callback'])) {
      return call_user_func_array($recipient_funcs[$form_id]['callback'], $arguments);
    }
  }

  return FALSE;
}

/**
 * Test whether an SMTP connection can be made.
 *
 * @return bool
 *   Whether the connection was successful.
 */
function manymail_validate_smtp() {
  // Load the PHPMailer library.
  $library = libraries_load('phpmailer');

  if (!$library || empty($library['loaded'])) {
    watchdog('ManyMail', 'Could not load PHPMailer library when trying to validate the SMTP settings.', NULL, WATCHDOG_ERROR);
    return FALSE;
  }

  // Set up a new mailer with the SMTP settings.
  $mail = new ManyMailMailer(TRUE);
  $mail->IsSMTP();

  $mail->Host    = variable_get('manymail_smtp_host', 'localhost');
  $mail->Port    = variable_get('manymail_smtp_port', 25);
  $mail->Timeout = variable_get('manymail_smtp_timeout', 10);

  $mail->SMTPSecure = variable_get('manymail_smtp_secure', '');
  $mail->SMTPAuth   = variable_get('manymail_smtp_auth', 0);
  $mail->Username   = variable_get('manymail_smtp_username', '');
  $mail->Password   = variable_get('manymail_smtp_password', '');

  // Try to connect to the SMTP host.
  try {
    if ($mail->SmtpConnect()) {
      $mail->SmtpClose();
      return TRUE;
    }
  }
  catch (phpmailerException $e) {
    watchdog('ManyMail', 'Caught an exception when trying to validate the SMTP settings: @error', array(
      '@error' => $e->errorMessage(),
    ), WATCHDOG_ERROR);
  }
  catch (Exception $e) {
    watchdog('ManyMail', 'Caught an exception when trying to validate the SMTP settings: @error', array(
      '@error' => $e->errorMessage(),
    ), WATCHDOG_ERROR);
  }

  return FALSE;
}

/**
 * Send mail function.
 *
 * @param object $data
 *   A stdClass with PHPMailer settings that should not be altered
 *   in between batches.
 *   - e-mail data
 *   - smtp settings
 *   - recipients: an array of ManyMailRecipient objects
 *   - meta: other metadata gathered through hook_manymail_mail_meta_alter()
 *   - mlog: the {manymail_log}.mlog for this e-mail.
 *
 * @return array
 *   An array of ManyMailRecipient objects that were successfully mailed to.
 */
function manymail_send_mail($data) {
  $library = libraries_load('phpmailer');

  if (!$library || empty($library['loaded'])) {
    watchdog('ManyMail', 'Could not load PHPMailer library when trying to send e-mails.', NULL, WATCHDOG_ERROR);
    return array();
  }

  // Used to register valid recipients.
  $successful = array();

  $personal_subject = token_scan($data->subject);
  $personal_message = token_scan($data->body);

  $mail = new ManyMailMailer(TRUE);
  $mail->XMailer = 'ManyMail 7.x-1.0-beta3 (http://drupal.org/project/manymail)';

  $mail->IsSMTP();
  $mail->SMTPKeepAlive = TRUE;

  $mail->Host    = $data->host;
  $mail->Port    = $data->port;
  $mail->Timeout = $data->timeout;
  $mail->CharSet = $data->charSet;

  $mail->SMTPSecure = $data->smtpSecure;
  $mail->SMTPAuth   = $data->smtpAuth;
  $mail->Username   = $data->username;
  $mail->Password   = $data->password;

  $mail->AddReplyTo($data->replyTo, $data->replyToName);
  $mail->SetFrom($data->from, $data->fromName);

  if ($sender = variable_get('manymail_options_sender_address')) {
    $mail->AddCustomHeader('Sender: ' . $sender);
  }

  if ($return_path = variable_get('manymail_options_return_path_address')) {
    $mail->AddCustomHeader('Return-Path: ' . $return_path);
  }

  if (!$personal_subject) {
    $mail->Subject = $data->subject;
  }

  if (!$personal_message) {
    $mail->Body = $data->body;
  }

  foreach ($data->recipients as $person) {
    $mail->AddAddress($person->mail, $person->name);

    if ($personal_subject) {
      $mail->Subject = token_replace($data->subject, array('manymail-recipient' => $person));
    }

    if ($personal_message) {
      $mail->Body = token_replace($data->body, array('manymail-recipient' => $person));
    }

    // Pass the mail to hook_manymail_mail_alter implementations.
    drupal_alter('manymail_mail', $mail, $data->meta);

    // If the content type remains text/plain, transform the HTML.
    if ($mail->ContentType == 'text/plain') {
      if (variable_get('manymail_options_html_to_text')) {
        $mail->Subject = drupal_html_to_text($mail->Subject);
        $mail->Body = drupal_html_to_text($mail->Body);
      }
      else {
        $mail->Subject = strip_tags($mail->Subject);
        $mail->Body = strip_tags($mail->Body);
      }
    }

    try {
      if ($mail->Send()) {
        $successful[] = $person;

        if (variable_get('manymail_options_log_per_mail', 1)) {
          // Log per-user if not unchecked in the admin interface.
          db_update('manymail_log_recipients')
            ->fields(array('status' => MANYMAIL_RECIPIENT_STATUS_SUCCESS))
            ->condition('mlog', $data->mlog)
            ->condition('mail', $person->mail)
            ->execute();
        }
      }
      elseif (variable_get('manymail_options_log_per_mail', 1)) {
        // Log per-user if not unchecked in the admin interface.
        db_update('manymail_log_recipients')
          ->fields(array('status' => MANYMAIL_RECIPIENT_STATUS_FAILURE))
          ->condition('mlog', $data->mlog)
          ->condition('mail', $person->mail)
          ->execute();
      }
    }
    catch (phpmailerException $e) {
      watchdog('ManyMail', 'Caught an exception when trying to send an e-mail: @error', array(
        '@error' => $e->errorMessage(),
      ), WATCHDOG_ERROR);
    }
    catch (Exception $e) {
      watchdog('ManyMail', 'Caught an exception when trying to send an e-mail: @error', array(
        '@error' => $e->errorMessage(),
      ), WATCHDOG_ERROR);
    }

    $mail->ClearAddresses();
  }

  return $successful;
}

/**
 * Starts or resumes a batch send action.
 *
 * @param int $mlog
 *   The {manymail_log}.mlog to start or resume.
 * @param array $send_state
 *   The $form_state or unserialized {manymail_log}.send_state to use.
 */
function manymail_setup_mail_batch($mlog, $send_state) {
  // Create a plain object to store all 'static' data of an e-mail.
  $data = new stdClass();

  // Check if a connection to the SMTP host can be made.
  $data->canConnect = manymail_validate_smtp();

  // Store the SMTP information.
  $data->host       = variable_get('manymail_smtp_host', 'localhost');
  $data->port       = variable_get('manymail_smtp_port', 25);
  $data->timeout    = variable_get('manymail_smtp_timeout', 10);
  $data->charSet    = variable_get('manymail_options_charset', 'utf-8');
  $data->smtpSecure = variable_get('manymail_smtp_secure', '');
  $data->smtpAuth   = variable_get('manymail_smtp_auth', 0);
  $data->username   = variable_get('manymail_smtp_username', '');
  $data->password   = variable_get('manymail_smtp_password', '');

  // Store the basic e-mail information.
  $data->from        = $send_state['values']['from'];
  $data->fromName    = $send_state['values']['from_name'];
  $data->replyTo     = (!empty($send_state['values']['reply_to_address']))
    ? $send_state['values']['reply_to_address']
    : $send_state['values']['from'];
  $data->replyToName = (!empty($send_state['values']['reply_to_name']))
    ? $send_state['values']['reply_to_name']
    : $send_state['values']['from_name'];
  $data->subject     = $send_state['values']['subject'];
  $data->body        = $send_state['values']['body'];

  // Add the signature to the body.
  if (!empty($send_state['values']['include_signature'])) {
    $data->body .= "\n\n" . $send_state['values']['signature_example'];
  }

  // Store the $mlog so we can retrieve the right recipients
  // during all the batch iterations.
  $data->mlog = $mlog;

  // Retrieve all recipients that are already attached to this
  // mailing and have not received it yet.
  $exists = db_select('manymail_log_recipients', 'm')
    ->fields('m', array('mlog'))
    ->condition('mlog', $mlog)
    ->condition('status', MANYMAIL_RECIPIENT_STATUS_IN_QUEUE)
    ->execute()
    ->rowCount();

  // If there are any at all, it means this mailing had been started
  // before, but never finished. So set the recipient amount to what's
  // left and resume the mailing.
  //
  // If there aren't any, however, retrieve all valid recipients and
  // attach them to the newly created $mlog.
  if (!$exists) {
    $recipients = manymail_get_recipients($send_state);
    $data->amount = $recipients->attachToMailing($mlog);

    // Redirect back to the main ManyMail page after a new e-mail.
    $redirect = 'manymail';
  }
  else {
    $data->amount = $exists;

    // Redirect back to the ManyMail logs page after a resumed e-mail.
    $redirect = 'admin/config/manymail/logs';
  }

  // Data about the mail that submodules want to retain from the form_state
  // all the way until manymail_send_mail() is called. It can then be used
  // in hook_manymail_mail_alter() to dynamically alter the PHPMailer object.
  $data->meta = module_invoke_all('manymail_mail_meta', $send_state);

  $batch = array(
    'title' => t('Sending e-mails'),
    'progress_message' => t('Testing SMTP settings'),
    'operations' => array(
      array(
        'manymail_send_mail_batch',
        array($data),
      ),
    ),
    'finished' => 'manymail_send_mail_batch_finished',
  );

  batch_set($batch);
  batch_process($redirect, 'batch', NULL);
}

/**
 * Implements set_batch() callback.
 *
 * @see manymail_setup_mail_batch()
 */
function manymail_send_mail_batch($data, &$context) {
  // Set the batch timer to more than one second to avoid the
  // 'optimizing' where Batch API runs several batches within
  // one second's time.
  global $timers;
  timer_stop('batch_processing');
  $timers['batch_processing']['time'] = 9001;

  // Set {manymail_log}.last_activity to the current time.
  db_update('manymail_log')
    ->fields(array(
      'last_activity' => REQUEST_TIME,
    ))
    ->condition('mlog', $data->mlog)
    ->execute();

  // Initiate the Batch API sandbox.
  if (empty($context['sandbox'])) {
    // Halt execution here if the SMTP settings don't add up.
    if (!$data->canConnect) {
      $context['results']['connect'] = FALSE;
      $context['finished'] = 1;
      return;
    }

    $context['sandbox']['offset'] = 0;
    $context['sandbox']['max'] = $data->amount;
    $context['results'] = array(
      'connect' => TRUE,
      'success' => array(),
      'failure' => array(),
    );
  }

  // Retrieve the maximum amount of e-mails that can be sent this run.
  // This can be changed while sending without any problems.
  $limit = variable_get('manymail_options_throttle_amount', 50);

  // Update the front-end message.
  $context['message'] = t('Sending e-mails @low-@high out of @amount.', array(
    '@low' => $context['sandbox']['offset'] + 1,
    '@high' => min($context['sandbox']['max'], $context['sandbox']['offset'] + $limit),
    '@amount' => $data->amount,
  ));

  // Retrieve the stored recipient objects.
  $query = db_select('manymail_log_recipients', 'm')
    ->fields('m', array('recipient'))
    ->condition('mlog', $data->mlog)
    ->condition('status', MANYMAIL_RECIPIENT_STATUS_IN_QUEUE)
    ->range(0, $limit);

  $data->recipients = array();
  foreach ($query->execute() as $record) {
    $data->recipients[] = unserialize($record->recipient);
  }

  // Send the e-mail for the recipients selected above.
  $mail_result = manymail_send_mail($data);

  // Separate the succesful mails from the failed ones.
  $success = array();
  $failure = array();

  foreach ($data->recipients as $recipient) {
    if (in_array($recipient, $mail_result)) {
      $context['results']['success'][] = $recipient;
      $success[] = $recipient->mail;
    }
    else {
      $context['results']['failure'][] = $recipient;
      $failure[] = $recipient->mail;
    }
  }

  // Log per-batch if unchecked in the admin interface.
  if (!variable_get('manymail_options_log_per_mail', 1)) {
    if (!empty($success)) {
      db_update('manymail_log_recipients')
        ->fields(array('status' => MANYMAIL_RECIPIENT_STATUS_SUCCESS))
        ->condition('mail', $success, 'IN')
        ->execute();
    }

    if (!empty($failure)) {
      db_update('manymail_log_recipients')
        ->fields(array('status' => MANYMAIL_RECIPIENT_STATUS_FAILURE))
        ->condition('mail', $failure, 'IN')
        ->execute();
    }
  }

  // Update the progress bar.
  $context['sandbox']['offset'] += $limit;
  if ($context['sandbox']['offset'] != $context['sandbox']['max']) {
    $context['finished'] = $context['sandbox']['offset'] / $context['sandbox']['max'];

    // Log the mailing as successful when progress reaches 100%.
    if ($context['finished'] >= 1) {
      db_update('manymail_log')
        ->fields(array('completed' => 1))
        ->condition('mlog', $data->mlog)
        ->execute();
    }
  }
}

/**
 * Implements set_batch() finished callback.
 *
 * @see manymail_send_mail_batch()
 */
function manymail_send_mail_batch_finished($success, $results, $operations) {
  if ($success) {
    if (!$results['connect']) {
      drupal_set_message(t('Failed to connect to the SMTP host.<br />Please contact an administrator for more information.'), 'error');
      watchdog('ManyMail', 'Aborted e-mail because no connection could be made to the SMTP host.', NULL, WATCHDOG_WARNING);

      // There were no send attempts if the SMTP connection failed,
      // so exit here.
      return;
    }

    if ($results['success']) {
      $success = array();

      foreach ($results['success'] as $result) {
        $success[] = "{$result->name} <{$result->mail}>";
      }

      drupal_set_message(format_plural(count($results['success']),
        'Succesfully sent e-mail to one person.',
        'Succesfully sent e-mail to @count people.'
      ));
    }

    if ($results['failure']) {
      $failure = array();

      foreach ($results['failure'] as $result) {
        $failure[] = "{$result->name} <{$result->mail}>";
      }

      drupal_set_message(format_plural(count($results['failure']),
        'Failed to send e-mail to one person.<br />Please contact an administrator for more information.',
        'Failed to send e-mail to @count people.<br />Please contact an administrator for more information.'
      ), 'warning');
    }
  }
  else {
    drupal_set_message(t('ManyMail finished mailing with an error.<br />Please contact an administrator for more information.'), 'error');
  }
}

/**
 * Implements hook_help().
 */
function manymail_help($path, $arg) {
  switch ($path) {
    case 'admin/help#manymail':
      return t('<p>Allows you to e-mail roles, views, specific users or any combination of the former.</p>');
      break;
  }
}

/**
 * Implements hook_permission().
 */
function manymail_permission() {
  $perm = array(
    'manymail admin' => array(
      'title' => t('Administer the ManyMail modules and submodules'),
    ),
    'manymail send all' => array(
      'title' => t('Send e-mail to all users'),
    ),
    'manymail send roles' => array(
      'title' => t('Send e-mail to user roles'),
    ),
  );

  if (variable_get('manymail_allowed_roles_override', 1)) {
    $perm['manymail override roles'] = array(
      'title' => t('Override preset recipient roles'),
    );
  }

  return $perm;
}

/**
 * Custom access callback.
 *
 * Checks for multiple permissions.
 *
 * @param array|string $permissions
 *   The name(s) of the permissions to check for
 *
 * @return bool
 *   Whether all permission checks are fulfilled
 */
function manymail_access_and($permissions) {
  if (!is_array($permissions)) {
    $permissions = array($permissions);
  }

  foreach ($permissions as $permission) {
    if (!user_access($permission)) {
      return FALSE;
    }
  }

  return TRUE;
}

/**
 * Custom access callback.
 *
 * Checks for any of the given permissions.
 *
 * @param array|string $permissions
 *   The name(s) of the permissions to check for
 *
 * @return bool
 *   Whether any of permission checks is fulfilled
 */
function manymail_access_or($permissions) {
  if (!is_array($permissions)) {
    $permissions = array($permissions);
  }

  foreach ($permissions as $permission) {
    if (user_access($permission)) {
      return TRUE;
    }
  }

  return FALSE;
}

/**
 * Implements hook_forms().
 */
function manymail_forms($form_id, $args) {
  $forms['manymail_send_all_form']['callback'] = 'manymail_send_form';
  $forms['manymail_send_role_form']['callback'] = 'manymail_send_form';

  return $forms;
}

/**
 * Implements hook_menu().
 */
function manymail_menu() {
  $items = array();

  $items['manymail'] = array(
    'title' => 'ManyMail',
    'description' => 'Send e-mails with the ManyMail module.',
    'page callback' => '_manymail_page',
    'access callback' => 'manymail_access_or',
    'access arguments' => array(array('manymail send all', 'manymail send roles')),
    'file' => 'includes/manymail.pages.inc',
    'type' => MENU_NORMAL_ITEM,
  );

  $items['manymail/info'] = array(
    'title' => 'Information',
    'description' => 'Important information about using ManyMail.',
    'weight' => 1,
    'type' => MENU_DEFAULT_LOCAL_TASK,
  );

  $items['manymail/all'] = array(
    'title' => 'Mail all users',
    'description' => 'Send an e-mail to all users.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('manymail_send_all_form'),
    'access arguments' => array('manymail send all'),
    'file' => 'includes/manymail.forms.inc',
    'weight' => 2,
    'type' => MENU_LOCAL_TASK,
  );

  $items['manymail/role'] = array(
    'title' => 'Mail user roles',
    'description' => 'Send an e-mail to one or more user roles.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('manymail_send_role_form'),
    'access arguments' => array('manymail send roles'),
    'file' => 'includes/manymail.forms.inc',
    'weight' => 3,
    'type' => MENU_LOCAL_TASK,
  );

  $items['admin/config/manymail'] = array(
    'title' => 'ManyMail',
    'description' => 'Configure the ManyMail module.',
    'page callback' => 'system_admin_menu_block_page',
    'access arguments' => array('manymail admin'),
    'file' => 'system.admin.inc',
    'file path' => 'modules/system',
    'position' => 'right',
    'weight' => -19,
    'type' => MENU_NORMAL_ITEM,
  );

  $items['admin/config/manymail/config'] = array(
    'title' => 'General configuration',
    'description' => 'Configure mail defaults, SMTP server settings and other technical details.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('manymail_config_options_form'),
    'access arguments' => array('manymail admin'),
    'file' => 'includes/manymail.admin.inc',
    'weight' => 1,
    'type' => MENU_NORMAL_ITEM,
  );

  $items['admin/config/manymail/config/options'] = array(
    'title' => 'Options',
    'description' => 'Configure ManyMail.',
    'weight' => 1,
    'type' => MENU_DEFAULT_LOCAL_TASK,
  );

  $items['admin/config/manymail/config/defaults'] = array(
    'title' => 'Content defaults',
    'description' => 'Configure default mail content.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('manymail_config_defaults_form'),
    'access arguments' => array('manymail admin'),
    'file' => 'includes/manymail.admin.inc',
    'weight' => 2,
    'type' => MENU_LOCAL_TASK,
  );

  $items['admin/config/manymail/config/headers'] = array(
    'title' => 'Header defaults',
    'description' => 'Configure default mail headers.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('manymail_config_headers_form'),
    'access arguments' => array('manymail admin'),
    'file' => 'includes/manymail.admin.inc',
    'weight' => 3,
    'type' => MENU_LOCAL_TASK,
  );

  $items['admin/config/manymail/config/smtp'] = array(
    'title' => 'SMTP settings',
    'description' => 'Configure SMTP server settings.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('manymail_config_smtp_form'),
    'access arguments' => array('manymail admin'),
    'file' => 'includes/manymail.admin.inc',
    'weight' => 4,
    'type' => MENU_LOCAL_TASK,
  );

  $items['admin/config/manymail/targets'] = array(
    'title' => 'Mass mail targets',
    'description' => 'Define to whom e-mails may be sent.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('manymail_targets_roles_form'),
    'access arguments' => array('manymail admin'),
    'file' => 'includes/manymail.admin.inc',
    'weight' => 2,
    'type' => MENU_NORMAL_ITEM,
  );

  $items['admin/config/manymail/targets/roles'] = array(
    'title' => 'Recipient roles',
    'description' => 'Define which roles e-mails may be sent to.',
    'weight' => 1,
    'type' => MENU_DEFAULT_LOCAL_TASK,
  );

  $items['admin/config/manymail/logs'] = array(
    'title' => 'E-mail logs and actions',
    'description' => 'View and manage sent e-mails.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('manymail_logs_overview_form'),
    'access arguments' => array('manymail admin'),
    'file' => 'includes/manymail.admin.inc',
    'weight' => 3,
    'type' => MENU_NORMAL_ITEM,
  );

  $items['admin/config/manymail/logs/%/view'] = array(
    'title' => 'View e-mail',
    'description' => 'View a sent e-mail.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('manymail_logs_view_mail_form', 4),
    'access arguments' => array('manymail admin'),
    'file' => 'includes/manymail.admin.inc',
    'type' => MENU_CALLBACK,
  );

  $items['admin/config/manymail/logs/%/recipients'] = array(
    'title' => 'View recipients',
    'description' => 'View the recipients for a sent e-mail.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('manymail_logs_view_mail_recipients_form', 4),
    'access arguments' => array('manymail admin'),
    'file' => 'includes/manymail.admin.inc',
    'type' => MENU_CALLBACK,
  );

  $items['admin/config/manymail/logs/%/resume'] = array(
    'title' => 'Resume e-mail',
    'description' => 'Resume sending e-mails.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('manymail_logs_view_mail_resume_form', 4),
    'access arguments' => array('manymail admin'),
    'file' => 'includes/manymail.admin.inc',
    'type' => MENU_CALLBACK,
  );

  return $items;
}

/**
 * Implements hook_form_FORM_ID_alter().
 *
 * @ingroup forms
 */
function manymail_form_manymail_send_role_form_alter(&$form, &$form_state, $form_id) {
  $admin = user_access('manymail override roles');

  // All roles except 'anonymous' and 'authenticated user'.
  $all_roles = user_roles(TRUE);
  unset($all_roles[DRUPAL_AUTHENTICATED_RID]);

  // Allow all roles if admins can override config page settings.
  // Otherwise retrieve the allowed RIDs from config page settings.
  $roles = (variable_get('manymail_allowed_roles_override', 1) && $admin)
    ? $all_roles
    : array_filter(variable_get('manymail_allowed_roles', array()));

  if ($roles) {
    if (array_key_exists(DRUPAL_AUTHENTICATED_RID, $roles)) {
      // If 'authenticated user' is set, allow all roles.
      $roles = $all_roles;
    }
    else {
      // Otherwise attach the correct role names to the allowed RIDs.
      $roles = array_intersect_key($all_roles, $roles);
    }

    $form['recipient'] = array(
      '#type' => 'fieldset',
      '#title' => t('Recipients'),
      '#weight' => 1,
      '#collapsible' => TRUE,
      '#collapsed' => FALSE,
    );

    array_walk($roles, 'check_plain');
    $form['recipient']['roles'] = array(
      '#type' => 'checkboxes',
      '#title' => 'Recipients',
      '#title_display' => 'invisible',
      '#options' => $roles,
      '#description' => t('The user roles to send this e-mail to.<br /><strong>Be careful what you select here: You may inadvertently e-mail a lot of people.</strong>'),
      '#required' => TRUE,
    );
  }
  else {
    $form = array(
      'error_no_roles' => array(
        '#prefix' => '<p>',
        '#suffix' => '</p>',
        '#markup' => t('There seem to be no roles configured for you to mail to.'),
      ),
    );
  }
}

/**
 * Implements hook_libraries_info().
 */
function manymail_libraries_info() {
  $libraries['phpmailer'] = array(
    'name' => 'PHPMailer library',
    'vendor url' => 'http://phpmailer.worxware.com/',
    'download url' => 'http://code.google.com/a/apache-extras.org/p/phpmailer/downloads/list',
    'version arguments' => array(
      'file' => 'changelog.txt',
      'pattern' => '/Version ([0-9.]+)/',
      'lines' => 10,
    ),
    'files' => array(
      'php' => array(
        'class.phpmailer.php',
        'class.smtp.php',
      ),
    ),
    'callbacks' => array(
      'post-detect' => array(
        'manymail_libraries_info_callback',
      ),
    ),
  );

  return $libraries;
}

/**
 * Post-detect callback for hook_libraries_info().
 *
 * Checks PHPMailer version support. (Minimum supported: 5.1)
 */
function manymail_libraries_info_callback(&$library, $version = NULL, $variant = NULL) {
  if (!is_null($library['version'])) {
    $library['version supported'] = version_compare($library['version'], '5.1', '>=');
  }
  else {
    $library['version supported'] = FALSE;
  }
}
