Problem/Motivation

#3379794: Add symfony mailer transports to Dependency Injection Container (mail delivery layer) added an experimental mailer module to the 11.4 branch. However, there is already an active mailer project in contrib. Users of the contrib project will run into errors when upgrading to 11.4 unless steps are taken to resolve the namespace conflict. There are two possible ways to resolve the conflict. Either rename the core module or rename the contrib project.

Steps to reproduce

Proposed resolution

Option A: Rename contrib project

Rough steps necessary for the contrib author:

  • Register a new project under a new name. Move all code over there.
  • Release a new version, deprecate everything in there, declare incompatibility with core >= 11.4

Rough steps necessary for contrib users:

  • Install the new module.
  • Rewrite all existing custom code to use the new contrib namespace.
  • Uninstall the contrib mailer module and remove it from composer.

Option B: Rename the experimental core mailer

Rough steps necessary for core:

  • Come up with a new name which is not already taken.
  • File a PR which renames the module before 11.4 is released.

Option C: Remove experimental core mailer

Rough steps necessary for core:

  1. Move the test modules to system
  2. Move the tests to core/tests
  3. Delete the help hook
  4. Move the services to core/experimental/mailer.services.yml (name and location up for discussion)

Remaining tasks

  • Finalise the approach (option c is looking the most likely)

Post merge tasks

Update the following documentation:

  1. The change record
  2. Experimental modules page
  3. Experimental modules and themes in Drupal core

User interface changes

Introduced terminology

API changes

Data model changes

Release notes snippet

Issue fork drupal-3542264

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

znerol created an issue. See original summary.

znerol’s picture

Tagging with 11.3 release priority. This needs to be resolved before release.

adamps’s picture

The contrib module is currently not compatible with D11 and also has only 34 sites that report using it.

When the mailer ceases to be experimental, do we still need a Core module? If so, then I feel we should keep the name "mailer". If this is only a temporary module, then one option is to give it a name that indicates the temporary status.

znerol’s picture

I tried what happens on a site where the contrib mailer module is enabled during an upgrade. The contrib mailer module doesn't have a Drupal 11 release ready, so I had to patch it.

This is what I did:

Install Drupal 11 and drush:

composer create-project --no-interaction "drupal/recommended-project:^11" mailer-contrib-test
cd mailer-contrib-test
composer require -W drush/drush

Install the contrib mailer and patch for D11 compatibility:

composer require mglaman/composer-drupal-lenient
composer config --merge --json extra.drupal-lenient.allowed-list '["drupal/mailer"]'
composer require 'drupal/mailer:^2.0@beta'
sed -i 's/^core_version_requirement.*/core_version_requirement: ^10 | ^11/' web/modules/contrib/mailer/mailer.info.yml web/modules/contrib/mailer/modules/mailer_example/mailer_example.info.yml

Run a database and install the site:

podman run -d --rm --network=host --name=drupal_memory --tmpfs=/var/lib/pg/data -e PGDATA=/var/lib/pg/data -e POSTGRES_PASSWORD=postgres -e POSTGRES_USER=postgres -e POSTGRES_DB=drupal docker.io/library/postgres:16
./vendor/bin/drush site-install --db-url=pgsql://postgres:postgres@localhost/drupal --no-interaction

Setup mailpit as sendmail binary:

