---
title: "Mail API"
manual: "TYPO3 Explained"
version: "main"
permalink: "https://docs.typo3.org/permalink/t3coreapi:mail@main"
source: "ApiOverview/Mail/Index.rst"
rendered: "2026-09-19T06:56:03+00:00"
---

# Mail API {#mail}

TYPO3 provides a RFC-compliant mailing solution based on
[symfony/mailer](https://symfony.com/doc/current/components/mailer.html)
for sending emails and
[symfony/mime](https://symfony.com/doc/current/components/mime.html)
for creating email messages.

TYPO3’s backend functionality already ships with a default layout for templated emails,
which can be tested out in TYPO3’s install tool test email functionality.

**Table of Contents**

-   [Configuration](https://docs.typo3.org/permalink/t3coreapi:configuration@main)
-   [Spooling](https://docs.typo3.org/permalink/t3coreapi:spooling@main)
-   [How to create and send emails](https://docs.typo3.org/permalink/t3coreapi:how-to-create-and-send-emails@main)
-   [How to add attachments](https://docs.typo3.org/permalink/t3coreapi:how-to-add-attachments@main)
-   [How to add inline media](https://docs.typo3.org/permalink/t3coreapi:how-to-add-inline-media@main)
-   [How to set and use a default sender](https://docs.typo3.org/permalink/t3coreapi:how-to-set-and-use-a-default-sender@main)
-   [Register a custom mailer](https://docs.typo3.org/permalink/t3coreapi:register-a-custom-mailer@main)
-   [PSR-14 events on sending messages](https://docs.typo3.org/permalink/t3coreapi:psr-14-events-on-sending-messages@main)
-   [Symfony mail documentation](https://docs.typo3.org/permalink/t3coreapi:symfony-mail-documentation@main)

## Configuration {#mail-configuration}

Several settings are available via **System > Settings > Configure
Installation-Wide Options > Mail** which are stored into
`$GLOBALS['TYPO3_CONF_VARS']['MAIL']`. See [MAIL settings](https://docs.typo3.org/permalink/t3coreapi:typo3confvars-mail@main) for
an overview of all settings.

> [!NOTE]
> If you want to send emails using Microsoft 365 or Office 365, you have to
> configure a connector first, as described in the article
> [Configure a connector to send mail using Microsoft 365 or Office 365 SMTP relay](https://learn.microsoft.com/en-us/exchange/mail-flow-best-practices/how-to-set-up-a-multifunction-device-or-application-to-send-email-using-microsoft-365-or-office-365#option-3-configure-a-connector-to-send-mail-using-microsoft-365-or-office-365-smtp-relay).

### Format {#mail-configuration-format}

`$GLOBALS['TYPO3_CONF_VARS']['MAIL']['format']` can be `both`, `plain` or
`html`. This option can be overridden in the project's
`config/system/settings.php` or `config/system/additional.php` files.

### Fluid paths {#mail-configuration-fluid}

All Fluid-based template paths can be configured via

-   `$GLOBALS['TYPO3_CONF_VARS']['MAIL']['layoutRootPaths']`
-   `$GLOBALS['TYPO3_CONF_VARS']['MAIL']['partialRootPaths']`
-   `$GLOBALS['TYPO3_CONF_VARS']['MAIL']['templateRootPaths']`

where TYPO3 reserves all array keys below `100` for internal purposes.

If you want to provide custom templates or layouts, set this in your
`config/system/settings.php` / `config/system/additional.php` file:

**config/system/additional.php | typo3conf/system/additional.php**

```php
<?php

$GLOBALS['TYPO3_CONF_VARS']['MAIL']['templateRootPaths'][700]
    = 'EXT:my_site_package/Resources/Private/Templates/Email';
$GLOBALS['TYPO3_CONF_VARS']['MAIL']['layoutRootPaths'][700]
    = 'EXT:my_site_extension/Resources/Private/Layouts';

```

#### Minimal example for a Fluid-based email template {#mail-configuration-fluid-example}

**Directory Structure:**

-   EXT:my_site_package/ > -   Resources > >     -   Private > >         -   Templates > >             -   Email > >                 -   MyCustomEmail.fluid.html

`MyCustomEmail.fluid.html`:

**EXT:my_site_package/Resources/Private/Templates/Email/MyCustomEmail.fluid.html**

```html
<f:layout name="SystemEmail" />

<f:section name="Subject">
    My Custom Subject
</f:section>

<f:section name="Main">
    Hello, this is a custom email template!
</f:section>
```

### transport {#mail-configuration-transport}

The most important configuration option for sending emails is
`$GLOBALS['TYPO3_CONF_VARS']['MAIL']['transport']`, which can take the
following values:

#### smtp {#mail-configuration-smtp}

-   **`$GLOBALS['TYPO3_CONF_VARS']['MAIL']['transport'] = 'smtp';`**

    Sends messages over SMTP. It can deal with encryption and authentication.
    Works exactly the same on Windows, Unix and MacOS. Requires a mail server
    and the following additional settings:

-   **`$GLOBALS['TYPO3_CONF_VARS']['MAIL']['transport_smtp_server'] = '<server:port>';`**

    Mail server name and port to connect to. Port defaults to `25`.

-   **`$GLOBALS['TYPO3_CONF_VARS']['MAIL']['transport_smtp_encrypt'] = <bool>;`**

    Determines whether the transport protocol should be encrypted. Requires
    OpenSSL library. Defaults to `false`.
    If `false`, symfony/mailer will use STARTTLS.

-   **`$GLOBALS['TYPO3_CONF_VARS']['MAIL']['transport_smtp_username] = '<username>';`**

    The username, if your SMTP server requires authentication.

-   **`$GLOBALS['TYPO3_CONF_VARS']['MAIL']['transport_smtp_password] = '<password>';`**

    The password, if your SMTP server requires authentication.

Example:

**config/system/additional.php | typo3conf/system/additional.php**

```php
<?php

$GLOBALS['TYPO3_CONF_VARS']['MAIL']['transport'] = 'smtp';
$GLOBALS['TYPO3_CONF_VARS']['MAIL']['transport_smtp_server'] = 'localhost';
$GLOBALS['TYPO3_CONF_VARS']['MAIL']['transport_smtp_encrypt'] = true;
$GLOBALS['TYPO3_CONF_VARS']['MAIL']['transport_smtp_username'] = 'johndoe';
$GLOBALS['TYPO3_CONF_VARS']['MAIL']['transport_smtp_password'] = 'cooLSecret';
// Fetches all 'returning' emails:
$GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromAddress']
    = 'bounces@example.org';

```

#### sendmail {#mail-configuration-sendmail}

-   **`$GLOBALS['TYPO3_CONF_VARS']['MAIL']['transport'] = 'sendmail';`**

    Sends messages by communicating with a locally installed MTA - such as sendmail.
    This may require setting the additional option:

-   **`$GLOBALS['TYPO3_CONF_VARS']['MAIL']['transport_sendmail_command'] = '<command>';`**

    The command to call to send an email locally. The default works on most
    modern Unix-based mail servers (sendmail, postfix, exim).

    Example:

    **config/system/additional.php | typo3conf/system/additional.php**

    ```php
    $GLOBALS['TYPO3_CONF_VARS']['MAIL']['transport'] = 'sendmail';
    $GLOBALS['TYPO3_CONF_VARS']['MAIL']['transport_sendmail_command'] = '/usr/sbin/sendmail -bs';
    ```

    > [!WARNING]
    > **Attention**
    >
    > Depending on the configuration of the server and the TYPO3 instance, it
    > may not be possible to send emails to BCC recipients. The configuration
    > of the `$GLOBALS['TYPO3_CONF_VARS']['MAIL']['transport_sendmail_command']`
    > value is crucial.
    >
    > TYPO3 recommends the parameter `-bs` (instead of `-t -i`). The
    > parameter `-bs` tells TYPO3 to use the SMTP standard and that way
    > the BCC recipients are properly set.
    > [Symfony](https://symfony.com/doc/current/mailer.html#using-built-in-transports)
    > refers to the problem of using the `-t` parameter as well. Since
    > [forge#65791](https://forge.typo3.org/issues/65791) the `transport_sendmail_command` is automatically
    > set from the PHP runtime configuration and saved. Thus, if you have
    > problems with sending emails to BCC recipients, check the above
    > mentioned configuration.

#### mbox {#mail-configuration-mbox}

-   **`$GLOBALS['TYPO3_CONF_VARS']['MAIL']['transport'] = 'mbox';`**

    This doesn't send any email out, but instead will write every outgoing email
    to a file adhering to the [RFC 4155 mbox format](https://www.rfc-editor.org/rfc/rfc4155.html), which is a simple text
    file where the emails are concatenated. Useful for debugging the email
    sending process and on development machines which cannot send emails to the
    outside. The file to write to is defined by:

-   **`$GLOBALS['TYPO3_CONF_VARS']['MAIL']['transport_mbox_file'] = '</abs/path/to/mbox/file>';`**

    The file where to write the emails into. The path must be absolute.

#### \<classname> {#mail-configuration-classname}

-   **`$GLOBALS['TYPO3_CONF_VARS']['MAIL']['transport'] = '<classname>';`**

    Custom class which implements
    `\Symfony\Component\Mailer\Transport\TransportInterface`.
    The constructor receives all settings from the `MAIL` section to make it
    possible to add custom settings.

### Validators {#mail-validators}

Using additional validators can help to identify if a provided email address
is valid or not. By default, the validator
`\Egulias\EmailValidator\Validation\RFCValidation` is used. The following
validators are available:

-   `\Egulias\EmailValidator\Validation\DNSCheckValidation`
-   `\Egulias\EmailValidator\Validation\SpoofCheckValidation`
-   `\Egulias\EmailValidator\Validation\NoRFCWarningsValidation`

Additionally, it is possible to provide an own implementation by implementing
the interface `\Egulias\EmailValidator\Validation\EmailValidation`.

If multiple validators are provided, each validator must return `true`.

Example:

**config/system/additional.php | typo3conf/system/additional.php**

```php
<?php

use Egulias\EmailValidator\Validation\DNSCheckValidation;
use Egulias\EmailValidator\Validation\RFCValidation;

$GLOBALS['TYPO3_CONF_VARS']['MAIL']['validators'] = [
  RFCValidation::class,
  DNSCheckValidation::class,
];

```

## Spooling {#mail-spooling}

The default behavior of the TYPO3 mailer is to send the email messages
immediately. However, you may want to avoid the performance hit of the
communication to the email server, which could cause the user to wait for the
next page to load while the email is being sent. This can be avoided by choosing
to "spool" the emails instead of sending them directly.

### Spooling in memory {#mail-spooling-spooling-memory}

```php
$GLOBALS['TYPO3_CONF_VARS']['MAIL']['transport_spool_type'] = 'memory';
```

When you use spooling to store the emails to memory, they will get sent right
before the kernel terminates. This means the email only gets sent if the whole
request got executed without any unhandled exception or any errors.

### Spooling using files {#mail-spooling-spooling-files}

```php
$GLOBALS['TYPO3_CONF_VARS']['MAIL']['transport_spool_type'] = 'file';
$GLOBALS['TYPO3_CONF_VARS']['MAIL']['transport_spool_filepath'] = '/folder/of/choice';
```

When using the filesystem for spooling, you need to define in which folder TYPO3
stores the spooled files. This folder will contain files for each email in the
spool. So make sure this directory is writable by TYPO3 and not accessible to
the world (outside of the webroot).

Additional notes about the mail spool path:

-   If the path is absolute, the path must either start with the root path of
    the TYPO3 project or the public web folder path
-   If the path is relative, the public web path is prepended to the path
-   The path must not contain symlinks (important for environments with auto
    deployment)
-   The path must not contain `//`, `..` or `\`

### Sending spooled mails {#mail-spooling-sending-spooled-mails}

To send the spooled emails you need to run the following CLI command:

**Composer-based installation**

```bash
vendor/bin/typo3 mailer:spool:send
```

**Classic mode installation (no Composer)**

```bash
typo3/sysext/core/bin/typo3 mailer:spool:send
```

This command can be set up to be run periodically using the
[TYPO3 Scheduler](https://docs.typo3.org/c/typo3/cms-scheduler/main/en-us/Index.html).

## How to create and send emails {#mail-create}

There are two ways to send emails in TYPO3 based on the Symfony API:

1.  With [Fluid](https://docs.typo3.org/permalink/t3coreapi:mail-fluid-email@main), using `\TYPO3\CMS\Core\Mail\FluidEmail`
1.  [Without Fluid](https://docs.typo3.org/permalink/t3coreapi:mail-mail-message@main), using `\TYPO3\CMS\Core\Mail\MailMessage`

`\TYPO3\CMS\Core\Mail\MailMessage` and `\TYPO3\CMS\Core\Mail\FluidEmail`
inherit from `\Symfony\Component\Mime\Email` and have a similar API.
**FluidEmail** is specific for sending emails based on Fluid.

Either method can be used to send emails with HTML content, text content or both
(HTML and text).

### Send email with `FluidEmail` {#mail-fluid-email}

This sends an email using a Fluid template `TipsAndTricks.html`, make
sure the paths are setup as described in [Fluid paths](https://docs.typo3.org/permalink/t3coreapi:mail-configuration-fluid@main):

**EXT:my_extension/Classes/MyClass.php**

```php
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension;

use Symfony\Component\Mime\Address;
use TYPO3\CMS\Core\Mail\FluidEmail;
use TYPO3\CMS\Core\Mail\MailerInterface;
use TYPO3\CMS\Core\Utility\GeneralUtility;

final class MyClass
{
  public function sendMail(): void
  {
    $email = new FluidEmail();
    $email
        ->to('contact@example.org')
        ->from(new Address('jeremy@example.org', 'Jeremy'))
        ->subject('TYPO3 loves you - here is why')
        // Send HTML and plaintext mail
        ->format(FluidEmail::FORMAT_BOTH)
        ->setTemplate('TipsAndTricks')
        ->assign('mySecretIngredient', 'Tomato and TypoScript');
    GeneralUtility::makeInstance(MailerInterface::class)->send($email);
  }
}

```

It is recommended to use the `\TYPO3\CMS\Core\Mail\MailerInterface`
to be able to use [custom mailer implementations](https://docs.typo3.org/permalink/t3coreapi:register-custom-mailer@main).

A file `TipsAndTricks.html` must exist in one of the paths defined in
`$GLOBALS['TYPO3_CONF_VARS']['MAIL']['templateRootPaths']` for sending the
HTML content. For sending plaintext content, a file `TipsAndTricks.txt`
should exist.

Defining a custom email subject in a custom Fluid template (this only works if "format" is set to FluidEmail::FORMAT_HTML):

```html
<f:section name="Subject">New Login at "{typo3.sitename}"</f:section>
```

Building templated emails with Fluid also allows to define the language key,
and use this within the Fluid template:

**EXT:my_extension/Classes/MyClass.php (excerpt)**

```php
$email = new FluidEmail();
$email
    ->to('contact@example.org')
    ->assign('language', 'de');
```

In Fluid, you can now use the defined language key ("language"):

```html
<f:translate languageKey="{language}" id="my_extension.emails:subject" />
```

#### Set the current request object for `FluidEmail` {#mail-fluid-email-set-request}

In order to use ViewHelpers that need a valid current request, such as [Uri.page ViewHelper \<f:uri.page>](https://docs.typo3.org/other/typo3/view-helper-reference/main/en-us/Global/Uri/Page.html#typo3-fluid-uri-page),
pass the current request to the FluidEmail instance:

```php
use TYPO3\CMS\Core\Mail\FluidEmail;

$email = new FluidEmail();
$email->setRequest($this->request);
```

Read more aboout [Getting the PSR-7 request object](https://docs.typo3.org/permalink/t3coreapi:getting-typo3-request-object@main) in different
contexts.

In a context where no valid request object can be retrieved, such as in a
[Console command](https://docs.typo3.org/permalink/t3coreapi:symfony-console-commands@main) a valid frontend context need to be
simulated ([Simulating a frontend request in TYPO3 Commands](https://docs.typo3.org/permalink/t3coreapi:console-command-tutorial-fe-request-example@main))
or the affected ViewHelpers cannot be used.

Trying to use these ViewHelpers without a valid request throws an [error](https://docs.typo3.org/m/typo3/reference-exceptions/main/en-us/Exceptions/1639819269.html)
like the following:

**Example error output**

```text
[ERROR] The rendering context of ViewHelper f:link.page is missing a valid request object.
```

### Send email of type `MailMessage` with an injected `MailerInterface` {#mail-mail-message}

<!-- TODO: no Markdown rendering for "versionchanged" -->

The following methods have been removed:TYPO3\CMS\Core\Mail\MailMessage->send()TYPO3\CMS\Core\Mail\MailMessage->isSent()

`\TYPO3\CMS\Core\Mail\MailMessage` can be used to generate an email
without using Fluid. The email can then be sent via the injected interface
`\TYPO3\CMS\Core\Mail\MailerInterface`.

**EXT:site_package/Classes/Controller/MyMailerController.php**

```php
<?php

use Symfony\Component\Mime\Address;
use TYPO3\CMS\Core\Mail\MailerInterface;
use TYPO3\CMS\Core\Mail\MailMessage;

final readonly class MyMailerController
{
  public function __construct(
    private MailerInterface $mailer,
  ) {}

  /**
   * @throws \Symfony\Component\Mailer\Exception\TransportExceptionInterface
   */
  public function sendMail()
  {
    $email = new MailMessage();
    // Prepare and send the message
    $email
        // Defining the "From" email address and name as an object
        // (email clients will display the name)
        ->from(new Address('john.doe@example.org', 'John Doe'))

        // Set the "To" addresses
        ->to(
          new Address('receiver@example.org', 'Max Mustermann'),
          new Address('other@example.org'),
        )

        // Give the message a subject
        ->subject('Your subject')

        // Give it the text message
        ->text('Here is the message itself')

        // And optionally an HTML message
        ->html('<p>Here is the message itself</p>')

        // Optionally add any attachments
        ->attachFromPath('/path/to/my-document.pdf');
    // And finally send it
    $this->mailer->send($email);
  }
}

```

## How to add attachments {#mail-attachments}

Attach files that exist in your file system:

**EXT:site_package/Classes/Utility/MyMailUtility.php**

```php
// Attach file to message
$email->attachFromPath('/path/to/documents/privacy.pdf');

// Optionally you can tell email clients to display a custom name for the file
$email->attachFromPath('/path/to/documents/privacy.pdf', 'Privacy Policy');

// Alternatively attach contents from a stream
$email->attach(fopen('/path/to/documents/contract.doc', 'r'));
```

## How to add inline media {#mail-inline}

Add some inline media like images in an email:

**EXT:site_package/Classes/Utility/MyMailUtility.php**

```php
// Get the image contents from a PHP resource
$email->embed(fopen('/path/to/images/logo.png', 'r'), 'logo');

// Get the image contents from an existing file
$email->embedFromPath('/path/to/images/signature.png', 'footer-signature');

// reference images using the syntax 'cid:' + "image embed name"
$email->html('<img src="cid:logo"> ... <img src="cid:footer-signature"> ...');
```

## How to set and use a default sender {#mail-sender}

It is possible to define a default email sender ("From:") in
**System > Settings > Configure Installation-Wide Options**:

**config/system/additional.php | typo3conf/system/additional.php**

```php
$GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromAddress'] = 'john.doe@example.org';
$GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromName'] = 'John Doe';
```

This is how you can use these defaults:

**EXT:site_package/Classes/Controller/MyMailerController.php**

```php
<?php

use TYPO3\CMS\Core\Mail\MailerInterface;
use TYPO3\CMS\Core\Mail\MailMessage;
use TYPO3\CMS\Core\Utility\MailUtility;

final readonly class MyMailerController
{
  public function __construct(
    private MailerInterface $mailer,
  ) {}

  /**
   * @throws \Symfony\Component\Mailer\Exception\TransportExceptionInterface
   */
  public function sendMail(MailMessage $email)
  {
    // As getSystemFrom() returns an array we need to use the setFrom method
    $email->setFrom(MailUtility::getSystemFrom());
    $this->mailer->send($email);
  }
}

```

## Register a custom mailer {#register-custom-mailer}

To be able to use a custom mailer implementation in TYPO3, the interface
`\TYPO3\CMS\Core\Mail\MailerInterface` is available, which extends
`\Symfony\Component\Mailer\MailerInterface`. By default,
`\TYPO3\CMS\Core\Mail\Mailer` is registered as implementation.

After implementing your custom mailer, add the following lines into the
[`Configuration/Services.yaml`](../../ExtensionArchitecture/FileStructure/Configuration/ServicesYaml.md#file-extension-configuration-services-yaml) file to ensure that your custom
mailer is used.

**EXT:site_package/Configuration/Services.yaml**

```yaml
TYPO3\CMS\Core\Mail\MailerInterface:
    alias: MyVendor\SitePackage\Mail\MyCustomMailer
```

## PSR-14 events on sending messages {#mail-psr-14-events}

Some PSR-14 events are available:

-   [BeforeMailerSentMessageEvent](https://docs.typo3.org/permalink/t3coreapi:beforemailersentmessageevent@main) to manipulate messages before they are
    sent by the mailer.
-   [AfterMailerSentMessageEvent](https://docs.typo3.org/permalink/t3coreapi:aftermailersentmessageevent@main) to further process a sent message.

## Symfony mail documentation {#mail-symfony-mime}

Please refer to the Symfony documentation for more information about
available methods.

> [!NOTE]
> **See also**
>
> -   [The Mime Component](https://symfony.com/doc/current/components/mime.html)
> -   [Sending Emails with Mailer](https://symfony.com/doc/current/mailer.html)
