Send queue 

Since version 4.3.0 a mail that could not be delivered to a recipient is not lost anymore. The recipient is put into a retry queue and the delivery is tried again later. Recipients that cannot be reached at all are marked as failed, so that you can see them in the backend, correct them and send again.

How it works 

When the sending command (mail:mass-mailing) delivers a mail to a recipient and the mail server refuses it or cannot be reached, the error is evaluated:

  • Temporary errors (SMTP reply code 4xx and errors without a code, for example a refused connection) are retried with increasing waiting times.
  • Permanent errors (SMTP reply code 5xx, for example a mailbox that does not exist) are not retried. The recipient is marked as failed right away.

Recipients that were delivered at the first attempt are not touched. Only failed recipients are written to the database table tx_mail_domain_model_queue.

Retry schedule 

After a failed attempt the next attempt is scheduled with these waiting times:

Failed attempt Waiting time
1st 1 minute
2nd 5 minutes
3rd 15 minutes
4th 1 hour
5th and every further attempt 4 hours

After maxAttempts attempts (including the first one) a recipient is marked as failed for good. With the default of 20 attempts, a recipient is tried for about 61 hours (two and a half days).

The retries are processed by the command mail:retry-failed. The command mail:mass-mailing does this as well after each cycle, so the scheduler task for the mass mailing is enough for most installations.

States of a queue entry 

Waiting for retry
The delivery failed temporarily. The next attempt is shown in the backend.
Sending
The entry is claimed by a running command. If a run is interrupted, entries in this state are put back into the queue after 15 minutes.
Sent
The delivery succeeded at a later attempt.
Failed
The delivery failed permanently, or the maximum number of attempts is reached. Failed entries are not retried automatically.

Failed deliveries in the backend 

The module Mail > Queue shows the section Deliveries to be retried or failed as soon as at least one recipient is waiting for a retry or has failed. Failed entries are red, waiting entries yellow.

The queue module lists failed and waiting deliveries with status icons, attempts, next attempt, last error and the buttons Send again and delete

For every entry you see the mail, the recipient, the status, the number of attempts, the time of the next attempt and the last error with its SMTP code. The status is shown as an icon: a red exclamation mark for a failed entry and a clock for an entry that waits for a retry. The text of the status appears as a tooltip. The complete error message is shown as a tooltip when you hover over the column Last error.

You can

  • press Send again to try the delivery again. The entry is put back into the queue and delivered with the next run of the sending command.
  • press the delete button (trash icon) to drop the entry. You have to confirm this in a dialog, which names the recipient. The recipient does not receive the mail.
  • correct the email address before you send again, if you enabled this function, see below.
The confirmation dialog when an entry of the send queue is deleted. It names the recipient

Correcting the email address 

If a delivery failed because the address is wrong, for example because of a typo, the address can be corrected in the queue module before the mail is sent again.

This function is disabled by default. Enable the checkbox enableEmailCorrection in the extension configuration of mail (tab feature) to use it.

The extension configuration of mail, tab feature, with the unchecked setting Enable correction of email addresses in the queue module

As soon as it is enabled, the column Recipient is an input field. Correct the address there and press Send again. The entry is put back into the queue with the corrected address and delivered with the next run of the sending command.

The queue module with the extension setting enableEmailCorrection enabled: the column Recipient is an input field to correct the email address

If the function is disabled, the address is shown as text. The server refuses requests that try to change the address anyway.

Automatic refresh 

The list is refreshed automatically. The interval is set by undeliveredRefreshRate (5 seconds by default, 0 turns it off). It is independent of the refresh of the delivery progress bars. You can change both intervals in the configuration dialog of the queue module, which opens with the gear icon at the top right.

The configuration dialog of the queue module with the intervals for refreshing the delivery progress bars and the failed deliveries

Every cycle only asks the server whether something has changed. The list is reloaded only if it has, so a retry that runs in the background shows up without reloading the module. The list is not replaced while you edit an email address.

Empty queue 

The queue module shows an info box with the text "The mail queue is empty" while there is no mail in the queue and no failed delivery

If there is no mail in the queue and no failed delivery, the module shows an info box "The mail queue is empty". The box disappears automatically as soon as a mail is scheduled, also by another user, or a delivery fails and is waiting for a retry. When the queue is empty again, the box is shown again. Mails are checked every refreshRate seconds, failed deliveries every undeliveredRefreshRate seconds. Finished mailings leave the list at once.

Reports 

A recipient that failed for good gets an additional entry with the response type "failed" in the mail log. The SMTP code is stored as return code, so that the failure shows up in the mail report together with the returned mails found by the bounce analysis.

If a failed recipient is delivered later, this entry is removed again and the delivery is counted as sent.

Parallel runs 

The commands that deliver mails (mail:mass-mailing and mail:retry-failed) share a lock. If a run is still active when the next one starts, the new run ends immediately with the note "Another send run is active. Skipped." This prevents mails from being delivered twice, for example if a scheduler task takes longer than its interval.

Alerting 

There are two ways to get informed about problems. Both are configured in the extension configuration.

Email
If opsNotificationEmail is set, an email is sent for each recipient that failed for good. It contains the number of the mail, the recipient, the SMTP code and the error.
Webhook

If alertWebhookUrl is set, the queue health is checked after each run. The queue counts as unhealthy as soon as the oldest recipient that is waiting or failed has been in the queue for at least alertThresholdMinutes minutes.

The webhook is called once when the queue turns unhealthy and, if notifyOnRecovery is active, once when it is healthy again. While the state stays the same, nothing is sent.

The request is a JSON POST. Only HTTPS addresses are called. Slack incoming webhooks work as they are, because Slack uses the field text and ignores the others.

Example of the request body
{
    "text": "EXT:mail send queue: deliveries are failing for 7 minutes.",
    "state": "red",
    "oldestUndeliverableSince": 1793381440
}
Copied!

The field state is red or recovered. oldestUndeliverableSince is the Unix timestamp of the oldest recipient that could not be delivered, or null when the queue is healthy again.

Cleanup 

Entries stay in the queue table after they are processed. The command mail:queue-cleanup removes sent and failed entries after the retention time set in the extension configuration (sentRetentionDays and failedRetentionDays). Add it as a daily scheduler task.