chmod u=rwX,go=rX web/sites/default web/sites/default/*
echo "sendmail_path = ${HOME}/bin/mailpit sendmail" > web/sites/default/php.ini
export PHPRC="${PWD}/web/sites/default"

Enable the contrib mailer and the example module, generate login link, run the built-in webserver:

./vendor/bin/drush en mailer mailer_example
./vendor/bin/drush uli --no-browser --uri=http://localhost:8888
http://localhost:8888/user/reset/1/1755891039/btjHfkrOCd7x1nKu8KtRJ8DmHoNCpwxW548Ul0HLyJk/login
./vendor/bin/drush rs

Open the test page and mailpit in a second tab and confirm that mailer test mail gets delivered:

xdg-open 'http://localhost:8888/admin/config/system/mailer/example'
xdg-open 'http://localhost:8025/'

Upgrade the site to 11.x-dev:

composer require -W "drupal/core-recommended:^11.x-dev" "drupal/core-recipe-unpack:^11.x-dev" "drupal/core-project-message:^11.x-dev" "drupal/core-composer-scaffold:^11.x-dev" "drupal/core:11.x-dev"
./vendor/bin/drush updb
./vendor/bin/drush cr

Confirm that now there are two mailer modules in the filesystem:

find . -name mailer

Open the test form and do the test again.

Interestingly in my case after all these steps, things are still working as before. So, it looks like the contrib mailer module wins the race for the \Drupal\mailer namespace.

stijn.blomme’s picture

Maintainer of the mailer contrib module here.
The D11 version of this module is being worked on and will be available in the future.

Move the module
I am willing to move the module and rename, document, ... if the decision is made to keep the name of the core project.

Alter the core version
I prefer this option as this will be less work / effort for all people impacted.
I could move the project, and document this, but it would always be a pain for users of the contrib mailer module while updating existing websites.
As this is an API module the needed changes would involve altering the use statements of all mailer plugins in all projects using this module.

As potential errors would occur when updating Drupal Core and not mailer we can't expect people to have read the documentation / release notes of the mailer module. It's an option to place a note in the core release notes, but that would be weird for a module with only 34 reported installs.

Do nothing
If the plan is to only keep the core module in experimental phase, and then move the code to the core framework, this could potentially never impact any website. If the users of the contrib mailer module keep the experimental core module disabled and do not use the new functionality before frame work inclusion.

znerol’s picture

Thanks @stijn.blomme for your thoughts.

Do nothing

If the plan is to only keep the core module in experimental phase, and then move the code to the core framework, this could potentially never impact any website. If the users of the contrib mailer module keep the experimental core module disabled and do not use the new functionality before frame work inclusion.

This is more or less what I tested in #4. The important thing to realize here is that users of the contrib mailer module do not have the choice to enable or disable the experimental core module. Modules need to have a unique name. And it looks like a module from contrib seems to override a module in core with the same name.

But honestly, as a site owner I wouldn't want to risk having two modules with the same name in my source tree. The findings in #4 should be treated as anecdotal. This certainly doesn't proof that two modules with the same name will coexist peacefully over the lifetime of a site.

znerol’s picture

As potential errors would occur when updating Drupal Core and not mailer we can't expect people to have read the documentation / release notes of the mailer module.

The contrib mailer module doesn't have a D11 compatible release. So sites using the contrib mailer wouldn't be able to update to Drupal 11 anyway yet. The experimental core mailer module will not be backported to any Drupal 10 release.

znerol’s picture

Status: Active » Needs review

Opened an MR that renames mailer into mailer_experiment. In my eyes that name (a) underlines that the module will go away when the experiment is over and (b) it works as a feature flag.

znerol’s picture

Title: Resolve potential namespace conflict with contrib mailer module » Rename mailer module to mailer_symfony and avoid namespace conflict with contrib mailer module
Issue summary: View changes
znerol’s picture

The CR needs minor updates when this gets committed.

znerol’s picture

Issue summary: View changes
stijn.blomme’s picture

I was wondering if we sould also alter the module name? This is still 'Mailer' It might be clearer if the name is Mailer Symfony

Services are not yet renamed (mailer_symfony.services.yml)
- 30: Drupal\Core\Mailer\Transport\SendmailCommandValidationTransportFactory -> Drupal\Core\mailer_symfony\Transport\SendmailCommandValidationTransportFactory
- 38: Drupal\Core\Mailer\TransportServiceFactory -> Drupal\Core\mailer_symfony\TransportServiceFactory
- 41: Drupal\Core\Mailer\TransportServiceFactoryInterface -> Drupal\Core\mailer_symfony\TransportServiceFactoryInterface

Mailerhooks:
25: The Mailer module provides an experimental -> The Mailer Symfony module
25: nline documentation for the Mailer module< -> Mailer Symfony module
26: Should the link change?

src/Kernel/TransportTest.php
30: If we alter the name, these comments should mention mailer_symfony

berdir’s picture

I think we explicitly don't want to do use Symfony there, if they didn't like Symfony Mailer in contrib, then they also wont' like "Mailer Symfony". It's the underlying system, but the current direction is that we will provide our own API on top of it, just like Drupal as a whole is built on top of some Symfony components.

The name is much easier to change than the machine name, so there I think we could use Experimental, so I'd go with "Experimental Mail(er) API". We can change once it's no longer experimental.

We are also not renaming the Core component, there is no conflict here and things like "mailer DSN" is a concept of the Symfony Mailer component, not the module name.

znerol’s picture

My intention was to only change the module namespace. But of course, if there are two modules available with the same human readable name, that would be confusing.

znerol’s picture

StatusFileSize
new111.4 KB
new112.88 KB
new112.83 KB

Without rename:

Experimental Mailer:

Core Mailer Preview:

znerol’s picture

What about Core Mailer Preview?

longwave’s picture

What about just mail for the core module?

https://www.drupal.org/project/mail exists but seems to be abandoned, we could ask the maintainers whether we could take over the namespace?

And I am kind of tempted to see if we can move all mail related code into a module eventually - not all sites need or want mail, and it forces separation of concerns.

znerol’s picture

I do not think that mail is abandoned. At least, the mail.info.yml declares compatibility with Drupal 10.

https://git.drupalcode.org/project/mail/-/blob/8.x-1.x/mail.info.yml?ref...

longwave’s picture

The only commits since 2017 are Drupal 9 and 10 compatibility fixes, there are no published compatible releases and it is "seeking new maintainers", next week I will contact the maintainers and ask.

joachim’s picture

Mail module is my project for a new config-based mail system in core.
I've not managed to get any traction for getting it into core, but it's not abandoned.

longwave’s picture

https://www.drupal.org/project/email is a D7 only module that was merged into core for D8.

Trying to find something short and simple here, because I think mailer_symfony is both long-winded and could easily be confused with symfony_mailer.

stijn.blomme’s picture

@longwave in the meeting at 03/09/25 mails or email were also suggested.
https://www.drupal.org/project/drupal/issues/3544898#comment-16256380

Mails is still available, emails is indeed an unsupported d7 module.
mailer_symfony was selected as the module will provide a wrapper around the symfony_mailer component.

joachim’s picture

mailer module in core is just about sending emails, not at all about configuring / translating / altering / etc?

If so, its name should reflect that it's low-level.

What about using symfony_mailer, since the project page for that says it'll be retired after D11?

znerol’s picture

  • We are trying to avoid a namespace conflict with an existing contrib module. Claiming the namespace of another existing contrib module doesn't seem to make much sense.
  • The core mailer module isn't supposed to stay in core. It is a temporary container for a bunch of service definitions. The service implementations themselves are added to Drupal\Core\Mailer namespace directly. When enough of the implementation is stable, the service definitions will be moved to core.services.yml and the core mailer module goes straight from experimental to deprecated.

So, I'd suggest to either agree on a namespace which is available or just not do anything at all.

needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new91 bytes

The Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".

This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

joachim’s picture

> We are trying to avoid a namespace conflict with an existing contrib module. Claiming the namespace of another existing contrib module doesn't seem to make much sense.

One says it's to be retired, the other does not.

znerol’s picture

Status: Needs work » Needs review

Merge conflicts resolved.

longwave’s picture

Removing tag as this was dropped from 11.3.x.

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.

znerol’s picture

Merge conflicts resolved.

smustgrave’s picture

Maybe dumb question won't this cause issues if mailer is installed?

znerol’s picture

I did some tests in #4. Do you have another scenario in mind?

smustgrave’s picture

Status: Needs review » Reviewed & tested by the community

Rebased so no credit there.

Since this one has been sitting for a while I don't mind marking, I also verified my own comment in #32 (which was the same as #4) for the mailer module.

But know there was back n forth around the name, personally I think symfony in the name makes sense since that's what the module is centered around. Mailer sounds right but seems very vague.

znerol’s picture

Issue summary: View changes
alexpott’s picture

Status: Reviewed & tested by the community » Needs work

@longwave @catch  and I have discussed a new idea that involves completely removing the module:

  • Move the test modules to system
  • Move the tests to core/tests
  • Delete the help hook
  • Move the services to core/experimental/mailer.services.yml (name and location up for discussion)
  • Add a helper to tests to set the the container yamls in settings to make it simple to enable.

For local development it becomes a case of making a change to your settings.php to enable the services.

alexpott changed the visibility of the branch main to hidden.

alexpott changed the visibility of the branch 11.x to hidden.

alexpott’s picture

Status: Needs work » Needs review

Implemented #36 - it looks good to me. There's a way to add it to the container build for both...

Kernel tests

  /**
   * {@inheritdoc}
   */
  public function register(ContainerBuilder $container): void {
    $yaml_loader = new YamlFileLoader($container);
    $yaml_loader->load($this->root . '/core/experimental/mailer.services.yml');
  }

