MailFactory is now a swappable service thanks to #1889644: Convert drupal_mail_system() to a MailFactory service to allow more flexible replacements. However, alternative implementations are hobbled by the lack of any kind of discovery mechanism for MailInterface classes.
For example, a contrib module like Mailsystem has no way of building a user interface for selecting mail methods, because it has no way of knowing what mail classes are available.
A simple and low-impact solution would be turn existing mail classes into annotated plugins and create a simple plugin manager for them. This would open up options for contrib.
Proposed change notice
Mail backends are now annotated plugins, and can be discovered and implemented via the new plugin.manager.mail
service.
The earlier mail.factory
service has been removed, and its functionality has been merged into plugin.manager.mail
.
Furthermore, the config setting system.mail.interface
, which identifies the mail plugin used for a particular message, now takes plugin IDs as values rather than class names.
Creating a mail plugin
To provide a new mail backend in a custom module named mymodule, you must implement Drupal\Core\Mail\MailInterface
within the \Drupal\mymodule\Plugin\Mail
namespace, and annotate the class:
<?php
namespace Drupal\mymodule\Plugin\Mail;
use Drupal\Core\Mail\MailInterface;
/**
* A custom mail backend.
*
* @Mail(
* id = "mymodule_mailer",
* label = @Translation("My custom mailer"),
* description = @Translation("An example mail plugin implementation.")
* )
*/
class MymoduleMailer implements MailInterface {
public function format(array $message) {
// ...
}
public function mail(array $message) {
// ...
}
}
?>
See the API documentation for MailInterface for implementation details.
Retrieving mail plugins
Previously in Drupal 8, there was no way to retrieve a list of MailInterface classes. Now, you can use the plugin.manager.mail
service:
<?php
// Get a keyed array of mail plugin definitions.
$definitions = \Drupal::service('plugin.manager.mail')->getDefinitions();
// Get a single definition by plugin ID.
$plugin_id = 'php_mail';
$definition = \Drupal::service('plugin.manager.mail')->getDefinition($plugin_id);
// Create an instance of a specific mail plugin.
$plugin_id = 'php_mail';
$mailer = \Drupal::service('plugin.manager.mail')->createInstance($plugin_id);
?>
Mail plugin selection
The Drupal 8 config setting system.mail.interface
is a keyed array that maps the message ID to the mail plugin it should use. The values used in this array are now plugin IDs.
Before in Drupal 8
<?php
\Drupal::config('system.mail')->set('interface.default', 'Drupal\Core\Mail\Plugin\Mail\PhpMail')->save();
?>
After
<?php
\Drupal::config('system.mail')->set('interface.default', 'php_mail')->save();
?>