Skip directly to page content
b13 GmbH

Hauptstätter Str. 59
70178 Stuttgart
Germany
+49 (0) 711 460 589 70 [email protected]
Envelope icon with a circular arrow, indicating the action of replying to an email, set against a gradient background.

Documentation

TYPO3 Extension “Mail Queue”
Version 1.7.0 (2026-09-12)

Why the Manual Hold Is Not Enough

The Hold all mails toggle in the backend module is stored in sys_registry, which means in the database. That is exactly right for an ad-hoc hold on production, because it survives deployments.

It is not a reliable guarantee for a staging or test instance. Those regularly import the production database, and that import carries production's un-held state along, silently resuming delivery. A manually set staging hold is wiped by the next dump.

The Configuration Setting

For "this environment must never send mail", use the forceHold extension configuration. It lives in the deployment (config/system/settings.php), not in the database, so a production database import cannot clear it.

When enabled:

  • Every mail is queued and flush runs deliver nothing
  • The backend module shows the hold as configuration-enforced, with no resume button—an admin cannot lift an environment guarantee by mistake
  • Send now, Send again, and Send to address are hidden and rejected server-side, so the guarantee covers manual delivery as well as the flush run
  • It takes precedence over the manual toggle

Setting It Per Environment

Set it per environment via an environment variable rather than committing an environment-specific value, for example in additional.php:

$GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['mail_queue']['forceHold']
    = filter_var(getenv('MAIL_QUEUE_HOLD'), FILTER_VALIDATE_BOOLEAN);

Use FILTER_VALIDATE_BOOLEAN, not a (bool) cast. A plain cast treats every non-empty string except "0" as true, so "false", "no", and "off" would all enable the hold. FILTER_VALIDATE_BOOLEAN reads those—and an unset variable—as false.

Retention: Do Not Skip This

Under force hold every mail stays queued forever until you resume or discard it. mailqueue:cleanup does not remove queued rows unless you set queuedRetentionDays to a positive value.

The default is 0, meaning disabled, so that production retries are never dropped early. On a staging or test instance with force hold, set a value so the daily cleanup bounds table and disk growth:

$GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['mail_queue']['queuedRetentionDays'] = 14;

Without it, the queue table and var/mailqueue/ grow without bound for as long as the environment runs.

Deliberate Wipe

Before turning force hold off on staging, or after a load test, clear the accumulated queue in one go:

vendor/bin/typo3 mailqueue:purge --status=queued --dry-run   # preview the count
vendor/bin/typo3 mailqueue:purge --status=queued --force     # delete rows and payload files

--force is required for the destructive run. The other statuses, failed and sent, are allowed the same way.