~nixin/eventum/eventum-es

« back to all changes in this revision

Viewing changes to lib/eventum/class.mail_queue.php

  • Committer: Elan Ruusamäe
  • Date: 2013-08-26 13:07:42 UTC
  • Revision ID: glen@delfi.ee-20130826130742-uqkz4vneqnwiw9nj
Sending Email Enhancements (bug: LP#1195856)

This patch will make two changes.

1. Remove the requirement to have a limit when sending outbound email
   (you can set it to false for no limit).

2. Add a new flag that will merge outbound emails to different
   recipients, that have the same contents, into one email with multiple
   recipients. These changes are centralized into the sending cron job
   procedure so they require no DDL changes or other changes to core
   parts of the application.

Show diffs side-by-side

added added

removed removed

Lines of Context:
151
151
     * @access  public
152
152
     * @param   string $status The status of the messages that need to be sent
153
153
     * @param   integer $limit The limit of emails that we should send at one time
 
154
     * @param   boolean $merge Whether or not to send one merged email for multiple entries with the same status and type.
154
155
     */
155
 
    function send($status, $limit)
 
156
    function send($status, $limit = false, $merge = false)
156
157
    {
157
 
        // foreach email, we use retrieve one email details a time to avoid
158
 
        // running out of memory.
 
158
        if ($merge !== false) {
 
159
            foreach (self::_getMergedList($status, $limit) as $maq_ids) {
 
160
                $emails = self::_getEntries($maq_ids);
 
161
                $recipients = array();
 
162
 
 
163
                foreach ($emails as $email) {
 
164
                    $recipients[] = $email['recipient'];
 
165
                }
 
166
 
 
167
                $email = $emails[0];
 
168
                $recipients = implode(',', $recipients);
 
169
                $message = $email['headers'] . "\r\n\r\n" . $email['body'];
 
170
                $structure = Mime_Helper::decode($message, false, false);
 
171
                $headers = $structure->headers;
 
172
 
 
173
                $headers['to'] = $recipients;
 
174
                $headers = Mime_Helper::encodeHeaders($headers);
 
175
 
 
176
                $res = Mail_Helper::prepareHeaders($headers);
 
177
                if (PEAR::isError($res)) {
 
178
                    Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__);
 
179
                    return $res;
 
180
                }
 
181
 
 
182
                list(,$text_headers) = $res;
 
183
                $result = self::_sendEmail($recipients, $text_headers, $email['body'], $status);
 
184
 
 
185
                if (PEAR::isError($result)) {
 
186
                    $maq_id = implode(',', $maq_ids);
 
187
                    $details = $result->getMessage() . "/" . $result->getDebugInfo();
 
188
                    echo "Mail_Queue: issue #{$email['maq_iss_id']}: Can't send merged mail $maq_id: $details\n";
 
189
 
 
190
                    foreach ($emails as $email) {
 
191
                        self::_saveStatusLog($email['id'], 'error', $details);
 
192
                    }
 
193
 
 
194
                    continue;
 
195
                }
 
196
 
 
197
                foreach ($emails as $email) {
 
198
                    self::_saveStatusLog($email['id'], 'sent', '');
 
199
 
 
200
                    if ($email['save_copy']) {
 
201
                        Mail_Helper::saveOutgoingEmailCopy($email);
 
202
                    }
 
203
                }
 
204
            }
 
205
        }
 
206
 
159
207
        foreach (self::_getList($status, $limit) as $maq_id) {
160
208
            $email = self::_getEntry($maq_id);
161
 
            if (empty($email)) {
162
 
                // skip on error
163
 
                continue;
164
 
            }
165
 
 
166
 
            $current_status = $status;
167
 
            if ($email['maq_type'] == 'error') {
168
 
                $current_status = 'error';
169
 
            }
170
 
            $result = self::_sendEmail($email['recipient'], $email['headers'], $email['body'], $current_status);
 
209
            $result = self::_sendEmail($email['recipient'], $email['headers'], $email['body'], $status);
171
210
 
172
211
            if (PEAR::isError($result)) {
173
212
                $details = $result->getMessage() . "/" . $result->getDebugInfo();
178
217
 
179
218
            self::_saveStatusLog($email['id'], 'sent', '');
180
219
            if ($email['save_copy']) {
181
 
                // send a copy of this email to eventum_sent@
182
220
                Mail_Helper::saveOutgoingEmailCopy($email);
183
221
            }
184
222
        }
264
302
     * @param   integer $limit The limit on the number of messages that need to be returned
265
303
     * @return  array The list of queued email messages
266
304
     */
267
 
    private function _getList($status, $limit = 50)
 
305
    private function _getList($status, $limit = false)
268
306
    {
269
307
        $sql = "SELECT
270
308
                    maq_id id
273
311
                 WHERE
274
312
                    maq_status='$status'
275
313
                 ORDER BY
276
 
                    maq_id ASC
277
 
                 LIMIT
278
 
                    0, $limit";
 
314
                    maq_id ASC";
 
315
 
 
316
        if ($limit !== false) {
 
317
            $sql .= " LIMIT 0, $limit";
 
318
        }
 
319
 
279
320
        $res = DB_Helper::getInstance()->getCol($sql);
280
321
        if (PEAR::isError($res)) {
281
322
            Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__);
286
327
    }
287
328
 
288
329
    /**
 
330
     * Retrieves the list of queued email messages ids, given a status, merged together by type
 
331
     *
 
332
     * @access  private
 
333
     * @param   string $status The status of the messages
 
334
     * @param   integer $limit The limit on the number of messages that need to be returned
 
335
     * @return  array The list of queued email messages
 
336
     */
 
337
    private function _getMergedList($status, $limit = false)
 
338
    {
 
339
        $sql = "SELECT
 
340
                    GROUP_CONCAT(maq_id) ids
 
341
                 FROM
 
342
                    " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "mail_queue
 
343
                 WHERE
 
344
                    maq_status='$status'
 
345
                 AND
 
346
                    maq_type_id > 0
 
347
                 GROUP BY
 
348
                    maq_type_id
 
349
                 ORDER BY
 
350
                    MIN(maq_id) ASC";
 
351
 
 
352
        if ($limit !== false) {
 
353
            $sql .= " LIMIT 0, $limit";
 
354
        }
 
355
 
 
356
        $res = DB_Helper::getInstance()->getAll($sql, DB_FETCHMODE_ASSOC);
 
357
        if (PEAR::isError($res)) {
 
358
            Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__);
 
359
            return array();
 
360
        }
 
361
 
 
362
        foreach ($res as &$value) {
 
363
           $value = explode(',', $value['ids']);
 
364
        }
 
365
 
 
366
        return $res;
 
367
    }
 
368
 
 
369
    /**
289
370
     * Retrieves queued email by maq_id.
290
371
     *
291
372
     * @access  private
316
397
        return $res;
317
398
    }
318
399
 
 
400
    /**
 
401
     * Retrieves queued email by maq_ids.
 
402
     *
 
403
     * @access  private
 
404
     * @param   array $maq_ids IDs of queue entries
 
405
     * @return  array The queued email message
 
406
     */
 
407
    private function _getEntries($maq_ids)
 
408
    {
 
409
        $stmt = "SELECT
 
410
                    maq_id id,
 
411
                    maq_iss_id,
 
412
                    maq_save_copy save_copy,
 
413
                    maq_recipient recipient,
 
414
                    maq_headers headers,
 
415
                    maq_body body,
 
416
                    maq_type,
 
417
                    maq_usr_id
 
418
                 FROM
 
419
                    " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "mail_queue
 
420
                 WHERE
 
421
                    maq_id IN (" . implode(',', $maq_ids) . ")";
 
422
        $res = DB_Helper::getInstance()->getAll($stmt, DB_FETCHMODE_ASSOC);
 
423
        if (PEAR::isError($res)) {
 
424
            Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__);
 
425
            return array();
 
426
        }
 
427
 
 
428
        return $res;
 
429
    }
319
430
 
320
431
    /**
321
432
     * Saves a log entry about the attempt, successful or otherwise, to send the