2

How does a module tell Drupal which mail plugin should be used? The SMTP Authentication Support module uses the following code in the submission handler of its settings form.

$values = $form_state->getValues();
$config = $this->configFactory->getEditable('smtp.settings');
$mail_config = $this->configFactory->getEditable('system.mail');
$mail_system = $mail_config->get('interface');

// Updating config vars.
if (isset($values['smtp_password'])) {
  $config->set('smtp_password', $values['smtp_password']);
}
$config->set('smtp_on', $values['smtp_on'])
  ->set('smtp_host', $values['smtp_host'])
  ->set('smtp_hostbackup', $values['smtp_hostbackup'])
  ->set('smtp_port', $values['smtp_port'])
  ->set('smtp_protocol', $values['smtp_protocol'])
  ->set('smtp_username', $values['smtp_username'])
  ->set('smtp_from', $values['smtp_from'])
  ->set('smtp_fromname', $values['smtp_fromname'])
  ->set('smtp_allowhtml', $values['smtp_allowhtml'])
  ->set('smtp_debugging', $values['smtp_debugging'])
  ->save();

// If an address was given, send a test e-mail message.
if ($test_address = $values['smtp_test_address']) {
  $params['subject'] = t('Drupal SMTP test e-mail');
  $params['body'] = array(t('If you receive this message it means your site is capable of using SMTP to send e-mail.'));
  $account = \Drupal::currentUser();
  // If module is off, send the test message with SMTP by temporarily overriding.
  if (!$config->get('smtp_on')) {
    $original = $mail_config->get('interface');
    $mail_system['default'] = 'SMTPMailSystem';
    $mail_config->set('interface', $mail_system)->save();
  }
  \Drupal::service('plugin.manager.mail')->mail('smtp', 'smtp-test', $test_address, $account->getPreferredLangcode(), $params);
  if (!$config->get('smtp_on')) {
    $mail_config->set('interface', $original)->save();
  }
  drupal_set_message(t('A test e-mail has been sent to @email via SMTP. You may want to check the log for any error messages.', ['@email' => $test_address]));
}

This code is not working, since in the log set with the mail.log directive I see the following, where it is evident that Drupal is still using the mail plugin definined in PhpMail.php.

[11-Mar-2016 06:36:14 UTC] mail() on [/home/domain/public_html/core/lib/Drupal/Core/Mail/Plugin/Mail/PhpMail.php:101]: To: edited@email.org -- Headers: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8; format=flowed; delsp=yes Content-Transfer-Encoding: 8Bit X-Mailer: Drupal Sender: edited@email.org From: Edited <edited@email.org>

I cleared the log before sending the test email from the administrative page of the SMTP Authentication Support module; so, I am sure the log is caused from sending the test email.

Since the method used from this module doesn't seem to work, what is the correct way to set the plugin Drupal uses to send emails?

Update

To make my question clearer, there are two things that are not clear to me in the code being used.

  1. The code is setting the mail plugin Drupal should use, just for the test email, but as I can see that method doesn't work, since Drupal still uses the default plugin.
  2. Apart from setting the mail plugin for the test email, the module doesn't change the mail plugin set by Drupal. How can Drupal know to use the mail plugin implemented by the module, then?
7
  • I think it is doing so appropriately though perhaps there's a interface.MODULE_NAME entry somewhere that's overriding it? I am also not sure if plugin ids can have capital letters or not.
    – mradcliffe
    Mar 11, 2016 at 16:53
  • I updated the question; I was missing a part of the code.
    – apaderno
    Mar 11, 2016 at 17:57
  • IMHO, modules like that shouldn't ever mess with that configuration directly. Modules like that should rely on drupal.org/project/mailsystem which provides a UI to configure the used default or by module/key mail plugin. It also has its own separate configuration, so if you have that enabled, then the config changes above won't do anything.
    – Berdir
    Mar 11, 2016 at 20:47
  • @Berdir Still, that module needs to tell Drupal which mail plugin should be used. I am more interesting in how telling Drupal which mail plugin to use, rather than using a module. I looked at the code of that module just because it implements a mail plugin.
    – apaderno
    Mar 13, 2016 at 17:04
  • Someone has to do it, yes. My point is that it's not the module that should do it, because the way to do it can very based on whatever implementation of MailManager you happen to use. If you do not have mailsystem installed, it's in system.mail.yml. Either the default, or a per module or per module/key. See api.drupal.org/api/drupal/….
    – Berdir
    Mar 13, 2016 at 17:09

1 Answer 1

0

Basing on Mail backends are now annotated plugins, drupal_mail_service() has been removed and the documentation for the MailManagerInterface interface, a module implementing a mail plugin should not set its own plugin as default plugin because MailManagerInterface interface doesn't document any configuration key the classes implementing it should use; only the site maintainer eventually know which mail manager is being used, and which configuration keys that mail manager is using. This is similar to setting the cache handlers, which is done in the settings.php file.

The SMTP Authentication module is doing the correct thing when it doesn't set its plugin as default plugin for sending emails.

As for the code to send a test email, the correct one should not directly set the configuration keys, if it wants to be independent from the current implementation of the mail manager. Eventually, code similar to the following should be used.

$mailer = \Drupal::service('plugin.manager.mail')->createInstance($plugin_id);
$bool = $mailer->send($mailer->format($message));

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.