Essential Configuration 

After completing the Azure Configuration, you need to configure the TYPO3 extension with the values obtained from Microsoft Entra ID.

Quick Navigation 

This page covers the complete configuration setup for the Exchange 365 TYPO3 extension:

Configuration Variables 

The extension reads its settings from $GLOBALS['TYPO3_CONF_VARS']['MAIL']. The keys are prefixed with transport_exchange365_ to avoid conflicts with other mail transports. These settings are used everywhere — backend, CLI, scheduler and, unless TypoScript overrides them, the frontend.

The steps below write them as environment variables named TYPO3_CONF_VARS__MAIL__…, which keeps every secret out of files that end up in version control.

  1. Set the mail transport to Exchange365Transport.

    Configure TYPO3 to use the Exchange 365 transport instead of the default SMTP transport.

    TYPO3_CONF_VARS__MAIL__transport=OliverKroener\\OkExchange365\\Mail\\Transport\\Exchange365Transport
    Copied!
  2. Configure the Tenant ID.

    Set the Tenant ID obtained from step 4 of the Azure Configuration.

    TYPO3_CONF_VARS__MAIL__transport_exchange365_tenantId='your-tenant-id-here'
    Copied!
  3. Configure the Client ID.

    Set the Client ID (Application ID) obtained from step 4 of the Azure Configuration.

    TYPO3_CONF_VARS__MAIL__transport_exchange365_clientId='your-client-id-here'
    Copied!
  4. Configure the Client Secret.

    Set the Client Secret value obtained from step 7 of the Azure Configuration.

    TYPO3_CONF_VARS__MAIL__transport_exchange365_clientSecret='your-client-secret-here'
    Copied!
  5. Configure the sender email address.

    Set the email address that will be used as the sender for all emails sent through this transport.

    TYPO3_CONF_VARS__MAIL__transport_exchange365_fromEmail='service@your-domain.com'
    Copied!
  6. Configure the Graph sender user ID (optional).

    Set the Microsoft Graph mailbox/user ID that is used for the /users/{id}/sendMail API call. This is intentionally separate from the message From address, so you can send as or on behalf of a different mailbox (Send As / Send On Behalf scenarios).

    TYPO3_CONF_VARS__MAIL__transport_exchange365_graphSenderUserId='shared-mailbox@your-domain.com'
    Copied!
  7. Configure save to sent items (optional).

    Determine whether sent emails should be saved to the sender's "Sent Items" folder.

    TYPO3_CONF_VARS__MAIL__transport_exchange365_saveToSentItems=1
    Copied!

Configuration Example 

Here's a complete example of all required configuration variables:

TYPO3 configuration showing Exchange365 transport variables setup

Environment Variables (.env file) 

You can configure these settings using a .env file in your TYPO3 root directory:

# Exchange 365 Mail Transport Configuration
TYPO3_CONF_VARS__MAIL__transport=OliverKroener\\OkExchange365\\Mail\\Transport\\Exchange365Transport
TYPO3_CONF_VARS__MAIL__transport_exchange365_tenantId='your-tenant-id-here'
TYPO3_CONF_VARS__MAIL__transport_exchange365_clientId='your-client-id-here'
TYPO3_CONF_VARS__MAIL__transport_exchange365_clientSecret='your-client-secret-here'
TYPO3_CONF_VARS__MAIL__transport_exchange365_fromEmail='service@your-domain.com'
# Optional: Graph sender mailbox (Send As / Send On Behalf).
#TYPO3_CONF_VARS__MAIL__transport_exchange365_graphSenderUserId='account1@your-domain.com'
TYPO3_CONF_VARS__MAIL__transport_exchange365_saveToSentItems=1
Copied!

Alternative Configuration Methods 

Mapping TYPO3_CONF_VARS__… variables 

If your project does not already map TYPO3_CONF_VARS__… environment variables, add this loop. Double underscores become array levels, so TYPO3_CONF_VARS__MAIL__transport_exchange365_clientSecret ends up in $GLOBALS['TYPO3_CONF_VARS']['MAIL']['transport_exchange365_clientSecret'].

