示例#1
0
    /**
     * Display the mail queue...
     *
     * @uses ManageMail template
     */
    public function action_browse()
    {
        global $scripturl, $context, $txt;
        require_once SUBSDIR . '/Mail.subs.php';
        loadTemplate('ManageMail');
        // First, are we deleting something from the queue?
        if (isset($_REQUEST['delete'])) {
            checkSession('post');
            deleteMailQueueItems($_REQUEST['delete']);
        }
        // Fetch the number of items in the current queue
        $status = list_MailQueueStatus();
        $context['oldest_mail'] = empty($status['mailOldest']) ? $txt['mailqueue_oldest_not_available'] : time_since(time() - $status['mailOldest']);
        $context['mail_queue_size'] = comma_format($status['mailQueueSize']);
        // Build our display list
        $listOptions = array('id' => 'mail_queue', 'title' => $txt['mailqueue_browse'], 'items_per_page' => 20, 'base_href' => $scripturl . '?action=admin;area=mailqueue', 'default_sort_col' => 'age', 'no_items_label' => $txt['mailqueue_no_items'], 'get_items' => array('function' => 'list_getMailQueue'), 'get_count' => array('function' => 'list_getMailQueueSize'), 'columns' => array('subject' => array('header' => array('value' => $txt['mailqueue_subject']), 'data' => array('function' => create_function('$rowData', '
							return Util::shorten_text(Util::htmlspecialchars($rowData[\'subject\'], 50));
						')), 'sort' => array('default' => 'subject', 'reverse' => 'subject DESC')), 'recipient' => array('header' => array('value' => $txt['mailqueue_recipient']), 'data' => array('sprintf' => array('format' => '<a href="mailto:%1$s">%1$s</a>', 'params' => array('recipient' => true))), 'sort' => array('default' => 'recipient', 'reverse' => 'recipient DESC')), 'priority' => array('header' => array('value' => $txt['mailqueue_priority'], 'class' => 'centertext'), 'data' => array('function' => create_function('$rowData', '
							global $txt;

							// We probably have a text label with your priority.
							$txtKey = sprintf(\'mq_mpriority_%1$s\', $rowData[\'priority\']);

							// But if not, revert to priority 0.
							return isset($txt[$txtKey]) ? $txt[$txtKey] : $txt[\'mq_mpriority_1\'];
						'), 'class' => 'centertext'), 'sort' => array('default' => 'priority', 'reverse' => 'priority DESC')), 'age' => array('header' => array('value' => $txt['mailqueue_age']), 'data' => array('function' => create_function('$rowData', '
							return time_since(time() - $rowData[\'time_sent\']);
						')), 'sort' => array('default' => 'time_sent', 'reverse' => 'time_sent DESC')), 'check' => array('header' => array('value' => '<input type="checkbox" onclick="invertAll(this, this.form);" class="input_check" />'), 'data' => array('function' => create_function('$rowData', '
							return \'<input type="checkbox" name="delete[]" value="\' . $rowData[\'id_mail\'] . \'" class="input_check" />\';
						')))), 'form' => array('href' => $scripturl . '?action=admin;area=mailqueue', 'include_start' => true, 'include_sort' => true), 'additional_rows' => array(array('position' => 'bottom_of_list', 'class' => 'submitbutton', 'value' => '
						<input type="submit" name="delete_redirects" value="' . $txt['quickmod_delete_selected'] . '" onclick="return confirm(\'' . $txt['quickmod_confirm'] . '\');" class="right_submit" />
						<a class="linkbutton" href="' . $scripturl . '?action=admin;area=mailqueue;sa=clear;' . $context['session_var'] . '=' . $context['session_id'] . '" onclick="return confirm(\'' . $txt['mailqueue_clear_list_warning'] . '\');">' . $txt['mailqueue_clear_list'] . '</a> ')));
        require_once SUBSDIR . '/GenericList.class.php';
        createList($listOptions);
    }
示例#2
0
/**
 * Sends a group of emails from the mail queue.
 *
 * - Allows a batch of emails to be released every 5 to 10 seconds (based on per period limits)
 * - If batch size is not set, will determine a size such that it sends in 1/2 the period (buffer)
 *
 * @package Mail
 * @param int|false $batch_size = false the number to send each loop
 * @param boolean $override_limit = false bypassing our limit flaf
 * @param boolean $force_send = false
 * @return boolean
 */
function reduceMailQueue($batch_size = false, $override_limit = false, $force_send = false)
{
    global $modSettings, $context, $webmaster_email, $scripturl;
    // Do we have another script to send out the queue?
    if (!empty($modSettings['mail_queue_use_cron']) && empty($force_send)) {
        return false;
    }
    // How many emails can we send each time we are called in a period
    if (!$batch_size) {
        // Batch size has been set in the ACP, use it
        if (!empty($modSettings['mail_batch_size'])) {
            $batch_size = $modSettings['mail_batch_size'];
        } elseif (empty($modSettings['mail_period_limit'])) {
            $batch_size = 5;
        } else {
            // Based on the number of times we will potentially be called each minute
            $delay = !empty($modSettings['mail_queue_delay']) ? $modSettings['mail_queue_delay'] : (!empty($modSettings['mail_period_limit']) && $modSettings['mail_period_limit'] <= 5 ? 10 : 5);
            $batch_size = ceil($modSettings['mail_period_limit'] / ceil(60 / $delay));
            $batch_size = $batch_size == 1 && $modSettings['mail_period_limit'] > 1 ? 2 : $batch_size;
        }
    }
    // If we came with a timestamp, and that doesn't match the next event, then someone else has beaten us.
    if (isset($_GET['ts']) && $_GET['ts'] != $modSettings['mail_next_send'] && empty($force_send)) {
        return false;
    }
    // Prepare to send each email, and log that for future proof.
    require_once SUBSDIR . '/Maillist.subs.php';
    // Set the delay for the next sending
    if (!$override_limit) {
        // Update next send time for our mail queue, if there was something to update. Otherwise bail out :P
        $delay = updateNextSendTime();
        if ($delay === false) {
            return false;
        }
        $modSettings['mail_next_send'] = time() + $delay;
    }
    // If we're not overriding, do we have quota left in this mail period limit?
    if (!$override_limit && !empty($modSettings['mail_period_limit'])) {
        // See if we have quota left to send another batch_size this minute or if we have to wait
        list($mail_time, $mail_number) = isset($modSettings['mail_recent']) ? explode('|', $modSettings['mail_recent']) : array(0, 0);
        // Nothing worth noting...
        if (empty($mail_number) || $mail_time < time() - 60) {
            $mail_time = time();
            $mail_number = $batch_size;
        } elseif ($mail_number < $modSettings['mail_period_limit']) {
            // If this is likely one of the last cycles for this period, then send any remaining quota
            if ($mail_time - (time() - 60) < $delay * 2) {
                $batch_size = $modSettings['mail_period_limit'] - $mail_number;
            } elseif ($mail_number + $batch_size > $modSettings['mail_period_limit']) {
                $batch_size = $modSettings['mail_period_limit'] - $mail_number;
            }
            $mail_number += $batch_size;
        } else {
            return false;
        }
        // Reflect that we're about to send some, do it now to be safe.
        updateSettings(array('mail_recent' => $mail_time . '|' . $mail_number));
    }
    // Now we know how many we're sending, let's send them.
    list($ids, $emails) = emailsInfo($batch_size);
    // Delete, delete, delete!!!
    if (!empty($ids)) {
        deleteMailQueueItems($ids);
    }
    // Don't believe we have any left after this batch?
    if (count($ids) < $batch_size) {
        resetNextSendTime();
    }
    if (empty($ids)) {
        return false;
    }
    // We have some to send, lets send them!
    $sent = array();
    $failed_emails = array();
    // Use sendmail or SMTP
    $use_sendmail = empty($modSettings['mail_type']) || $modSettings['smtp_host'] == '';
    // Line breaks need to be \r\n only in windows or for SMTP.
    $line_break = !empty($context['server']['is_windows']) || !$use_sendmail ? "\r\n" : "\n";
    foreach ($emails as $key => $email) {
        // Use the right mail resource
        if ($use_sendmail) {
            $email['subject'] = strtr($email['subject'], array("\r" => '', "\n" => ''));
            if (!empty($modSettings['mail_strip_carriage'])) {
                $email['body'] = strtr($email['body'], array("\r" => ''));
                $email['headers'] = strtr($email['headers'], array("\r" => ''));
            }
            $need_break = substr($email['headers'], -1) === "\n" || substr($email['headers'], -1) === "\r" ? false : true;
            // Create our unique reply to email header if this message needs one
            $unq_id = '';
            $unq_head = '';
            if (!empty($modSettings['maillist_enabled']) && $email['message_id'] !== null && strpos($email['headers'], 'List-Id: <') !== false) {
                $unq_head = md5($scripturl . microtime() . rand()) . '-' . $email['message_id'];
                $encoded_unq_head = base64_encode($line_break . $line_break . '[' . $unq_head . ']' . $line_break);
                $unq_id = ($need_break ? $line_break : '') . 'Message-ID: <' . $unq_head . strstr(empty($modSettings['maillist_mail_from']) ? $webmaster_email : $modSettings['maillist_mail_from'], '@') . '>';
                $email['body_fail'] = $email['body'];
                $email['body'] = mail_insert_key($email['body'], $unq_head, $encoded_unq_head, $line_break);
            } elseif ($email['message_id'] !== null && empty($modSettings['mail_no_message_id'])) {
                $unq_id = ($need_break ? $line_break : '') . 'Message-ID: <' . md5($scripturl . microtime()) . '-' . $email['message_id'] . strstr(empty($modSettings['maillist_mail_from']) ? $webmaster_email : $modSettings['maillist_mail_from'], '@') . '>';
            }
            // No point logging a specific error here, as we have no language. PHP error is helpful anyway...
            $result = mail(strtr($email['to'], array("\r" => '', "\n" => '')), $email['subject'], $email['body'], $email['headers'] . $unq_id);
            // If it sent, keep a record so we can save it in our allowed to reply log
            if (!empty($unq_head) && $result) {
                $sent[] = array($unq_head, time(), $email['to']);
            }
            // Track total emails sent
            if ($result && !empty($modSettings['trackStats'])) {
                trackStats(array('email' => '+'));
            }
            // Try to stop a timeout, this would be bad...
            @set_time_limit(300);
            if (function_exists('apache_reset_timeout')) {
                @apache_reset_timeout();
            }
        } else {
            $result = smtp_mail(array($email['to']), $email['subject'], $email['body'], $email['send_html'] ? $email['headers'] : 'Mime-Version: 1.0' . "\r\n" . $email['headers'], $email['priority'], $email['message_id']);
        }
        // Hopefully it sent?
        if (!$result) {
            $failed_emails[] = array(time(), $email['to'], $email['body_fail'], $email['subject'], $email['headers'], $email['send_html'], $email['priority'], $email['private'], $email['message_id']);
        }
    }
    // Clear out the stat cache.
    trackStats();
    // Log each of the sent emails.
    if (!empty($sent)) {
        log_email($sent);
    }
    // Any emails that didn't send?
    if (!empty($failed_emails)) {
        // If it failed, add it back to the queue
        updateFailedQueue($failed_emails);
        return false;
    } elseif (!empty($modSettings['mail_failed_attempts'])) {
        updateSuccessQueue();
    }
    // Had something to send...
    return true;
}