Problem

The problem occurs when upgrading from v1.2.x when both the following conditions are true:

  • symfony_mailer_bc was enabled
  • Some Mailer configuration import operations had been ignored (neither imported or skipped)

For more detail, see #7.

Workaround

Visit the mailer overrides page, and correct the settings - enable or import any overrides that are missing. Warning: this resets any changes you have made to the default configuration.

Proposed resolution

Fix the update hook as described in #8.

Original summary

On Override tab I enabled & imported User items.
And now the user tokens in the password reset emails are not replaced. Only [site:xxx] are replaced.

Explanation why it happens:
Password reset emails provide their own 'user' context token data. And user tokens are replaced AFTER text formatters are applied to the text.
If text formatters use "Replace tokens" with "Replace empty values" option checked, tokens will be deleted from text and mail provider will have text without tokens already.

What can I do?

Comments

super_romeo created an issue. See original summary.

adamps’s picture

Status: Active » Postponed (maintainer needs more info)

It works for me. UserEmailBuilder::build passes the callback user_mail_tokens.

nojj’s picture

after updating to V1.3.2 I seem to have the same issue.
Tokens are not replaced.
Even [site:name] is not replaced.
Any ideas?

Edit:
for me it was the policy of User Registration Password which was not activated by default. I had to activate override and enter the message again. now tokens are working.

vlad.dancer’s picture

Status: Postponed (maintainer needs more info) » Active

Ok. I had this issue too.
I think after updating symfony_mailer from 1.2.1 to 1.3.1 the new user policies from symfony_mailer were added but not enabled.
And LegacyEmailBuilder was used in symfony_mailer_mailer_builder_info_alter to build emails with user policies because override_manager->isEnabled can't find overrides in $\Drupal\symfony_mailer\Processor\OverrideManager::isEnabled $this->configFactory->get('symfony_mailer.settings')->get('override').

So @nojj is right in order to fix this issue we need to enable/disable user policies override.

vlad.dancer’s picture

Priority: Normal » Major

Changing priority since register user/restore password features are very important on many sites.

adamps’s picture

Status: Active » Postponed (maintainer needs more info)

I still don't understand how to reproduce the bug. #3 talks about User Registration Password. #4 talks about updating from v1.2. Neither one has a precise sequence of steps I can follow. The issue summary is totally missing the "Steps to reproduce" section which is essential for a bug report.

The following are both by design, not a bug

  1. Overrides are disabled by default
  2. If the user override is disabled then tokens won't work in a Mailer Policy - that's mixing up the old and new way of doing things
vlad.dancer’s picture

Status: Postponed (maintainer needs more info) » Active

I think there will be more bug reports in this issue.
I came to this issue when detected that user related emails were with raw tokens. But other people can detect this issue on different emails.

Steps to reproduce:

  • 1. Install latest drupal 9. Installing Drupal
  • 2. (optional) Install mailhog
  • 3. Go to restore password page, restore password and expect to receive email with token replaced.
  • 4. Install mailer 1.2.1: composer require 'drupal/symfony_mailer:1.2.1' --no-audit. Installing Modules
  • 5. Enable mailer: drush en symfony_mailer
  • 6. Configure best transport for you as default transport: /admin/config/system/mailer/transport. I'm using mailhog via SMTP.
  • 7. Go to restore password page, restore password and expect to receive email with token replaced.
  • 8. Enable symfony_mailer_bc: drush en symfony_mailer_bc
  • 10. Now in admin interface there is an error message: "There are Mailer configuration import operations pending: import." (Ignore it in order to reproduce the problem)
  • 11. Go to restore password, expect to receive email with token replaced
  • 12. Install mailer 1.3.1+: composer require 'drupal/symfony_mailer:1.3.1' && drush cr
  • 13. Go to restore password, expect to receive email with token replaced. Instead, email sent now with raw tokens without beeing replaced.

Summary

If you used 1.2.1 mailer with symfony_mailer_bc and then updated to 1.3+ using drush (without visiting admin interface) you'll end up with having mailer policies but with disabled overrides for them:

default_transport: sendmail
override: {}

Suggested way to fix

Provide runtime check in symfony_mailer_requirements to compare if mail policies exist and symfony_mailer.settings.override is empty.
If that was detected then suggest user to re-enable policy overrides or delete that policies.

Let me know if you need additional information or access to the test drupal instance.

vlad.dancer’s picture

adamps’s picture

Title: User tokens in Password reset email are not replaced » Override settings may be wrong after upgrade from 1.2.x
Issue summary: View changes

Great thanks for a detailed report and excellent debugging. The override setting is initialised in symfony_mailer_update_10008(). However if there was never any import or skip, then the old import key-value wasn't set, so the update hook doesn't work.

It's perfectly allowed to have a policy but no override. The policy could be to add a bcc, skip sending the message, or log it. So we can't rely on existing policy. Also we can't assume the overrides available now were also available in v1.2 as this module added commerce in v1.3.

I believe the correct fix is in the update hook.

  1. If symfony_mailer_bc is enabled then call OverrideManager::getInfo() to get a list of available overrides.
  2. Calculate the intersection of this with the overrides that were available in symfony_mailer_bc: contact, contact_form, simplenews_newsletter, simplenews, update, user, user_registrationpassword.
  3. If these are missing then set them to STATE_ENABLED.
vlad.dancer’s picture

Here is requirement check that can inform users to delete odd policies manually:

if ($phase == 'runtime' || $phase == 'update') {
    $version = \Drupal::service("extension.list.module")->getExtensionInfo('symfony_mailer')['version'] ?? 0;
    $affectedVersion = version_compare($version, '1.3.0', '>=');

    if ($affectedVersion) {
      $overrides = \Drupal::configFactory()->get('symfony_mailer.settings')->get("override") ?? FALSE;
      /** @var \Drupal\symfony_mailer\Entity\MailerPolicy[] $policies */
      $policies = \Drupal::entityTypeManager()->getListBuilder('mailer_policy')->load();

      $oddPolicies = [];

      /** @var \Drupal\symfony_mailer\Entity\MailerPolicy $entity */
      foreach ($policies as $entity) {
        $hasPolicyOfType = in_array($entity->getType(), ['user', 'update', 'contact']);
        $isDisabled = !isset($overrides[$entity->getType()]) || $overrides[$entity->getType()] === \Drupal\symfony_mailer\Processor\OverrideManagerInterface::STATE_DISABLED;

        if ($hasPolicyOfType && $isDisabled) {
          $oddPolicies[] = $entity->id();
        }
      }

      $corruptedState = empty($overrides) || count($oddPolicies) > 0;

      if ($corruptedState) {
        $args = [
          '@policies_link' => \Drupal\Core\Link::fromTextAndUrl(
            'Symfony Mailer policies overview page',
            \Drupal\Core\Url::fromUserInput('/admin/config/system/mailer', ['absolute' => TRUE])
          )->toString(),
          '@overrides_page' => \Drupal\Core\Link::fromTextAndUrl(
            'Symfony Mailer policy overrides page',
            \Drupal\Core\Url::fromUserInput('/admin/config/system/mailer/override', ['absolute' => TRUE])
          )->toString(),
        ];

        $description = t('Visit @policies_link to delete odd policies, or visit @overrides_page to delete in a bulk mode policy overrides of specific type.', $args);
        $requirements['symfony_mailer_wrong_overrides'] = [
          'title' => t('Disabled overrides with custom mailer policies detected'),
          'value' => t('Policies for update: @policies', ['@policies' => implode(', ', $oddPolicies)]),
          'severity' => REQUIREMENT_ERROR,
          'description' => $description,
        ];
      }
    }
  }

BTW: thanks for keeping original summary because lots of people will search by "User tokens in Password reset email are not replaced".

adamps’s picture

Status: Active » Needs review
StatusFileSize
new1.8 KB

Patch not fully tested yet

adamps’s picture

#10 is an interesting idea thanks. However (as I said in #9) it's perfectly allowed to have a policy but no override. The policy could be to add a bcc, skip sending the message, or log it.

vlad.dancer’s picture

Status: Needs review » Needs work

ParseError: syntax error, unexpected token ";" in /var/www/html/web/modules/contrib/symfony_mailer/symfony_mailer.install on line 202 #0 /var/www/html/web/core/includes/install.inc(87): Drupal\Core\Extension\ModuleHandler->loadInclude()

vlad.dancer’s picture

Status: Needs work » Needs review
StatusFileSize
new2.05 KB

Thank you @AdamPS, your fix works for me.

Just fixed syntax error and notices in your patch:

Undefined variable $settings symfony_mailer.install:201
> [error] array_key_exists(): Argument #2 ($array) must be of type array, null given
> [error] Update failed: symfony_mailer_update_10008

vlad.dancer’s picture

I've copied code from the patch not fully)
Now should work.

vlad.dancer’s picture

StatusFileSize
new2.08 KB

Heh. Hope this is last one.

vlad.dancer’s picture

StatusFileSize
new2.08 KB

Added ending line-feed.

  • AdamPS committed e18a2c2a on 1.x
    Issue #3392446 by vlad.dancer, AdamPS: Override settings may be wrong...
adamps’s picture

Great thanks

adamps’s picture

Status: Needs review » Fixed
giuseppe87’s picture

Am I wrong or this patch approach doesn't consider the case the updates of 1.4.0-beta1 has been already done? Because the symfony_mailer_update_10008 symfony_mailer_update_10009 would have already run.

From a quick test setting the version to a previous state, e.g.

drush ev "\Drupal::service('update.update_hook_registry')->setInstalledVersion('symfony_mailer', 10007);"

and re-do the updates should work, but please correct me if this it is not right or necessary.

adamps’s picture

For sites that have already upgraded to 1.4.0-beta1, then symfony_mailer_update_10009 has removed the symfony_mailer_bc module, so symfony_mailer_update_10008 would have no effect. I can't see any possible automatic fix as the code can't tell if symfony_mailer_bc was previously installed - sorry.

The code in #21 should work if you manually enable symfony_mailer_bc again first.

giuseppe87’s picture

Yes, I can confirm that

drush en symfony_mailer_bc 
drush ev "\Drupal::service('update.update_hook_registry')->setInstalledVersion('symfony_mailer', 10007);"

fixed the token replacement in my site, even if already run the updates with 1-4.0-beta1.

Thank you.

michèle’s picture

I can confirm #23, too. Thank you!

But bear in mind, that you have to
drush en symfony_mailer_bc
again, after updatedb, as 10007 will disable the module.

kreatil’s picture

In my case, the method described under #23 also worked. However, afterwards I had to reactivate symfony_mailer_bc and go to admin/config/system/mailer/override and perform "User" > "Enable & Import". Why symfony_mailer_bc now has to be active again, even though it was declared as obsolete, is beyond me.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.