You are here

public function MailManager::doMail in Drupal 9

Same name and namespace in other branches
  1. 8 core/lib/Drupal/Core/Mail/MailManager.php \Drupal\Core\Mail\MailManager::doMail()

Composes and optionally sends an email message.

Parameters

string $module: A module name to invoke hook_mail() on. The {$module}_mail() hook will be called to complete the $message structure which will already contain common defaults.

string $key: A key to identify the email sent. The final message ID for email altering will be {$module}_{$key}.

string $to: The email address or addresses where the message will be sent to. The formatting of this string will be validated with the PHP email validation filter. Some examples are:

string $langcode: Language code to use to compose the email.

array $params: (optional) Parameters to build the email. Use the key '_error_message' to provide translatable markup to display as a message if an error occurs, or set this to false to disable error display.

string|null $reply: Optional email address to be used to answer.

bool $send: If TRUE, call an implementation of \Drupal\Core\Mail\MailInterface->mail() to deliver the message, and store the result in $message['result']. Modules implementing hook_mail_alter() may cancel sending by setting $message['send'] to FALSE.

Return value

array The $message array structure containing all details of the message. If already sent ($send = TRUE), then the 'result' element will contain the success indicator of the email, failure being already written to the watchdog. (Success means nothing more than the message being accepted at php-level, which still doesn't guarantee it to be delivered.)

See also

\Drupal\Core\Mail\MailManagerInterface::mail()

1 call to MailManager::doMail()
MailManager::mail in core/lib/Drupal/Core/Mail/MailManager.php
Composes and optionally sends an email message.
1 method overrides MailManager::doMail()
TestMailManager::doMail in core/tests/Drupal/Tests/Core/Mail/MailManagerTest.php
Composes and optionally sends an email message.

File

core/lib/Drupal/Core/Mail/MailManager.php, line 227

Class

MailManager
Provides a Mail plugin manager.

Namespace

Drupal\Core\Mail

Code

public function doMail($module, $key, $to, $langcode, $params = [], $reply = NULL, $send = TRUE) {
  $site_config = $this->configFactory
    ->get('system.site');
  $site_mail = $site_config
    ->get('mail');
  if (empty($site_mail)) {
    $site_mail = ini_get('sendmail_from');
  }

  // Bundle up the variables into a structured array for altering.
  $message = [
    'id' => $module . '_' . $key,
    'module' => $module,
    'key' => $key,
    'to' => $to,
    'from' => $site_mail,
    'reply-to' => $reply,
    'langcode' => $langcode,
    'params' => $params,
    'send' => TRUE,
    'subject' => '',
    'body' => [],
  ];

  // Build the default headers.
  $headers = [
    'MIME-Version' => '1.0',
    'Content-Type' => 'text/plain; charset=UTF-8; format=flowed; delsp=yes',
    'Content-Transfer-Encoding' => '8Bit',
    'X-Mailer' => 'Drupal',
  ];

  // To prevent email from looking like spam, the addresses in the Sender and
  // Return-Path headers should have a domain authorized to use the
  // originating SMTP server.
  $headers['From'] = $headers['Sender'] = $headers['Return-Path'] = $site_mail;

  // Make sure the site-name is a RFC-2822 compliant 'display-name'.
  if ($site_mail) {
    $mailbox = new MailboxHeader('From', new Address($site_mail, $site_config
      ->get('name') ?: ''));
    $headers['From'] = $mailbox
      ->getBodyAsString();
  }
  if ($reply) {
    $headers['Reply-to'] = $reply;
  }
  $message['headers'] = $headers;

  // Build the email (get subject and body, allow additional headers) by
  // invoking hook_mail() on this module. We cannot use
  // moduleHandler()->invoke() as we need to have $message by reference in
  // hook_mail().
  if (function_exists($function = $module . '_mail')) {
    $function($key, $message, $params);
  }

  // Invoke hook_mail_alter() to allow all modules to alter the resulting
  // email.
  $this->moduleHandler
    ->alter('mail', $message);

  // Retrieve the responsible implementation for this message.
  $system = $this
    ->getInstance([
    'module' => $module,
    'key' => $key,
  ]);

  // Attempt to convert relative URLs to absolute.
  foreach ($message['body'] as &$body_part) {
    if ($body_part instanceof MarkupInterface) {
      $body_part = Markup::create(Html::transformRootRelativeUrlsToAbsolute((string) $body_part, \Drupal::request()
        ->getSchemeAndHttpHost()));
    }
  }

  // Format the message body.
  $message = $system
    ->format($message);

  // Optionally send email.
  if ($send) {

    // The original caller requested sending. Sending was canceled by one or
    // more hook_mail_alter() implementations. We set 'result' to NULL,
    // because FALSE indicates an error in sending.
    if (empty($message['send'])) {
      $message['result'] = NULL;
    }
    else {

      // Ensure that subject is plain text. By default translated and
      // formatted strings are prepared for the HTML context and email
      // subjects are plain strings.
      if ($message['subject']) {
        $message['subject'] = PlainTextOutput::renderFromHtml($message['subject']);
      }
      $message['result'] = $system
        ->mail($message);

      // Log errors.
      if (!$message['result']) {
        $this->loggerFactory
          ->get('mail')
          ->error('Error sending email (from %from to %to with reply-to %reply).', [
          '%from' => $message['from'],
          '%to' => $message['to'],
          '%reply' => $message['reply-to'] ? $message['reply-to'] : $this
            ->t('not set'),
        ]);
        $error_message = $params['_error_message'] ?? $this
          ->t('Unable to send email. Contact the site administrator if the problem persists.');
        if ($error_message) {
          $this
            ->messenger()
            ->addError($error_message);
        }
      }
    }
  }
  return $message;
}