Functional tests

   */
  protected function prepareSettings(): void {
    parent::prepareSettings();

    // Load the mailer.services.yml file.
    $filename = $this->siteDirectory . '/settings.php';
    $line = "\n\$settings['container_yamls'][] = '" . $this->root . "/core/experimental/mailer.services.yml';\n";
    file_put_contents($filename, $line, FILE_APPEND);
  }
alexpott’s picture

Issue summary: View changes
alexpott’s picture

Realised we can do this in an even nicer way by providing a trait for kernel tests and modules that wish to experiment to use... and we can use it in our own test module... so

Kernel tests

Add in the trait Drupal\Core\Experimental\MailerServicesTrait

Functional tests

Add core_mailer_services_testto the modules list.

Contrib experiments

Add a service provider (a class in src/ModuleNameServiceProvider.php that implements ServiceProviderInterface) and use the Drupal\Core\Experimental\MailerServicesTrait.

Local dev

Add $settings['container_yamls'][] = $app_root . '/core/experimental/mailer.services.yml'; to your settings.php

znerol’s picture

I thought about a $servicesFiles property on the test class analogous to $modules. This wouldn't work with a trait though, the test base classes would need to do the heavy lifting. But it would be more generic than the trait.

alexpott’s picture

@znerol and that would involve change to the test system and this involves none and provides a simple way for contrib to opt-in too.

