diff --git a/core/core.services.yml b/core/core.services.yml index 5399bc7..c7cadab 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -487,6 +487,9 @@ services: flood: class: Drupal\Core\Flood\DatabaseBackend arguments: ['@database', '@request'] + mail.factory: + class: Drupal\Core\Mail\MailFactory + arguments: ['@config.factory'] plugin.manager.condition: class: Drupal\Core\Condition\ConditionManager arguments: ['@container.namespaces', '@cache.cache', '@language_manager', '@module_handler'] diff --git a/core/includes/mail.inc b/core/includes/mail.inc index ce1df77..5c8117d 100644 --- a/core/includes/mail.inc +++ b/core/includes/mail.inc @@ -200,98 +200,21 @@ function drupal_mail($module, $key, $to, $langcode, $params = array(), $from = N /** * Returns an object that implements Drupal\Core\Mail\MailInterface. * - * Allows for one or more custom mail backends to format and send mail messages - * composed using drupal_mail(). - * - * An implementation needs to implement the following methods: - * - format: Allows to preprocess, format, and postprocess a mail - * message before it is passed to the sending system. By default, all messages - * may contain HTML and are converted to plain-text by the - * Drupal\Core\Mail\PhpMail implementation. For example, an alternative - * implementation could override the default implementation and additionally - * sanitize the HTML for usage in a MIME-encoded e-mail, but still invoking - * the Drupal\Core\Mail\PhpMail implementation to generate an alternate - * plain-text version for sending. - * - mail: Sends a message through a custom mail sending engine. - * By default, all messages are sent via PHP's mail() function by the - * Drupal\Core\Mail\PhpMail implementation. - * - * The selection of a particular implementation is controlled via the config - * 'system.mail.interface', which is a keyed array. The default implementation - * is the class whose name is the value of 'default' key. A more specific match - * first to key and then to module will be used in preference to the default. To - * specify a different class for all mail sent by one module, set the class - * name as the value for the key corresponding to the module name. To specify - * a class for a particular message sent by one module, set the class name as - * the value for the array key that is the message id, which is - * "${module}_${key}". - * - * For example to debug all mail sent by the user module by logging it to a - * file, you might set the variable as something like: - * - * @code - * array( - * 'default' => 'Drupal\Core\Mail\PhpMail', - * 'user' => 'DevelMailLog', - * ); - * @endcode - * - * Finally, a different system can be specified for a specific e-mail ID (see - * the $key param), such as one of the keys used by the contact module: - * - * @code - * array( - * 'default' => 'Drupal\Core\Mail\PhpMail', - * 'user' => 'DevelMailLog', - * 'contact_page_autoreply' => 'DrupalDevNullMailSend', - * ); - * @endcode - * - * Other possible uses for system include a mail-sending class that actually - * sends (or duplicates) each message to SMS, Twitter, instant message, etc, or - * a class that queues up a large number of messages for more efficient bulk - * sending or for sending via a remote gateway so as to reduce the load - * on the local server. - * - * @param $module + * @param string $module * The module name which was used by drupal_mail() to invoke hook_mail(). - * @param $key + * @param string $key * A key to identify the e-mail sent. The final e-mail ID for the e-mail * alter hook in drupal_mail() would have been {$module}_{$key}. * * @return Drupal\Core\Mail\MailInterface + * An object that implements Drupal\Core\Mail\MailInterface. * * @throws \Exception + * + * @see \Drupal\Core\Mail\MailFactory::get() */ function drupal_mail_system($module, $key) { - $instances = &drupal_static(__FUNCTION__, array()); - - $id = $module . '_' . $key; - - $configuration = Drupal::config('system.mail')->get('interface'); - - // Look for overrides for the default class, starting from the most specific - // id, and falling back to the module name. - if (isset($configuration[$id])) { - $class = $configuration[$id]; - } - elseif (isset($configuration[$module])) { - $class = $configuration[$module]; - } - else { - $class = $configuration['default']; - } - - if (empty($instances[$class])) { - $interfaces = class_implements($class); - if (isset($interfaces['Drupal\Core\Mail\MailInterface'])) { - $instances[$class] = new $class(); - } - else { - throw new Exception(t('Class %class does not implement interface %interface', array('%class' => $class, '%interface' => 'Drupal\Core\Mail\MailInterface'))); - } - } - return $instances[$class]; + return Drupal::service('mail.factory')->get($module, $key); } /** diff --git a/core/lib/Drupal/Core/Mail/MailFactory.php b/core/lib/Drupal/Core/Mail/MailFactory.php new file mode 100644 index 0000000..d6bef9f --- /dev/null +++ b/core/lib/Drupal/Core/Mail/MailFactory.php @@ -0,0 +1,126 @@ +mailConfig = $configFactory->get('system.mail'); + } + + + /** + * Returns an object that implements \Drupal\Core\Mail\MailInterface. + * + * Allows for one or more custom mail backends to format and send mail messages + * composed using drupal_mail(). + * + * The selection of a particular implementation is controlled via the config + * 'system.mail.interface', which is a keyed array. The default + * implementation is the class whose name is the value of 'default' key. A + * more specific match first to key and then to module will be used in + * preference to the default. To specify a different class for all mail sent + * by one module, set the class name as the value for the key corresponding to + * the module name. To specify a class for a particular message sent by one + * module, set the class name as the value for the array key that is the + * message id, which is "${module}_${key}". + * + * For example to debug all mail sent by the user module by logging it to a + * file, you might set the variable as something like: + * + * @code + * array( + * 'default' => 'Drupal\Core\Mail\PhpMail', + * 'user' => 'DevelMailLog', + * ); + * @endcode + * + * Finally, a different system can be specified for a specific e-mail ID (see + * the $key param), such as one of the keys used by the contact module: + * + * @code + * array( + * 'default' => 'Drupal\Core\Mail\PhpMail', + * 'user' => 'DevelMailLog', + * 'contact_page_autoreply' => 'DrupalDevNullMailSend', + * ); + * @endcode + * + * Other possible uses for system include a mail-sending class that actually + * sends (or duplicates) each message to SMS, Twitter, instant message, etc, + * or a class that queues up a large number of messages for more efficient + * bulk sending or for sending via a remote gateway so as to reduce the load + * on the local server. + * + * @param string $module + * The module name which was used by drupal_mail() to invoke hook_mail(). + * @param string $key + * A key to identify the e-mail sent. The final e-mail ID for the e-mail + * alter hook in drupal_mail() would have been {$module}_{$key}. + * + * @return \Drupal\Core\Mail\MailInterface + * An object that implements Drupal\Core\Mail\MailInterface. + * + * @throws \Exception + */ + public function get($module, $key) { + $id = $module . '_' . $key; + + $configuration = $this->mailConfig->get('interface'); + + // Look for overrides for the default class, starting from the most specific + // id, and falling back to the module name. + if (isset($configuration[$id])) { + $class = $configuration[$id]; + } + elseif (isset($configuration[$module])) { + $class = $configuration[$module]; + } + else { + $class = $configuration['default']; + } + + if (empty($this->instances[$class])) { + $interfaces = class_implements($class); + if (isset($interfaces['Drupal\Core\Mail\MailInterface'])) { + $this->instances[$class] = new $class(); + } + else { + throw new \Exception(String::format('Class %class does not implement interface %interface', array('%class' => $class, '%interface' => 'Drupal\Core\Mail\MailInterface'))); + } + } + return $this->instances[$class]; + } + +} diff --git a/core/lib/Drupal/Core/Mail/MailInterface.php b/core/lib/Drupal/Core/Mail/MailInterface.php index 3485cfd..d3e3173 100644 --- a/core/lib/Drupal/Core/Mail/MailInterface.php +++ b/core/lib/Drupal/Core/Mail/MailInterface.php @@ -15,6 +15,14 @@ /** * Formats a message composed by drupal_mail() prior sending. * + * Allows to preprocess, format, and postprocess a mail message before it is + * passed to the sending system. By default, all messages may contain HTML and + * are converted to plain-text by the Drupal\Core\Mail\PhpMail implementation. + * For example, an alternative implementation could override the default + * implementation and additionally sanitize the HTML for usage in a + * MIME-encoded e-mail, but still invoking the Drupal\Core\Mail\PhpMail + * implementation to generate an alternate plain-text version for sending. + * * @param array $message * A message array, as described in hook_mail_alter(). *