public function MailManager::mail in Zircon Profile 8
Same name and namespace in other branches
- 8.0 core/lib/Drupal/Core/Mail/MailManager.php \Drupal\Core\Mail\MailManager::mail()
Composes and optionally sends an email message.
Sending an email works with defining an email template (subject, text and possibly email headers) and the replacement values to use in the appropriate places in the template. Processed email templates are requested from hook_mail() from the module sending the email. Any module can modify the composed email message array using hook_mail_alter(). Finally \Drupal::service('plugin.manager.mail')->mail() sends the email, which can be reused if the exact same composed email is to be sent to multiple recipients.
Finding out what language to send the email with needs some consideration. If you send email to a user, her preferred language should be fine, so use user_preferred_langcode(). If you send email based on form values filled on the page, there are two additional choices if you are not sending the email to a user on the site. You can either use the language used to generate the page or the site default language. See Drupal\Core\Language\LanguageManagerInterface::getDefaultLanguage(). The former is good if sending email to the person filling the form, the later is good if you send email to an address previously set up (like contact addresses in a contact form).
Taking care of always using the proper language is even more important when sending emails in a row to multiple users. Hook_mail() abstracts whether the mail text comes from an administrator setting or is static in the source code. It should also deal with common mail tokens, only receiving $params which are unique to the actual email at hand.
An example:
function example_notify($accounts) {
foreach ($accounts as $account) {
$params['account'] = $account;
// example_mail() will be called based on the first
// MailManagerInterface->mail() parameter.
\Drupal::service('plugin.manager.mail')
->mail('example', 'notice', $account->mail, user_preferred_langcode($account), $params);
}
}
function example_mail($key, &$message, $params) {
$data['user'] = $params['account'];
$options['langcode'] = $message['langcode'];
user_mail_tokens($variables, $data, $options);
switch ($key) {
case 'notice':
// If the recipient can receive such notices by instant-message, do
// not send by email.
if (example_im_send($key, $message, $params)) {
$message['send'] = FALSE;
break;
}
$message['subject'] = t('Notification from @site', $variables, $options);
$message['body'][] = t("Dear @username\n\nThere is new content available on the site.", $variables, $options);
break;
}
}
Another example, which uses MailManagerInterface->mail() to format a message for sending later:
$params = array(
'current_conditions' => $data,
);
$to = 'user@example.com';
$message = \Drupal::service('plugin.manager.mail')
->mail('example', 'notice', $to, $langcode, $params, FALSE);
// Only add to the spool if sending was not canceled.
if ($message['send']) {
example_spool_message($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:
- user@example.com
- user@example.com, anotheruser@example.com
- User <user@example.com>
- User <user@example.com>, Another User <anotheruser@example.com>
string $langcode: Language code to use to compose the email.
array $params: (optional) Parameters to build the email.
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.)
Overrides MailManagerInterface::mail
File
- core/
lib/ Drupal/ Core/ Mail/ MailManager.php, line 159 - Contains \Drupal\Core\Mail\MailManager.
Class
- MailManager
- Provides a Mail plugin manager.
Namespace
Drupal\Core\MailCode
public function mail($module, $key, $to, $langcode, $params = array(), $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 = array(
'id' => $module . '_' . $key,
'module' => $module,
'key' => $key,
'to' => $to,
'from' => $site_mail,
'reply-to' => $reply,
'langcode' => $langcode,
'params' => $params,
'send' => TRUE,
'subject' => '',
'body' => array(),
);
// Build the default headers.
$headers = array(
'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['Sender'] = $headers['Return-Path'] = $site_mail;
$headers['From'] = $site_config
->get('name') . ' <' . $site_mail . '>';
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(array(
'module' => $module,
'key' => $key,
));
// 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).', array(
'%from' => $message['from'],
'%to' => $message['to'],
'%reply' => $message['reply-to'] ? $message['reply-to'] : $this
->t('not set'),
));
drupal_set_message($this
->t('Unable to send email. Contact the site administrator if the problem persists.'), 'error');
}
}
}
return $message;
}