znerol’s picture

  1. Would it be possible to use the same mechanism for both kinds of tests? Analogous to mailer_capture module. The trait could be inlined into the service provider class and then there wouldn't be any need for the instanceof conditional.
  2. The mailer_capture module doesn't have a _test suffix. It doesn't really act as a test double (like the other _test modules) but more like a feature flag. I wonder whether there is a pattern we could use to differentiate reusable feature flags / fixture from regular test double style modules. How about:
    • mailer_capture -> mailer_capture_fixture
    • core_mailer_services_test -> mailer_services_fixture
  3. I'd expect the services yaml file in the sites directory. Side-by-side to the existing sites/development.services.yml. Maybe sites/experimental.mailer.services.yml.
alexpott’s picture

  1. Kernel tests could just enable the test module - but there's no need - the same trait just works fine - so why do that?
  2. Just i noticed that - at best this feels like a follow-up but this is follow-up material and not necessary to solve here.
  3. I don't think that we should be shipping this in the sites directory. We've never shipped an experimental services file before this is a new pattern I don't think there an really any expectations to meet here.
longwave’s picture

Can't kernel tests install core_mailer_services_test too? Then we don't need the trait and have one unified way of setting it up.

longwave’s picture

Probably too early to think about this but if we do #3111008: Use native Symfony YamlFileLoader and later enable imports in YAML then we could split up core.services.yml into more manageable chunks. Mailer could just be one of those chunks, that isn't included by default, but one day we just switch it on by including it globally.

alexpott’s picture

@longwave yes they can but the trait is really nice for any contrib that wants to depend on the services and explore using them. I'm fine to drop it and then contrib can just copy the service provider from the test module and be done...

alexpott’s picture

Removed the trait - now everything is using the test module to add the services to the container. And any contrib module can just add a service provider in the same way.

znerol’s picture

Approach C requires updates to documentation. At least:

  1. The change record
  2. Experimental modules page
  3. Experimental modules and themes in Drupal core

1 needs to reworded for the new approach, 2 can be removed completely, 3 can be updated to not mention mailer. But maybe we'd need a new policy page which describes the experimental feature approach this issue introduces. Should that be a follow-up as well?

alexpott’s picture

Issue summary: View changes
Issue tags: +Needs change record updates

#51 has great points... tagging for the CR update. I think it is okay to leave the policy thing to a follow-up that we should create now. Will do that later today. FWIW option B would require editing all those pages too. So I've copied the list to the issue summary to ensure it is not lost when we merge.

stijn.blomme’s picture

I really like option C.
It was always the plan to remove the module after acceptance into core. This approach eliminates the overhead of a later transition and the risk of bugs during that phase.
The services being in the right place from the start will make it easier for contrib to start supporting the new functionality when not stable.
Services are namespaced so this approach also removes the naming conflict with contrib modules.