public/typo3conf/AdditionalConfiguration.php
<?php

// Variables loaded by a dotenv library live in $_ENV, variables set by the
// web server or container in getenv(). Read both.
foreach (array_merge(getenv(), $_ENV) as $name => $value) {
    if (!is_string($name) || strpos($name, 'TYPO3_CONF_VARS__') !== 0) {
        continue;
    }
    $target = &$GLOBALS['TYPO3_CONF_VARS'];
    foreach (explode('__', substr($name, strlen('TYPO3_CONF_VARS__'))) as $segment) {
        $target = &$target[$segment];
    }
    $target = $value;
    unset($target);
}
Copied!

In TYPO3 configuration files, reading the environment 

Without the mapping, set the values in public/typo3conf/AdditionalConfiguration.php and read the secrets from the environment there. Use your own variable names:

public/typo3conf/AdditionalConfiguration.php
<?php

$env = static fn (string $name): string => (string)(getenv($name) ?: ($_ENV[$name] ?? ''));

$GLOBALS['TYPO3_CONF_VARS']['MAIL']['transport'] = \OliverKroener\OkExchange365\Mail\Transport\Exchange365Transport::class;
$GLOBALS['TYPO3_CONF_VARS']['MAIL']['transport_exchange365_tenantId'] = $env('EXCHANGE365_TENANT_ID');
$GLOBALS['TYPO3_CONF_VARS']['MAIL']['transport_exchange365_clientId'] = $env('EXCHANGE365_CLIENT_ID');
$GLOBALS['TYPO3_CONF_VARS']['MAIL']['transport_exchange365_clientSecret'] = $env('EXCHANGE365_CLIENT_SECRET');
$GLOBALS['TYPO3_CONF_VARS']['MAIL']['transport_exchange365_fromEmail'] = 'service@your-domain.com';
// Optional: distinct Graph sender mailbox (Send As / Send On Behalf).
// $GLOBALS['TYPO3_CONF_VARS']['MAIL']['transport_exchange365_graphSenderUserId'] = 'account1@your-domain.com';
$GLOBALS['TYPO3_CONF_VARS']['MAIL']['transport_exchange365_saveToSentItems'] = 1;
Copied!

Testing the Configuration 

After configuring all variables, you can test the email functionality by:

  1. Sending a test email through TYPO3's mail functionality
  2. Checking the TYPO3 logs for any error messages
  3. Verifying that emails are received at the intended recipients
  4. Checking the sender's "Sent Items" folder if saveToSentItems is enabled

Security Considerations 

Configuration Validation 

To verify your configuration is correct:

  1. Check in backend:

    • Open Admin Tools > Environment > Test Mail Setup and send a test mail
    • Ensure the transport is set to Exchange365Transport and all required fields are filled
    TYPO3 Environment module showing the Test Mail Setup
  2. Check TYPO3 configuration:

    // In TYPO3 backend or debug context
    \TYPO3\CMS\Core\Utility\DebugUtility::debug($GLOBALS['TYPO3_CONF_VARS']['MAIL']);
    Copied!
  3. Test email sending:

    // Test email functionality
    $mail = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Mail\MailMessage::class);
    $mail->to('test@example.com')
        ->subject('Test Email')
        ->text('This is a test email from TYPO3.')
        ->send();
    Copied!
  4. Check logs: Monitor TYPO3 logs for authentication or sending errors. A failed send throws a Symfony TransportException (a RuntimeException) whose message names the cause, for example Exchange 365 configuration missing required field: clientSecret.

Automated tests 

This branch is covered by the cross-version test matrix that lives on the extension's main branch (make test-matrix / make test-matrix-live there). For TYPO3 v11 it runs the unit and functional tests, PHPStan and the coding standard check, sends real mail through Microsoft Graph from the CLI and from the frontend (credentials via := getEnv()), and checks in a headless browser that the credentials are masked in the backend.