0

I'd like to make all of my partners in my company receive daily metrics like new users, pageviews everyday, I wrote a custom module using hook_cron.

This is my code:

function custom_metrics_cron() {
  global $language;

  $default = strtotime('-24 Hours', REQUEST_TIME);
  $last_send  = variable_get('custom_metrics_daily_last_send', $default);
  $only_after = strtotime('+24 Hours', $last_send);

  if (REQUEST_TIME >= $only_after) {
    variable_set('custom_metrics_daily_last_send', REQUEST_TIME);
    drupal_mail('custom_metrics', 'daily', MAIL_RECIEVERS, $language);
  }
}

function custom_metrics_mail($key, &$message, $params) {
  $date = date('m-d-Y', strtotime('-1 Day', time()));
  $metrics = custom_metrics_get_metrics();
  switch($key) {
    case 'daily':
      $message['subject'] = t('Daily Metrics: !date', array('!date' => $date));
      $message['headers']['Content-Type'] = 'text/html; charset=UTF-8; format=flowed';
      $message['body'][] = custom_metrics_get_metrics();
      break;
  }
}

It works okay, I get the mails everyday, but the problem is I get not only one mail, I already set the variable and make it send ONE mail every 24 hours but I still get 4~5 mails every 24 hours. Can anyone tell me where does I do wrong?

2 Answers 2

5

D7, I struggled a lot, this is what i did, works perfect, following modules are required: Job shcheduler, Rules, and optionally Rules switch user, i use core cron; make a custom module 'MYMODULE' and place this code:

   /**
   * Implements hook_cron_job_scheduler_info().
   *
   * Do not forget to run job_scheduler_rebuild_all() on any changes here,
   * see https://drupal.org/comment/8406919#comment-8406919
   */
  // * Implements hook_cron()
  function MYMODULE_cron_job_scheduler_info() {
    $schedulers = array();
  //add as many scheduled jobs as needed.
  //$schedulers['daily_email_6_am'] = array(...);
    $schedulers['daily_email_7_am'] = array(
      'worker callback' => 'send_emails_action_7_am',
      'jobs' => array(
        array(
          'type' => 'notification',
          'id' => 1,
          'crontab' => '0 7 * * 1-6', // 7am, mon-sat
          //'crontab' => '0 * * * *', // once a day, midnigth
          //'crontab' => '*/1 * * * *', // once every minute, dev settings
          'periodic' => TRUE
        ),
      )
    );
    return $schedulers;
  }
  function send_emails_action_7_am() {
    // Do stuff.
    rules_invoke_component('rules_send_emails_component_7_am');
}

now you have a cron based scheduled job at 7 am from monday to saturday that executes a rule-component machine name: 'send_emails_component_7_am', be carefull, function calls: rules_MACHINENAME of component, built rule component to send your emails, i usually i built my emails with views rules module and have a great control to built email-body-value. see this answer, and this one also could be many emails, benefits of using views-rules as you can loop by views all users and filter them as needed and inject to rules whatever you imagine. emails are not 'duplicated', only 1 mail per user.

cron run as anonymous user, so, only if you have some content_access restrictions your emails won't be sent, here comes the benefit of 'Rules switch user', do pay attention with this module settings as this img suggest, i hope this helps someone. enter image description here

-1

One of the safest general solutions is Elysia CRON module - when using it you can write your hook_cron without any checks, and set how often it should be really called in Elysia Cron GUI. That way you only need to code module-specific logic in your module, saving time. And if you will ever need to send mail twice a day, it will save you the need of updating module.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.