sgalinski / sg-mail
TYPO3 Mail Queue & Templates - TYPO3 mail management extension with multilingual template and layout editing (HTML/MJML), queue and priority handling, ext:form finishers, marker/event API, CSV export, blacklist controls, and Scheduler/CLI commands.
Package info
gitlab.sgalinski.de/typo3/sg_mail.git
Type:typo3-cms-extension
pkg:composer/sgalinski/sg-mail
Requires
- typo3/cms-core: >=14.3.0 <=14.3.99
Replaces
- sgalinski/sg_mail: 11.1.1
This package is auto-updated.
Last update: 2026-08-14 23:47:11 UTC
README
License: GNU GPL, Version 2
Repository: https://gitlab.sgalinski.de/typo3/sg_mail
Please report bugs here: https://gitlab.sgalinski.de/typo3/sg_mail/-/issues
Overview
sg_mail provides a site- and language-aware mail-template service, an editable mail-layout backend module and a
durable mail queue for TYPO3. It also integrates with EXT:form, provides marker and event APIs, and can capture
outgoing TYPO3 mail in the queue for operational visibility.
The extension is the generic mail layer. Domain-specific workflows, such as newsletter recipients, archives and their attachment lifecycle, belong in the consuming extension.
Requirements
- TYPO3
14.3 - PHP
8.3or newer - A configured TYPO3 mail transport (
MAIL.transport)
Installation
Install the Composer package and run the TYPO3 maintenance steps:
composer require sgalinski/sg-mail
vendor/bin/typo3 extension:setup
vendor/bin/typo3 database:updateschema
vendor/bin/typo3 cache:flush
Activate the extension's Site Set for every site that uses the site settings, for example bounce processing:
# config/sites/<site>/config.yaml
dependencies:
- sgalinski/sg-mail
After installation, open the SG Mail backend module and create or review the layouts and templates required by the project. Existing installations must also follow UPGRADE.md.
Configuration
Mail transport and queue
Configure the actual delivery transport through TYPO3's MAIL.transport configuration. By default, sg_mail
registers its spool transport so outgoing TYPO3 mails are recorded in the sg_mail queue. The queue worker uses the
configured real transport and adds a bypass header to prevent mails being queued a second time.
Set enableGlobalMailSpoolTransport = 0 in Settings > Extension Configuration > sg_mail if the project must not
capture all outgoing TYPO3 mail. This does not disable mails created explicitly through MailDeliveryService.
Create these Scheduler tasks (or invoke the equivalent commands from a system cron):
# Send up to 50 due queue entries.
vendor/bin/typo3 sg_mail:sendMail 50
# Remove queue history older than 180 days, including FAL attachments owned only by those records.
vendor/bin/typo3 sg_mail:deleteOldMails 180 1000
The project must choose its own execution interval, batch size and retention period. A practical starting point is a queue worker every five minutes and cleanup once a day.
Bounce mailbox
Configure only non-secret values in config/sites/<site>/settings.yaml. Credentials and complete DSNs must come from
the deployment environment, not version control:
sgMail:
bounceReturnPath: bounces@example.org
bounceMailbox:
host: imap.example.org
port: 993
user: bounces@example.org
passwordEnvironmentVariable: SG_MAIL_BOUNCE_PASSWORD
folder: INBOX
encryption: ssl
validateCertificate: true
processedFolder: Processed
deleteProcessed: false
Alternatively, configure the name of an environment variable that contains the full IMAP DSN:
sgMail:
bounceMailbox:
dsnEnvironmentVariable: SG_MAIL_BOUNCE_DSN
SG_MAIL_BOUNCE_DSN may use the schemes imap, imaps, imap+ssl, imap+tls or imap+notls. A DSN overrides
the individual mailbox fields; an environment-variable value overrides the corresponding site setting. The generic
parsing and classification live in sg_mail; the business reaction to a bounce belongs in the consuming extension.
Template exclusions
Use the extension configuration to exclude registered templates from the backend selector and from delivery:
excludeTemplatesAllDomains: comma-separated template keys, for examplemy_extension.confirm,my_extension.alertexcludeTemplates: semicolon-separated site rules, for example1,my_extension.confirm;10,my_extension.alert
Each template key has the format <extension_key>.<template_key>.
Usage
Register a shipped template
Registrations that are part of extension code are PHP files registered from ext_localconf.php. Backend-managed and
form-generated registrations are stored in the database; do not write mutable registrations to fileadmin.
// EXT:my_extension/ext_localconf.php
$GLOBALS['sg_mail']['my_extension']['registration_confirmed'] =
'EXT:my_extension/Configuration/SgMail/RegistrationConfirmed.php';
// EXT:my_extension/Configuration/SgMail/RegistrationConfirmed.php
use SGalinski\SgMail\Service\MarkerService;
return [
'extension_key' => 'my_extension',
'template_key' => 'registration_confirmed',
'description' => 'LLL:EXT:my_extension/Resources/Private/Language/locallang.xlf:mail.registrationConfirmed.description',
'subject' => 'LLL:EXT:my_extension/Resources/Private/Language/locallang.xlf:mail.registrationConfirmed.subject',
'templateContent' => '<p>Hello {user.name},</p>',
'markers' => [
[
'marker' => 'user.name',
'type' => MarkerService::TYPE_STRING,
'value' => 'Ada Lovelace',
'description' => 'LLL:EXT:my_extension/Resources/Private/Language/locallang.xlf:mail.marker.userName',
],
],
];
Use templateContent for the shipped content. The deprecated templatePath mechanism is not supported for new
templates. Clear TYPO3 caches after changing a PHP registration.
Create and queue a mail
Inject TemplateService and MailDeliveryService. The page and language identify the site-specific template and
layout. A CLI command or middleware without a complete Extbase request must use
createMailFromTemplateNameInRuntimeContext().
use SGalinski\SgMail\Domain\Model\Mail;
use SGalinski\SgMail\Service\MailDeliveryService;
use SGalinski\SgMail\Service\TemplateService;
final class RegistrationMailService
{
public function __construct(
private readonly TemplateService $templateService,
private readonly MailDeliveryService $mailDeliveryService,
) {}
public function queue(string $recipient, int $pageId, int $languageId): bool
{
$mail = $this->templateService->createMailFromTemplateName(
'registration_confirmed',
'my_extension',
['user.name' => 'Ada Lovelace'],
$pageId,
$languageId,
Mail::PRIORITY_MEDIUM,
);
$mail->setToAddress($recipient);
return $this->mailDeliveryService->addMailToQueue($mail);
}
}
addMailToQueue() persists the mail for the worker. Use sendMailFromQueue($mail) only for an intentional immediate
send, such as a preview or a transactional mail that must not wait for the worker. Inspect the queue and its error
messages in the SG Mail backend module.
Layouts, language and forms
Layouts and database templates are edited in the SG Mail backend module. The template editor provides marker
previews and sends test mails with a (PREVIEW) subject prefix. Template fields and labels can use LLL: references;
the selected site language is applied when rendering.
EXT:form receives the MailToUserFinisher and MailToAdminFinisher finishers once sg_mail is installed. Select
an sg_mail template in the Form Editor and configure recipient, sender and optional reply-to/CC/BCC fields there.
Generated registrations are stored in the database and are migrated by the provided upgrade wizard when required.
Attachments
For mail-queue history, sg_mail supports TYPO3 FAL attachments on mail records. The cleanup command removes a file
only when the deleted mail record was its last reference. Consumers that need durable or public attachment links must
create and retain their own FAL references; a transient filesystem path is not a durable attachment reference.
Testing
Run the extension checks from the project root:
composer ecs vendor/sgalinski/sg-mail
composer phpstan vendor/sgalinski/sg-mail
composer phpunit vendor/sgalinski/sg-mail
Upgrade notes
See UPGRADE.md before upgrading. In particular, version 11 requires TYPO3 14.3+, moves bounce settings to the Site Set, and provides an upgrade wizard for legacy file-based mutable registrations.