Skip to content

Commit

Permalink
SMTP Mail Queueing improvements
Browse files Browse the repository at this point in the history
Fixes #7787

Trying to keep inside the database schema, i'm abusing the priority level to slowly raise it to the max (127 due to signed tinyint).  It does this over a period of 3 days (which can be changed) by calculating the difference between the current time and the time the email was sent.
  • Loading branch information
jdarwood007 committed Jul 8, 2023
1 parent 78e16b5 commit d9a986f
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 6 deletions.
17 changes: 13 additions & 4 deletions Sources/ScheduledTasks.php
Original file line number Diff line number Diff line change
Expand Up @@ -712,7 +712,7 @@ function ReduceMailQueue($number = false, $override_limit = false, $force_send =

// Now we know how many we're sending, let's send them.
$request = $smcFunc['db_query']('', '
SELECT id_mail, recipient, body, subject, headers, send_html, time_sent, private
SELECT id_mail, recipient, body, subject, headers, send_html, time_sent, private, priority
FROM {db_prefix}mail_queue
ORDER BY priority ASC, id_mail ASC
LIMIT {int:limit}',
Expand All @@ -734,6 +734,7 @@ function ReduceMailQueue($number = false, $override_limit = false, $force_send =
'send_html' => $row['send_html'],
'time_sent' => $row['time_sent'],
'private' => $row['private'],
'priority' => $row['priority'],
);
}
$smcFunc['db_free_result']($request);
Expand Down Expand Up @@ -772,6 +773,8 @@ function ReduceMailQueue($number = false, $override_limit = false, $force_send =

// Send each email, yea!
$failed_emails = array();
$max_priority = 127;
$smtp_expire = ($modSettings['smtp_day_expiry'] ?? 3) * 60 * 60 * 24;
foreach ($emails as $email)
{
if (empty($modSettings['mail_type']) || $modSettings['smtp_host'] == '')
Expand All @@ -795,10 +798,16 @@ function ReduceMailQueue($number = false, $override_limit = false, $force_send =
$result = smtp_mail(array($email['to']), $email['subject'], $email['body'], $email['headers']);

// Hopefully it sent?
if (!$result)
$failed_emails[] = array($email['to'], $email['body'], $email['subject'], $email['headers'], $email['send_html'], $email['time_sent'], $email['private']);
if (!$result && $email['priority'] < $max_priority)
{
// Determine the "priority" as a way to keep track of SMTP failures.
$email['priority'] = max($email['priority'], min(ceil((time() - $email['time_sent']) / $smtp_expire * $max_priority), $max_priority));

$failed_emails[] = array($email['to'], $email['body'], $email['subject'], $email['headers'], $email['send_html'], $email['time_sent'], $email['private'], $email['priority']);
}
}


// Any emails that didn't send?
if (!empty($failed_emails))
{
Expand Down Expand Up @@ -826,7 +835,7 @@ function ReduceMailQueue($number = false, $override_limit = false, $force_send =
// Add our email back to the queue, manually.
$smcFunc['db_insert']('insert',
'{db_prefix}mail_queue',
array('recipient' => 'string', 'body' => 'string', 'subject' => 'string', 'headers' => 'string', 'send_html' => 'string', 'time_sent' => 'string', 'private' => 'int'),
array('recipient' => 'string', 'body' => 'string', 'subject' => 'string', 'headers' => 'string', 'send_html' => 'string', 'time_sent' => 'string', 'private' => 'int', 'priority' => 'int'),
$failed_emails,
array('id_mail')
);
Expand Down
5 changes: 3 additions & 2 deletions Sources/Subs-Post.php
Original file line number Diff line number Diff line change
Expand Up @@ -1592,9 +1592,10 @@ function server_parse($message, $socket, $code, &$response = null)
if ($code === null)
return substr($server_response, 0, 3);

if (substr($server_response, 0, 3) != $code)
if (($server_code = substr($server_response, 0, 3)) != $code)
{
log_error($txt['smtp_error'] . $server_response);
if ($server_code < 500 && !in_array($server_code, [450, 451, 421]))
log_error($txt['smtp_error'] . $server_response);
return false;
}

Expand Down

0 comments on commit d9a986f

Please sign in to comment.