static function email_normal() { global $USER, $CFG, $PERF; $exceptioncount = 0; // Obtain information about all mails that are due for sending mtrace('Email processing:'); $before = microtime(true); if (!empty($PERF->dbqueries)) { $beforequeries = $PERF->dbqueries; } mtrace('Initial query: ', ''); $list = new forum_mail_list(true); mtrace(round(microtime(true) - $before, 1) . 's'); // Cumulative time spent actually sending emails $mailtime = 0; // Forum loop while ($list->next_forum($forum, $cm, $context, $course)) { self::debug("DEBUG: Forum " . $forum->get_name() . " on course {$course->shortname} " . "(cmid {$cm->id} contextid {$context->id})"); // Set up course details course_setup($course); // Count posts and emails just for logging $postcount = 0; $emailcount = 0; // Get subscribers to forum try { $subscribers = $forum->get_subscribers(); self::debug("DEBUG: Subscribers before filter " . count($subscribers), ''); self::email_filter_subscribers($course, $cm, $forum, $subscribers, false); self::debug(", after " . count($subscribers)); if (count($subscribers) == 0) { continue; } } catch (forum_exception $e) { // If an error occurs while getting subscribers, continue // to next forum mtrace(' Exception while getting subscribers for forum ' . $forum->get_id()); mtrace($e->__toString()); continue; } while ($list->next_discussion($discussion)) { self::debug("DEBUG: Discussion " . $discussion->get_subject() . ' (' . $discussion->get_id() . ')'); // Evaluate list of users based on this discussion (which holds // group info). Organise list by language, timezone and email // type. $langusers = array(); foreach ($subscribers as $subscriber) { // Conditions for each subscriber to get this discussion if (self::subscriber_receives_discussion($forum, $discussion, $subscriber)) { $oldlang = $USER->lang; $USER->lang = $subscriber->lang; $lang = current_language(); $USER->lang = $oldlang; $langusers[$lang][$subscriber->timezone][$subscriber->emailtype][$subscriber->id] = $subscriber; } } if (self::debug()) { $debugcount = 0; foreach ($langusers as $lang => $tzusers) { foreach ($tzusers as $timezone => $typeusers) { foreach ($typeusers as $emailtype => $users) { mtrace("DEBUG: Subscribers for lang [{$lang}] " . "tz [{$timezone}] type [{$emailtype}]: " . count($users)); $debugcount += count($users); } } } mtrace("DEBUG: Total discussion subscribers: {$debugcount}"); } while ($list->next_post($post, $inreplyto)) { if (self::debug()) { mtrace("DEBUG: Post " . $post->get_id(), ''); $debugcount = $emailcount; } try { $from = $post->get_user(); // These loops are intended so that we generate identical // emails once only, and can then send them in batches foreach ($langusers as $lang => $tzusers) { foreach ($tzusers as $timezone => $typeusers) { foreach ($typeusers as $emailtype => $users) { // We get both plaintext and html versions. // The html version will be blank if set to // plain text mode. $post->build_email($inreplyto, $subject, $plaintext, $html, $emailtype & 1, $emailtype & 2, $emailtype & 4, $lang, $timezone); $beforemail = microtime(true); if ($CFG->forumng_usebcc) { // Use BCC to send all emails at once $emailcount += self::email_send_bcc($users, $from, $subject, $html, $plaintext, "post " . $post->get_id(), $emailtype & 1, $emailtype & 4); } else { // Loop through subscribers, sending mail to // each one foreach ($users as $mailto) { self::email_send($mailto, $from, $subject, $plaintext, $html); $emailcount++; } } $mailtime += microtime(true) - $beforemail; } } } // Reset exception count; while some posts are // successful, we'll keep trying to send them out $exceptioncount = 0; } catch (exception $e) { mtrace(' Exception while sending post ' . $post->get_id()); mtrace($e->__toString()); $exceptioncount++; if ($exceptioncount > 100) { throw new forum_exception('Too many post exceptions in a row, aborting'); } } $postcount++; if (self::debug()) { mtrace(", sent " . ($emailcount - $debugcount) . " emails"); } } } // Trace and log information $counts = "{$postcount} posts ({$emailcount} emails) to " . count($subscribers) . " subscribers"; mtrace("Forum " . $forum->get_name() . ": sent {$counts}"); add_to_log($forum->get_course_id(), 'forumng', 'mail ok', 'view.php?' . $forum->get_link_params(forum::PARAM_PLAIN), $counts); } $queryinfo = ''; if (!empty($PERF->dbqueries)) { $queryinfo = ', ' . ($PERF->dbqueries - $beforequeries) . ' queries'; } $totalpostcount = $list->get_post_count_so_far(); $totaltime = microtime(true) - $before; mtrace("Email processing ({$totalpostcount} new posts) complete, total: " . round($totaltime, 1) . 's (mail sending ' . round($mailtime, 1) . 's = ' . round(100.0 * $mailtime / $totaltime, 1) . '%)' . $queryinfo); }
protected function get_safety_net($time) { // The digest safety net is 24 hours earlier because digest posts may // be delayed by 24 hours. return parent::get_safety_net($time) - 24 * 3600; }