You are here

function reroute_email_mail_alter in Reroute Email 8

Same name and namespace in other branches
  1. 5 reroute_email.module \reroute_email_mail_alter()
  2. 6 reroute_email.module \reroute_email_mail_alter()
  3. 7 reroute_email.module \reroute_email_mail_alter()
  4. 2.x reroute_email.module \reroute_email_mail_alter()

Implements hook_mail_alter().

Alter destination of outgoing emails if reroute_email is enabled.

File

./reroute_email.module, line 49
Intercepts all outgoing emails to be rerouted to a configurable destination.

Code

function reroute_email_mail_alter(&$message) {
  global $base_url;
  $config = \Drupal::config('reroute_email.settings');
  if (empty($message) || !is_array($message)) {
    return;
  }

  // Allow other modules to decide whether the email should be rerouted by
  // specify a special header 'X-Rerouted-Force' to TRUE or FALSE. Any module
  // can add this header to any own emails in hook_mail or any other emails in
  // hook_mail_alter() implementations.
  if (!empty($message['headers']) && isset($message['headers']['X-Rerouted-Force'])) {
    if (FALSE === (bool) $message['headers']['X-Rerouted-Force']) {
      return;
    }

    // We ignore all module settings if X-Rerouted-Force header was set to TRUE.
  }
  elseif (reroute_email_check($message) === FALSE) {
    return;
  }
  $mailkey = isset($message['id']) ? $message['id'] : t('[mail id] is missing');
  $to = isset($message['to']) ? $message['to'] : t('[to] is missing');
  $message['headers']['X-Rerouted-Mail-Key'] = $mailkey;
  $message['headers']['X-Rerouted-Website'] = $base_url;

  // Unset Bcc and Cc fields to prevent emails from going to those addresses.
  if (isset($message['headers']) && is_array($message['headers'])) {

    // Ensure we catch all Cc and Bcc headers, regardless of case,
    // and protecting against multiple instances of the "same" header.
    $header_keys = [];
    foreach (array_keys($message['headers']) as $key) {
      $header_keys[strtolower($key)][] = $key;
    }
    if (!empty($header_keys['cc'])) {
      foreach ($header_keys['cc'] as $header) {
        $message['headers']['X-Rerouted-Original-Cc'] = $message['headers'][$header];
        unset($message['headers'][$header]);
      }
    }
    if (!empty($header_keys['bcc'])) {
      foreach ($header_keys['bcc'] as $header) {
        $message['headers']['X-Rerouted-Original-Bcc'] = $message['headers'][$header];
        unset($message['headers'][$header]);
      }
    }
  }

  // Get reroute_email_address, or use system.site.mail if not set.
  $rerouting_addresses = $config
    ->get(REROUTE_EMAIL_ADDRESS);
  if (NULL === $rerouting_addresses) {
    $rerouting_addresses = \Drupal::config('system.site')
      ->get('mail');
  }
  $message['headers']['X-Rerouted-Original-To'] = $to;
  $message['to'] = $rerouting_addresses;

  // Format a message to show at the top.
  if ($config
    ->get(REROUTE_EMAIL_DESCRIPTION)) {
    $message_lines = [
      t('This email was rerouted.'),
      t('Web site: @site', [
        '@site' => $base_url,
      ]),
      t('Mail key: @key', [
        '@key' => $mailkey,
      ]),
      t('Originally to: @to', [
        '@to' => $to,
      ]),
    ];

    // Add Cc/Bcc values to the message only if they are set.
    if (!empty($message['headers']['X-Rerouted-Original-Cc'])) {
      $message_lines[] = t('Originally cc: @cc', [
        '@cc' => $message['headers']['X-Rerouted-Original-Cc'],
      ]);
    }
    if (!empty($message['headers']['X-Rerouted-Original-Bcc'])) {
      $message_lines[] = t('Originally bcc: @bcc', [
        '@bcc' => $message['headers']['X-Rerouted-Original-Bcc'],
      ]);
    }

    // Simple separator between reroute and original messages.
    $message_lines[] = '-----------------------';
    $message_lines[] = '';
    $msg = implode(PHP_EOL, $message_lines);

    // Prepend explanation message to the body of the email. This must be
    // handled differently depending on whether the body came in as a
    // string or an array. If it came in as a string (despite the fact it
    // should be an array) we'll respect that and leave it as a string.
    if (is_string($message['body'])) {
      $message['body'] = $msg . $message['body'];
    }
    else {
      array_unshift($message['body'], $msg);
    }
  }

  // Abort sending of the email if the no rerouting addresses provided.
  if ($rerouting_addresses === '') {
    $message['send'] = FALSE;

    // Extensive params keys cause OOM error in var_export().
    unset($message['params']);

    // Simplify subject to avoid OOM error in var_export().
    if ($message['subject'] instanceof TranslatableMarkup) {
      $message['subject'] = $message['subject']
        ->render();
    }

    // Record a variable dump of the email in the recent log entries.
    $message_string = var_export($message, TRUE);
    \Drupal::logger('reroute_email')
      ->notice('Aborted email sending for <em>@message_id</em>. <br/>Detailed email data: Array $message <pre>@message</pre>', [
      '@message_id' => $message['id'],
      '@message' => $message_string,
    ]);

    // Let users know email has been aborted, but logged.
    if ($config
      ->get(REROUTE_EMAIL_MESSAGE)) {
      \Drupal::messenger()
        ->addMessage(t('<em>@message_id</em> was aborted by reroute email; site administrators can check the recent log entries for complete details on the rerouted email.', [
        '@message_id' => $message['id'],
      ]));
    }
  }
  elseif ($config
    ->get(REROUTE_EMAIL_MESSAGE)) {

    // Display a message to let users know email was rerouted.
    \Drupal::messenger()
      ->addMessage(t('Submitted email, with ID: <em>@message_id</em>, was rerouted to configured address: <em>@reroute_target</em>. For more details please refer to Reroute Email settings.', [
      '@message_id' => $message['id'],
      '@reroute_target' => $message['to'],
    ]));
  }
}