You are here

public function PhpMailerSmtp::mail in PHPMailer SMTP 2.x

Same name and namespace in other branches
  1. 8 src/Plugin/Mail/PhpMailerSmtp.php \Drupal\phpmailer_smtp\Plugin\Mail\PhpMailerSmtp::mail()
  2. 2.0.x src/Plugin/Mail/PhpMailerSmtp.php \Drupal\phpmailer_smtp\Plugin\Mail\PhpMailerSmtp::mail()
  3. 2.1.x src/Plugin/Mail/PhpMailerSmtp.php \Drupal\phpmailer_smtp\Plugin\Mail\PhpMailerSmtp::mail()

Sends an e-mail message composed by drupal_mail().

Parameters

array $message: A message array, as described in hook_mail_alter().

Return value

bool TRUE if the mail was successfully accepted, otherwise FALSE.

Overrides MailInterface::mail

See also

PHPMailer::Send()

File

src/Plugin/Mail/PhpMailerSmtp.php, line 340

Class

PhpMailerSmtp
Implements the base PHPMailer SMTP class for the Drupal MailInterface.

Namespace

Drupal\phpmailer_smtp\Plugin\Mail

Code

public function mail(array $message) {
  try {

    // Parse 'From' address.
    $from = phpmailer_smtp_parse_address($message['headers']['From']);
    $from = reset($from);
    $this->From = $from['mail'];
    if ($from['name'] != '') {
      $this->FromName = $from['name'];
    }
    unset($message['headers']['From']);

    // @todo This \still\ might not be the correct way to do this.
    $phpmailer_smtp_debug_email = $this->configFactory
      ->get('system.maintenance')
      ->get('phpmailer_smtp_debug_email');
    if (empty($phpmailer_smtp_debug_email)) {

      // Set recipients.
      foreach (phpmailer_smtp_parse_address($message['to']) as $address) {
        $this
          ->AddAddress($address['mail'], $address['name']);
      }

      // Extract CCs and BCCs from headers.
      if (!empty($message['headers']['Cc'])) {
        foreach (phpmailer_smtp_parse_address($message['headers']['Cc']) as $address) {
          $this
            ->AddCC($address['mail'], $address['name']);
        }
      }
      if (!empty($message['headers']['Bcc'])) {
        foreach (phpmailer_smtp_parse_address($message['headers']['Bcc']) as $address) {
          $this
            ->AddBCC($address['mail'], $address['name']);
        }
      }
    }
    else {

      // Reroute to debug e-mail address.
      // @todo This might not be the correct way to do this.
      $this
        ->AddAddress($phpmailer_smtp_debug_email);
    }
    unset($message['headers']['Cc'], $message['headers']['Bcc']);

    // Extract Reply-To from headers.
    if (isset($message['headers']['Reply-To'])) {
      foreach (phpmailer_smtp_parse_address($message['headers']['Reply-To']) as $address) {
        $this
          ->AddReplyTo($address['mail'], $address['name']);
      }
      unset($message['headers']['Reply-To']);
    }
    elseif ($this->config
      ->get('smtp_always_replyto')) {

      // If no Reply-To header has been explicitly set, use the From address
      // to be able to respond to e-mails sent via Google Mail.
      $this
        ->AddReplyTo($from['mail'], $from['name']);
    }

    // Extract Content-Type and charset.
    if (isset($message['headers']['Content-Type'])) {
      $content_type = explode(';', $message['headers']['Content-Type']);
      $this->ContentType = trim(array_shift($content_type));
      foreach ($content_type as $param) {
        $param = explode('=', $param, 2);
        $key = trim($param[0]);
        if ($key == 'charset') {
          $this->CharSet = trim($param[1]);
        }
        else {
          $this->ContentType .= '; ' . $key . '=' . trim($param[1]);
        }
      }
      unset($message['headers']['Content-Type']);
    }

    // Set additional properties.
    $properties = [
      'X-Priority' => 'Priority',
      'Content-Transfer-Encoding' => 'Encoding',
      'Message-ID' => 'MessageID',
    ];
    foreach ($properties as $source => $property) {
      if (isset($message['headers'][$source])) {
        $this->{$property} = $message['headers'][$source];
        unset($message['headers'][$source]);
      }
    }

    // Return-Path should not be set by Drupal.
    if (isset($message['headers']['Return-Path'])) {
      unset($message['headers']['Return-Path']);
    }

    // X-Mailer is set by PHPMailer which is the mailer.
    if (isset($message['headers']['X-Mailer'])) {
      unset($message['headers']['X-Mailer']);
    }

    // Set default sender address.
    $envelopeSender = phpmailer_smtp_parse_address($message['from']);
    $envelopeSender = reset($envelopeSender);
    $this->Sender = $envelopeSender['mail'];

    // Check envelope sender option.
    $senderOption = $this->config
      ->get('smtp_envelope_sender_option');
    if ($senderOption === 'site_mail') {
      $this->Sender = $this->configFactory
        ->get('system.site')
        ->get('mail');
    }
    if ($senderOption === 'from_address') {
      $this->Sender = $from['mail'];
    }
    if ($senderOption === 'other') {
      $this->Sender = $this->config
        ->get('smtp_envelope_sender');
    }
    if (!empty($this->config
      ->get('smtp_ehlo_host'))) {
      $this->Hostname = $this->config
        ->get('smtp_ehlo_host');
    }

    // This one is always set by PHPMailer.
    unset($message['headers']['MIME-Version']);

    // Add remaining header lines.
    // Note: Any header lines MUST already be checked by the caller for
    // unwanted newline characters to avoid header injection.
    // @see PHPMailer::SecureHeader()
    foreach ($message['headers'] as $key => $value) {
      $this
        ->AddCustomHeader($key, $value);
    }
    $this->Subject = $message['subject'];
    $this->Body = $message['body'];
    return $this
      ->Send();
  } catch (Exception $e) {

    // Log the error including verbose debug information.
    // Since DBLog module is the most common case, we use HTML to format the
    // message for visual inspection. For sites running with Syslog or other
    // logging modules, we put the actual values on separate lines (\n), so
    // the surrounding HTML markup doesn't get too disturbing.
    // Message is a safe $this->t() string from PhpMailerSmtp::SetLanguage().
    $output = $e
      ->getMessage();

    // Attempt to delimit summary from full message.
    $output .= " \n";
    $arguments = [];

    // Append SMTP communication output.
    if ($this->drupalDebugOutput) {

      // PHPMailer debug output contains HTML linebreaks. PRE is more
      // readable.
      $output .= '<p><strong>Server response:</strong></p>';
      $output .= "<pre>\n@smtp_output\n</pre>";
      $arguments += [
        '@smtp_output' => str_replace("<br>\n", "\n", Html::decodeEntities($this->drupalDebugOutput)),
      ];
    }

    // We need to log the message in order to be able to debug why the server
    // responded with an error. The mail body may contain passwords and other
    // sensitive information, which should not be logged. Since all kind of
    // mails are processed and Drupal provides no way to mark sensible data,
    // it is technically impossible prevent logging in all cases.
    // Remove $params; they've already been processed and may contain sensible
    // data.
    unset($message['params']);

    // Subject.
    $output .= "<p><strong>Subject:</strong> \n@subject\n</p>";
    $arguments += [
      '@subject' => $message['subject'],
    ];
    unset($message['subject']);

    // Body.
    $output .= '<p><strong>Body:</strong></p>';
    $output .= "<pre>\n@body\n</pre>";
    $arguments += [
      '@body' => $message['body'],
    ];
    unset($message['body']);

    // Rest of $message.
    $output .= '<p><strong>Message:</strong></p>';
    $output .= "<pre>\n@message\n</pre>";
    $arguments += [
      '@message' => var_export($message, TRUE),
    ];
    $this->loggerFactory
      ->get('phpmailer_smtp')
      ->error($output, $arguments);
    return FALSE;
  }
}