---
title: "4.3.0 - 5th Nov 2026"
manual: "Mail system"
version: "main"
permalink: "https://docs.typo3.org/permalink/mediaessenz/mail:4-3-0-5th-nov-2026@main"
source: "ChangeLog/4-3-0.rst"
rendered: "2026-11-05T22:41:21+00:00"
---

# 4.3.0 - 5th Nov 2026 {#4-3-0-5th-nov-2026}

-   [Send queue with retry for failed deliveries](https://docs.typo3.org/permalink/mediaessenz/mail:send-queue-with-retry-for-failed-deliveries@main)
-   [Alerting by webhook and email](https://docs.typo3.org/permalink/mediaessenz/mail:alerting-by-webhook-and-email@main)
-   [No overlapping send runs](https://docs.typo3.org/permalink/mediaessenz/mail:no-overlapping-send-runs@main)
-   [send-per-cycle is a limit for the whole run](https://docs.typo3.org/permalink/mediaessenz/mail:send-per-cycle-is-a-limit-for-the-whole-run@main)
-   [Manual delivery is switched off by default](https://docs.typo3.org/permalink/mediaessenz/mail:manual-delivery-is-switched-off-by-default@main)
-   [Module is reloaded after saving a configuration dialog](https://docs.typo3.org/permalink/mediaessenz/mail:module-is-reloaded-after-saving-a-configuration-dialog@main)
-   [Note instead of an empty table in the queue module](https://docs.typo3.org/permalink/mediaessenz/mail:note-instead-of-an-empty-table-in-the-queue-module@main)
-   [Class attributes in the mail: keep the ones that are still needed](https://docs.typo3.org/permalink/mediaessenz/mail:class-attributes-in-the-mail-keep-the-ones-that-are-still-needed@main)
-   [Improved detection of returned mails](https://docs.typo3.org/permalink/mediaessenz/mail:improved-detection-of-returned-mails@main)
-   [Mail object properties as markers](https://docs.typo3.org/permalink/mediaessenz/mail:mail-object-properties-as-markers@main)
-   [New commands](https://docs.typo3.org/permalink/mediaessenz/mail:new-commands@main)
-   [Update notes](https://docs.typo3.org/permalink/mediaessenz/mail:update-notes@main)
-   [For developers](https://docs.typo3.org/permalink/mediaessenz/mail:for-developers@main)

## Send queue with retry for failed deliveries {#send-queue-with-retry-for-failed-deliveries}

Until now, a recipient to whom a mail could not be delivered was treated like a recipient who got the mail. There was no
retry, and failed deliveries were only visible in the log of your mail server.

Failed deliveries are now written to a send queue and retried with increasing waiting times (1 minute, 5 minutes,
15 minutes, 1 hour, then every 4 hours). Permanent errors (SMTP reply code 5xx) are not retried, the recipient is
marked as failed right away. After 20 attempts (configurable) a recipient is marked as failed for good.

-   The module **Mail > Queue** shows waiting and failed recipients with the error message, the number of
    attempts and the time of the next attempt. The status is shown as an icon. You can send again or delete an entry
    after a confirmation.
-   The email address of a delivery can be corrected before it is sent again. This function is a feature flag and
    **disabled by default**. Enable the new extension setting
    [enableEmailCorrection](https://docs.typo3.org/permalink/mediaessenz/mail:extension-configuration-enable-email-correction@main) (tab "feature") to use it.
-   Recipients that failed for good get an additional entry with the response type "failed" in the mail log, with the SMTP
    code as return code. They are counted in the mail report. If such a recipient is delivered later, the entry is
    removed and the delivery is counted as sent.
-   The list is refreshed automatically. The interval is set by the new page TSconfig setting
    [undeliveredRefreshRate](https://docs.typo3.org/permalink/mediaessenz/mail:confval-undeliveredrefreshrate@main) (5 seconds by default, 0 turns it off), which can also
    be changed in the configuration dialog of the queue module. Only a small request runs each cycle, the list is
    reloaded when it has changed. It is not replaced while an email address is being edited.
-   The correction of an address only applies to this delivery (and needs the feature flag). The new PSR-14 event
    [RecipientEmailCorrectedEvent](https://docs.typo3.org/permalink/mediaessenz/mail:events-recipient-email-corrected@main) makes it possible to apply it to the
    recipient record (tt_address, fe_users and so on) as well.
-   The retry runs after each cycle of `mail:mass-mailing`. You can also run it more often with the new command
    `mail:retry-failed`.

See [Send queue](https://docs.typo3.org/permalink/mediaessenz/mail:send-queue@main) for details.

## Alerting by webhook and email {#alerting-by-webhook-and-email}

New extension settings under the tab "queue":

-   [alertWebhookUrl](https://docs.typo3.org/permalink/mediaessenz/mail:extension-configuration-alert-webhook-url@main): An HTTPS address that is called when the
    queue turns unhealthy, and when it is healthy again. The request is a JSON POST with a `text` field, so a
    Slack incoming webhook works as it is.
-   [alertThresholdMinutes](https://docs.typo3.org/permalink/mediaessenz/mail:extension-configuration-alert-threshold-minutes@main) and
    [notifyOnRecovery](https://docs.typo3.org/permalink/mediaessenz/mail:extension-configuration-notify-on-recovery@main) control when the webhook is called.
-   [opsNotificationEmail](https://docs.typo3.org/permalink/mediaessenz/mail:extension-configuration-ops-notification-email@main): An email address that is notified
    for every recipient that failed for good.

Both are disabled as long as the settings are empty.

## No overlapping send runs {#no-overlapping-send-runs}

`mail:mass-mailing` and `mail:retry-failed` now share a lock. If a run is still active when the next one
starts, the new run ends immediately. This prevents duplicate mails, for example if a scheduler task takes longer than
its interval.

## send-per-cycle is a limit for the whole run {#send-per-cycle-is-a-limit-for-the-whole-run}

The number of mails that are sent per cycle was counted per recipient source, so a mail with several recipient groups
of different sources could send more mails per cycle than configured. The limit now applies to the whole run.

## Manual delivery is switched off by default {#manual-delivery-is-switched-off-by-default}

The box with the button "Start sending manually" is only shown in the queue module, if "Send per click" in the
configuration dialog of the module ([sendPerCycle](https://docs.typo3.org/permalink/mediaessenz/mail:confval-sendpercycle@main)) is greater than 0. The dialog now accepts
0\. The action behind the button refuses to run as well, if the value is 0, so it cannot be called by url either.

The default of "Send per click" changed from 50 to 0. This means, the manual delivery is switched off by default and
mails are only sent by the scheduler or the command `mail:mass-mailing`.

> [!IMPORTANT]
> If you did not save "Send per click" for your mail folder before, the box "Manual delivery" is not shown anymore
> after the update. To get it back, open the configuration dialog of the queue module (gear icon) and set "Send per
> click" to a value greater than 0, for example 50. A value that was saved before is kept.

## Module is reloaded after saving a configuration dialog {#module-is-reloaded-after-saving-a-configuration-dialog}

If you changed a value in the configuration dialog of the queue module (or of the wizard) and saved it, the module below
the dialog still showed the old values until the page was reloaded manually. For example the number of mails in the text
of the manual delivery stayed the same. The module is now reloaded automatically when the dialog closes after saving.
Closing the dialog without saving does not reload anything.

## Note instead of an empty table in the queue module {#note-instead-of-an-empty-table-in-the-queue-module}

If the mail queue is empty, the queue module now shows an info box with the text "The mail queue is empty" instead of a
table with a single row. The box disappears by itself as soon as a mail is in the queue, also if another user scheduled
it, or if there are failed deliveries in the retry queue. It appears again when the queue is empty. The check uses the
interval [refreshRate](https://docs.typo3.org/permalink/mediaessenz/mail:confval-refreshrate@main), the failed deliveries are checked with
[undeliveredRefreshRate](https://docs.typo3.org/permalink/mediaessenz/mail:confval-undeliveredrefreshrate@main).

## Class attributes in the mail: keep the ones that are still needed {#class-attributes-in-the-mail-keep-the-ones-that-are-still-needed}

The class attributes of a mail are removed after the CSS has been inlined (`removeClassAttributes`, enabled by
default). This also removed the classes which are still needed by CSS rules that cannot be inlined, so a rule like
`.body a:hover` never applied.

-   The new option `removeClassAttributes.smart = 1` keeps exactly the classes that are still referenced by such
    rules and removes all others. Example:

    ```typoscript
    mail.10.removeClassAttributes = 1
    mail.10.removeClassAttributes.smart = 1
    ```
-   `removeClassAttributes.keepOnTags` keeps the class attribute of the given tags,
    `removeClassAttributes.keepClasses` keeps the given classes on all other elements. Both can be combined with
    `smart`.
-   The same is available in the Fluid template with the new arguments `removeClassAttributes`,
    `keepOnTags`, `keepClasses` and `smartClassRemoval` of the
    [EmogrifyViewHelper](https://docs.typo3.org/permalink/mediaessenz/mail:view-helpers-emogrify@main).
-   Fix: The class was only removed from elements which had another attribute. `<div class="body">` kept its class.
    The class attributes are now removed from every element. If your styles depended on a class that stayed by accident,
    add it with `keepClasses`.
-   New options of the CSS inliner for the content object `EMOGRIFIER`: `addExcludedCssSelector` and
    `removeExcludedCssSelector`. They require `pelago/emogrifier` 7.3 or higher, the extension now requires
    this version.
-   `EmogrifierUtility::emogrify()` has strict parameter types now (`string`, `string`, `bool`,
    `array`) and does not accept `null` for the HTML and the CSS anymore. This only affects your own code, which
    calls the method directly.

> [!WARNING]
> Do not assign your own CSS to `mail.10.css.10` or `mail.10.css.20`. These indexes are used by the
> extension, your CSS replaces its styles and the mail loses e.g. its container width and padding. Use a free index like
> `mail.10.css.30`.

See [EMOGRIFIER](https://docs.typo3.org/permalink/mediaessenz/mail:content-object-emogrifier@main) and [SCSS](https://docs.typo3.org/permalink/mediaessenz/mail:content-object-scss@main).

## Improved detection of returned mails {#improved-detection-of-returned-mails}

Several users reported that returned mails (bounces) got a wrong reason and showed up in the wrong category of the report
module. The detection is rewritten:

-   The type and the reason are taken from the delivery status notification (RFC 3464) of the mail server, which carries
    the enhanced status code (for example 5.1.1 for an unknown recipient, 5.2.2 for a full mailbox). Only returned mails
    without a notification are classified by the text, in a defined order (for example "User unknown" counts before
    "Recipient address rejected").
-   The quoted original of your mailing is not searched anymore. Before, words like "quota exceeded" in a newsletter
    could decide about the category of a returned mail.
-   Rejections by a spam filter or a policy (status 5.7.x, "access denied", "relay denied") are no longer reported as
    "Recipient unknown". They have their own category "Blocked by policy or spam filter".
-   Temporary problems (status 4.x.x, greylisting) are separated as "Temporary problems" and are not counted as
    permanent failures. A button "Disable returned recipients" only affects permanent bounces and no longer affects
    policy rejections and temporary problems.
-   Returned mails with an unknown reason are stored now. Before they could get lost, because the reason was written as
    `-1` into an unsigned column, which failed on databases in strict mode. The message stayed in the mailbox and
    was read again with every run.
-   Auto replies (out of office) and delivery receipts are ignored. The text is decoded (quoted-printable, base64, charsets),
    several recipients in one notification are handled and a recipient is counted once per mailing.
-   The `mail:analyze-bounce-mail` command continues after an error in one message and prints a summary. The new
    options `--dry-run` and `--unseen-only` are described in [AnalyzeBounceMailCommand](https://docs.typo3.org/permalink/mediaessenz/mail:analyze-bounce-mail-command-controller@main).
-   The return code of the log is now the real SMTP code (before it was an internal code, which collided with the codes of
    the send queue). The report uses the new columns `bounce_type`, `bounce_reason` and `dsn_status`.

See [Mail Report](https://docs.typo3.org/permalink/mediaessenz/mail:mail-report-returned@main).

## Mail object properties as markers {#mail-object-properties-as-markers}

Similar to the properties of a recipient, the properties of the mail object can be used as markers in the content of
an email. For example, the reply-to address can be printed in the footer with `###MAIL_replyToEmail###`.

-   All properties of the mail object with a getter named `get<Property>` can be used. The allowed properties are set
    by the new extension setting [mailFields](https://docs.typo3.org/permalink/mediaessenz/mail:extension-configuration-mail-fields@main).
-   By default these markers are available: `###MAIL_subject###`, `###MAIL_fromEmail###`,
    `###MAIL_fromName###`, `###MAIL_replyToEmail###`, `###MAIL_replyToName###` and
    `###MAIL_organisation###`.

## New commands {#new-commands}

-   `mail:retry-failed`: Delivers waiting recipients whose retry time is reached.
-   `mail:queue-cleanup`: Removes delivered and failed entries after the configured retention time
    ([sentRetentionDays](https://docs.typo3.org/permalink/mediaessenz/mail:extension-configuration-sent-retention-days@main): 30 days,
    [failedRetentionDays](https://docs.typo3.org/permalink/mediaessenz/mail:extension-configuration-failed-retention-days@main): 90 days by default).
-   `mail:queue-purge`: Deletes all queue entries with a given status. Without `--force` it only shows how
    many entries would be deleted.

See [Command Controller](https://docs.typo3.org/permalink/mediaessenz/mail:command-controller@main).

## Update notes {#update-notes}

> [!IMPORTANT]
> This version adds the database table `tx_mail_domain_model_queue`. After the update, open
> **Admin Tools > Maintenance > Analyze Database Structure** and apply the suggested changes. On the command
> line, run `vendor/bin/typo3 extension:setup` or, if typo3_console is installed,
> `vendor/bin/typo3 database:updateschema`.

> [!IMPORTANT]
> The table `tx_mail_domain_model_log` gets the columns `bounce_type`, `bounce_reason` and
> `dsn_status`. Apply the database changes as described above and run the upgrade wizard
> **EXT:mail: Set type and reason of returned mails** (`vendor/bin/typo3 upgrade:run mailBounceTypeMigration`).
> Without the wizard, returned mails that were stored by an older version are listed as "Reason unknown".

Recommended after the update:

-   Set [opsNotificationEmail](https://docs.typo3.org/permalink/mediaessenz/mail:extension-configuration-ops-notification-email@main) and/or
    [alertWebhookUrl](https://docs.typo3.org/permalink/mediaessenz/mail:extension-configuration-alert-webhook-url@main) in the extension settings.
-   Add `mail:queue-cleanup` as a daily scheduler task.
-   Make sure the sending is done by the scheduler (`mail:mass-mailing`). The manual delivery in the queue module
    is switched off by default now.
-   Enable [enableEmailCorrection](https://docs.typo3.org/permalink/mediaessenz/mail:extension-configuration-enable-email-correction@main), if editors should be able to
    correct the email address of failed deliveries. It is disabled by default.

If a mail is deleted in the **Queue** or **Reports** module, its queue entries are deleted as well.
Queue entries of a mail that was deleted another way are removed with the next send run, without a failure message.

## For developers {#for-developers}

-   New event `MEDIAESSENZ\Mail\Events\RecipientEmailCorrectedEvent`, see [RecipientEmailCorrectedEvent](https://docs.typo3.org/permalink/mediaessenz/mail:events-recipient-email-corrected@main).
    The constructor of `SendQueueService` got the event dispatcher as an additional argument. The class is internal.
-   `MEDIAESSENZ\Mail\Mail\MailMessage::sendOrFail()` sends a message and lets transport errors through. The
    existing `send()` keeps its behavior and still returns `false` on errors.
-   `MEDIAESSENZ\Mail\Service\MailerService::resendToRecipient()` returns the sent format
    (`MEDIAESSENZ\Mail\Type\Bitmask\SendFormat`) instead of nothing. It is used by the retry and not meant to be called
    by other extensions.
-   New event `MEDIAESSENZ\Mail\Events\RecipientBouncedEvent`, see [RecipientBouncedEvent](https://docs.typo3.org/permalink/mediaessenz/mail:events-recipient-bounced@main). The values in
    the data of the [DeactivateRecipientsEvent](https://docs.typo3.org/permalink/mediaessenz/mail:events-deactivate-recipients@main) under `returnCodes` are the values of
    `MEDIAESSENZ\Mail\Type\Enumeration\BounceReason` now.
-   The internal class `MEDIAESSENZ\Mail\Utility\BounceMailUtility` is removed, the analysis is done by
    `MEDIAESSENZ\Mail\Bounce\BounceAnalyzer`. The enumeration `ReturnCodes` is deprecated, it was not used for
    real codes. `LogRepository::findReturnCodesByMail()` is replaced by `findBounceStatsByMail()`.
-   The new classes `SendQueueService`, `AlertService`, `SendQueueLock` and the repositories for the
    queue are internal. Their signatures may change.
-   The extension now has unit and functional tests for the send queue (`composer test:unit`,
    `composer test:functional`).
