public function composeMessage($message) { $mimeheaders = array(); $message['headers']['To'] = $message['to']; foreach ($message['headers'] as $name => $value) { $mimeheaders[] = $name . ': ' . Unicode::mimeHeaderEncode($value); } $line_endings = Settings::get('mail_line_endings', PHP_EOL); $output = join($line_endings, $mimeheaders) . $line_endings; // 'Subject:' is a mail header and should not be translated. $output .= 'Subject: ' . $message['subject'] . $line_endings; // Blank line to separate headers from body. $output .= $line_endings; $output .= preg_replace('@\\r?\\n@', $line_endings, $message['body']); return $output; }
/** * Sends an email message. * * @param array $message * A message array, as described in hook_mail_alter(). * * @return bool * TRUE if the mail was successfully accepted, otherwise FALSE. * * @see http://php.net/manual/en/function.mail.php * @see \Drupal\Core\Mail\MailManagerInterface::mail() */ public function mail(array $message) { // If 'Return-Path' isn't already set in php.ini, we pass it separately // as an additional parameter instead of in the header. if (isset($message['headers']['Return-Path'])) { $return_path_set = strpos(ini_get('sendmail_path'), ' -f'); if (!$return_path_set) { $message['Return-Path'] = $message['headers']['Return-Path']; unset($message['headers']['Return-Path']); } } $mimeheaders = array(); foreach ($message['headers'] as $name => $value) { $mimeheaders[] = $name . ': ' . Unicode::mimeHeaderEncode($value); } $line_endings = Settings::get('mail_line_endings', PHP_EOL); // Prepare mail commands. $mail_subject = Unicode::mimeHeaderEncode($message['subject']); // Note: email uses CRLF for line-endings. PHP's API requires LF // on Unix and CRLF on Windows. Drupal automatically guesses the // line-ending format appropriate for your system. If you need to // override this, adjust $settings['mail_line_endings'] in settings.php. $mail_body = preg_replace('@\\r?\\n@', $line_endings, $message['body']); // For headers, PHP's API suggests that we use CRLF normally, // but some MTAs incorrectly replace LF with CRLF. See #234403. $mail_headers = join("\n", $mimeheaders); $request = \Drupal::request(); // We suppress warnings and notices from mail() because of issues on some // hosts. The return value of this method will still indicate whether mail // was sent successfully. if (!$request->server->has('WINDIR') && strpos($request->server->get('SERVER_SOFTWARE'), 'Win32') === FALSE) { // On most non-Windows systems, the "-f" option to the sendmail command // is used to set the Return-Path. There is no space between -f and // the value of the return path. $additional_headers = isset($message['Return-Path']) ? '-f' . $message['Return-Path'] : ''; $mail_result = @mail($message['to'], $mail_subject, $mail_body, $mail_headers, $additional_headers); } else { // On Windows, PHP will use the value of sendmail_from for the // Return-Path header. $old_from = ini_get('sendmail_from'); ini_set('sendmail_from', $message['Return-Path']); $mail_result = @mail($message['to'], $mail_subject, $mail_body, $mail_headers); ini_set('sendmail_from', $old_from); } return $mail_result; }
/** * Tests multibyte encoding and decoding. * * @dataProvider providerTestMimeHeader * @covers ::mimeHeaderEncode * @covers ::mimeHeaderDecode */ public function testMimeHeader($value, $encoded) { $this->assertEquals($encoded, Unicode::mimeHeaderEncode($value)); $this->assertEquals($value, Unicode::mimeHeaderDecode($encoded)); }
/** * Implements SourceInterface::getFromFormatted(). */ function getFromFormatted() { // Windows based PHP systems don't accept formatted email addresses. if (Unicode::substr(PHP_OS, 0, 3) == 'WIN') { return $this->getFromAddress(); } return '"' . addslashes(Unicode::mimeHeaderEncode($this->getNewsletter()->from_name)) . '" <' . $this->getFromAddress() . '>'; }
/** * Gives useful defaults for standard email headers. * * @param array $headers * Message headers. * @param string $from * The address of the sender. * * @return array * Overwrited headers. */ public static function mimeMailHeaders($headers, $from = NULL) { $default_from = \Drupal::config('system.site')->get('mail'); // Overwrite standard headers. if ($from) { if (!isset($headers['From']) || $headers['From'] == $default_from) { $headers['From'] = $from; } if (!isset($headers['Sender']) || $headers['Sender'] == $default_from) { $headers['Sender'] = $from; } // This may not work. The MTA may rewrite the Return-Path. if (!isset($headers['Return-Path']) || $headers['Return-Path'] == $default_from) { if (preg_match('/[a-z\\d\\-\\.\\+_]+@(?:[a-z\\d\\-]+\\.)+[a-z\\d]{2,4}/i', $from, $matches)) { $headers['Return-Path'] = "<{$matches['0']}>"; } } } // Convert From header if it is an array. if (is_array($headers['From'])) { $headers['From'] = static::mimeMailAddress($headers['From']); } // Run all headers through mime_header_encode() to convert non-ascii // characters to an rfc compliant string, similar to drupal_mail(). foreach ($headers as $key => $value) { $headers[$key] = Unicode::mimeHeaderEncode($value); } return $headers; }
/** * Send a newsletter with the HTML format. */ function testSendHTML() { $this->setUpSubscribers(5); // Use custom testing mail system to support HTML mails. $mail_config = $this->config('system.mail'); $mail_config->set('interface.default', 'test_simplenews_html_mail'); $mail_config->save(); // Set the format to HTML. $this->drupalGet('admin/config/services/simplenews'); $this->clickLink(t('Edit')); $edit_newsletter = array('format' => 'html', 'from_name' => 'Drupäl', 'from_address' => $this->randomEmail(), 'receipt' => TRUE); $this->drupalPostForm(NULL, $edit_newsletter, t('Save')); $this->clickLink(t('Edit')); $edit = array('title[0][value]' => $this->randomString() . '\'<', 'body[0][value]' => "Mail token: <strong>[simplenews-subscriber:mail]</strong>", 'simplenews_issue' => 'default'); $this->drupalPostForm('node/add/simplenews_issue', $edit, 'Save and publish'); $this->assertTrue(preg_match('|node/(\\d+)$|', $this->getUrl(), $matches), 'Node created'); $node = Node::load($matches[1]); // Add node to spool. \Drupal::service('simplenews.spool_storage')->addFromEntity($node); // Send mails. \Drupal::service('simplenews.mailer')->sendSpool(); // Make sure that 5 mails have been sent. $this->assertEqual(5, count($this->drupalGetMails())); // Test that tokens are correctly replaced. foreach (array_slice($this->drupalGetMails(), 0, 3) as $mail) { // Verify title. $this->assertTrue(strpos($mail['body'], '<h2>' . Html::escape($node->getTitle()) . '</h2>') !== FALSE); // Verify the format/content type. $this->assertEqual($mail['params']['format'], 'text/html'); $this->assertEqual($mail['params']['plain'], NULL); $this->assertEqual($mail['headers']['Content-Type'], 'text/html; charset=UTF-8'); // Make sure that the same mail was used in the body token as it has been // sent to. $this->assertTrue(strpos($mail['body'], '<strong>' . $mail['to'] . '</strong>') !== FALSE); // Make sure the body is only attached once. $this->assertEqual(1, preg_match_all('/Mail token/', $mail['body'], $matches)); // Check the plaintext version, both params][plaintext (Mime Mail) and // plain (Swiftmailer). $this->assertTrue(strpos($mail['params']['plaintext'], $mail['to']) !== FALSE); $this->assertFalse(strpos($mail['params']['plaintext'], '<strong>')); $this->assertEqual($mail['params']['plaintext'], $mail['plain']); // Make sure the body is only attached once. $this->assertEqual(1, preg_match_all('/Mail token/', $mail['params']['plaintext'], $matches)); // Check the attachments and files arrays. $this->assertTrue(is_array($mail['params']['attachments'])); $this->assertEqual($mail['params']['attachments'], $mail['params']['files']); // Make sure formatted address is properly encoded. $from = '"' . addslashes(Unicode::mimeHeaderEncode($edit_newsletter['from_name'])) . '" <' . $edit_newsletter['from_address'] . '>'; $this->assertEqual($from, $mail['reply-to']); // And make sure it won't get encoded twice. $this->assertEqual($from, Unicode::mimeHeaderEncode($mail['reply-to'])); // @todo: Improve this check, there are currently two spaces, not sure // where they are coming from. $this->assertTrue(strpos($mail['body'], 'class="newsletter-footer"')); // Verify receipt headers. $this->assertEqual($mail['headers']['Disposition-Notification-To'], $edit_newsletter['from_address']); $this->assertEqual($mail['headers']['X-Confirm-Reading-To'], $edit_newsletter['from_address']); } }
/** * {@inheritdoc} */ public function getFrom() { $address = $this->config->get('newsletter.from_address'); $name = $this->config->get('newsletter.from_name'); // Windows based PHP systems don't accept formatted email addresses. $formatted_address = Unicode::substr(PHP_OS, 0, 3) == 'WIN' ? $address : '"' . addslashes(Unicode::mimeHeaderEncode($name)) . '" <' . $address . '>'; return array('address' => $address, 'formatted' => $formatted_address); }