public function SmtpMailSystem::mailWithoutQueue in SMTP Authentication Support 7
Same name and namespace in other branches
- 7.2 smtp.mail.inc \SmtpMailSystem::mailWithoutQueue()
1 call to SmtpMailSystem::mailWithoutQueue()
- SmtpMailSystem::mail in ./
smtp.mail.inc - Send the e-mail message.
File
- ./
smtp.mail.inc, line 62 - The code processing mail in the smtp module.
Class
- SmtpMailSystem
- Modify the drupal mail system to use smtp when sending emails. Include the option to choose between plain text or HTML
Code
public function mailWithoutQueue(array $message) {
$to = $message['to'];
$from = $message['from'];
$from_name = isset($message['from_name']) ? $message['from_name'] : FALSE;
$body = $message['body'];
$headers = $message['headers'];
$subject = $message['subject'];
// Optionally reroute all emails to a single address.
$reroute_address = variable_get('smtp_reroute_address', '');
if (!empty($reroute_address)) {
$to = $reroute_address;
// Remove any CC and BCC headers that might have been set.
unset($headers['cc']);
unset($headers['bcc']);
}
// Create a new PHPMailer object - autoloaded from registry.
$mailer = new PHPMailer();
$logging = variable_get('smtp_debugging', SMTP_LOGGING_ERRORS);
// Turn on debugging, if requested.
if ($logging == SMTP_LOGGING_ALL && user_access('administer smtp module')) {
$mailer->SMTPDebug = TRUE;
}
// Set the from name. First we try to get the name from i18n, in the case
// that it has been translated. The name is set according to the language
// of the email being sent.
if (empty($from_name)) {
if (function_exists('i18n_variable_get')) {
// The 'language' value may be stored as an object.
$langcode = $message['language'];
if (is_object($langcode)) {
$langcode = $langcode->language;
}
if (i18n_variable_get('smtp_fromname', $langcode, '') != '') {
$from_name = i18n_variable_get('smtp_fromname', $langcode, '');
}
else {
$from_name = i18n_variable_get('site_name', $langcode, '');
}
}
else {
if (variable_get('smtp_fromname', '') != '') {
$from_name = variable_get('smtp_fromname', '');
}
else {
$from_name = variable_get('site_name', '');
}
}
}
if (variable_get('smtp_client_hostname', '') != '') {
$mailer->Hostname = variable_get('smtp_client_hostname', '');
}
if (variable_get('smtp_client_helo', '') != '') {
$mailer->Helo = variable_get('smtp_client_helo', '');
}
//Hack to fix reply-to issue.
if (!isset($headers['Reply-To']) || empty($headers['Reply-To'])) {
if (strpos($from, '<')) {
$reply = preg_replace('/>.*/', '', preg_replace('/.*</', '', $from));
}
else {
$reply = $from;
}
$headers['Reply-To'] = $reply;
}
$properfrom = variable_get('smtp_from', '');
if (!empty($properfrom)) {
$headers['From'] = $properfrom;
$from = $properfrom;
}
if ($from == NULL || $from == '') {
// If from e-mail address is blank, use smtp_from config option.
if (($from = variable_get('smtp_from', '')) == '') {
// If smtp_from config option is blank, use site_email.
if (($from = variable_get('site_mail', '')) == '') {
drupal_set_message(t('There is no submitted from address.'), 'error');
if ($logging) {
watchdog('smtp', 'There is no submitted from address.', array(), WATCHDOG_ERROR);
}
return FALSE;
}
}
}
$from_comp = $this
->_get_components($from);
if (!valid_email_address($from_comp['email'])) {
drupal_set_message(t('The submitted from address (@from) is not valid.', array(
'@from' => $from_comp['email'],
)), 'error');
if ($logging) {
watchdog('smtp', 'The submitted from address (@from) is not valid.', array(
'@from' => $from_comp['email'],
), WATCHDOG_ERROR);
}
return FALSE;
}
// Defines the From value to what we expect.
$mailer->From = $from_comp['email'];
$mailer->FromName = empty($from_comp['name']) ? $from_name : $from_comp['name'];
$mailer->Sender = $from_comp['email'];
// Create the list of 'To:' recipients.
$torecipients = explode(',', $to);
foreach ($torecipients as $torecipient) {
$to_comp = $this
->_get_components($torecipient);
$mailer
->AddAddress($to_comp['email'], $to_comp['name']);
}
// Parse the headers of the message and set the PHPMailer object's settings
// accordingly.
foreach ($headers as $key => $value) {
//watchdog('error', 'Key: ' . $key . ' Value: ' . $value);
switch (drupal_strtolower($key)) {
case 'from':
if ($from == NULL or $from == '') {
// If a from value was already given, then set based on header.
// Should be the most common situation since drupal_mail moves the
// from to headers.
$from = $value;
$mailer->From = $value;
// then from can be out of sync with from_name !
$mailer->FromName = '';
$mailer->Sender = $value;
}
break;
case 'content-type':
// Parse several values on the Content-type header, storing them in an array like
// key=value -> $vars['key']='value'
$vars = explode(';', $value);
foreach ($vars as $i => $var) {
if ($cut = strpos($var, '=')) {
$new_var = trim(drupal_strtolower(drupal_substr($var, $cut + 1)));
$new_key = trim(drupal_substr($var, 0, $cut));
unset($vars[$i]);
$vars[$new_key] = $new_var;
}
}
// Set the charset based on the provided value, otherwise set it to UTF-8 (which is Drupals internal default).
$mailer->CharSet = isset($vars['charset']) ? $vars['charset'] : 'UTF-8';
// If $vars is empty then set an empty value at index 0 to avoid a PHP warning in the next statement
$vars[0] = isset($vars[0]) ? $vars[0] : '';
switch ($vars[0]) {
case 'text/plain':
// The message includes only a plain text part.
$mailer
->IsHTML(FALSE);
$content_type = 'text/plain';
break;
case 'text/html':
// The message includes only an HTML part.
$mailer
->IsHTML(TRUE);
$content_type = 'text/html';
break;
case 'multipart/related':
// Get the boundary ID from the Content-Type header.
$boundary = $this
->_get_substring($value, 'boundary', '"', '"');
// The message includes an HTML part w/inline attachments.
$mailer->ContentType = $content_type = 'multipart/related; boundary="' . $boundary . '"';
break;
case 'multipart/alternative':
// The message includes both a plain text and an HTML part.
$mailer->ContentType = $content_type = 'multipart/alternative';
// Get the boundary ID from the Content-Type header.
$boundary = $this
->_get_substring($value, 'boundary', '"', '"');
break;
case 'multipart/mixed':
// The message includes one or more attachments.
$mailer->ContentType = $content_type = 'multipart/mixed';
// Get the boundary ID from the Content-Type header.
$boundary = $this
->_get_substring($value, 'boundary', '"', '"');
break;
default:
// Everything else is unsuppored by PHPMailer.
drupal_set_message(t('The %header of your message is not supported by PHPMailer and will be sent as text/plain instead.', array(
'%header' => "Content-Type: {$value}",
)), 'error');
if ($logging) {
watchdog('smtp', 'The %header of your message is not supported by PHPMailer and will be sent as text/plain instead.', array(
'%header' => "Content-Type: {$value}",
), WATCHDOG_ERROR);
}
// Force the Content-Type to be text/plain.
$mailer
->IsHTML(FALSE);
$content_type = 'text/plain';
}
break;
case 'reply-to':
$replyto_comp = $this
->_get_components($value);
$mailer
->AddReplyTo($replyto_comp['email'], $replyto_comp['name']);
break;
case 'content-transfer-encoding':
$mailer->Encoding = $value;
break;
case 'return-path':
$returnpath_comp = $this
->_get_components($value);
$mailer->Sender = $returnpath_comp['email'];
break;
case 'mime-version':
case 'x-mailer':
// Let PHPMailer specify these.
break;
case 'errors-to':
$mailer
->AddCustomHeader('Errors-To: ' . $value);
break;
case 'cc':
$ccrecipients = explode(',', $value);
foreach ($ccrecipients as $ccrecipient) {
$cc_comp = $this
->_get_components($ccrecipient);
$mailer
->AddCC($cc_comp['email'], $cc_comp['name']);
}
break;
case 'bcc':
$bccrecipients = explode(',', $value);
foreach ($bccrecipients as $bccrecipient) {
$bcc_comp = $this
->_get_components($bccrecipient);
$mailer
->AddBCC($bcc_comp['email'], $bcc_comp['name']);
}
break;
case 'message-id':
$mailer->MessageID = $value;
break;
default:
// The header key is not special - add it as is.
$mailer
->AddCustomHeader($key . ': ' . $value);
}
}
/**
* TODO
* Need to figure out the following.
*
* Add one last header item, but not if it has already been added.
* $errors_to = FALSE;
* foreach ($mailer->CustomHeader as $custom_header) {
* if ($custom_header[0] = '') {
* $errors_to = TRUE;
* }
* }
* if ($errors_to) {
* $mailer->AddCustomHeader('Errors-To: '. $from);
* }
*/
// Add the message's subject.
$mailer->Subject = $subject;
// Processes the message's body.
switch ($content_type) {
case 'multipart/related':
$mailer->Body = $body;
// TODO: Figure out if there is anything more to handling this type.
break;
case 'multipart/alternative':
// Split the body based on the boundary ID.
$body_parts = $this
->_boundary_split($body, $boundary);
foreach ($body_parts as $body_part) {
// If plain/text within the body part, add it to $mailer->AltBody.
if (strpos($body_part, 'text/plain')) {
// Clean up the text.
$body_part = trim($this
->_remove_headers(trim($body_part)));
// Include it as part of the mail object.
$mailer->AltBody = $body_part;
}
elseif (strpos($body_part, 'text/html')) {
// Clean up the text.
$body_part = trim($this
->_remove_headers(trim($body_part)));
// Include it as part of the mail object.
$mailer->Body = $body_part;
}
}
break;
case 'multipart/mixed':
// Split the body based on the boundary ID.
$body_parts = $this
->_boundary_split($body, $boundary);
// Determine if there is an HTML part for when adding the plain text part.
$text_plain = FALSE;
$text_html = FALSE;
foreach ($body_parts as $body_part) {
if (strpos($body_part, 'text/plain')) {
$text_plain = TRUE;
}
if (strpos($body_part, 'text/html')) {
$text_html = TRUE;
}
}
foreach ($body_parts as $body_part) {
// If test/plain within the body part, add it to either
// $mailer->AltBody or $mailer->Body, depending on whether there is
// also a text/html part ot not.
if (strpos($body_part, 'multipart/alternative')) {
// Get boundary ID from the Content-Type header.
$boundary2 = $this
->_get_substring($body_part, 'boundary', '"', '"');
// Clean up the text.
$body_part = trim($this
->_remove_headers(trim($body_part)));
// Split the body based on the boundary ID.
$body_parts2 = $this
->_boundary_split($body_part, $boundary2);
foreach ($body_parts2 as $body_part2) {
// If plain/text within the body part, add it to $mailer->AltBody.
if (strpos($body_part2, 'text/plain')) {
// Clean up the text.
$body_part2 = trim($this
->_remove_headers(trim($body_part2)));
// Include it as part of the mail object.
$mailer->AltBody = $body_part2;
$mailer->ContentType = 'multipart/mixed';
}
elseif (strpos($body_part2, 'text/html')) {
// Get the encoding.
$body_part2_encoding = trim($this
->_get_substring($body_part2, 'Content-Transfer-Encoding', ':', "\n"));
// Clean up the text.
$body_part2 = trim($this
->_remove_headers(trim($body_part2)));
// Check whether the encoding is base64, and if so, decode it.
if (drupal_strtolower($body_part2_encoding) == 'base64') {
// Include it as part of the mail object.
$mailer->Body = base64_decode($body_part2);
// Ensure the whole message is recoded in the base64 format.
$mailer->Encoding = 'base64';
}
else {
// Include it as part of the mail object.
$mailer->Body = $body_part2;
}
$mailer->ContentType = 'multipart/mixed';
}
}
}
elseif (strpos($body_part, 'text/plain')) {
// Clean up the text.
$body_part = trim($this
->_remove_headers(trim($body_part)));
if ($text_html) {
$mailer->AltBody = $body_part;
$mailer
->IsHTML(TRUE);
$mailer->ContentType = 'multipart/mixed';
}
else {
$mailer->Body = $body_part;
$mailer
->IsHTML(FALSE);
$mailer->ContentType = 'multipart/mixed';
}
}
elseif (strpos($body_part, 'text/html')) {
// Clean up the text.
$body_part = trim($this
->_remove_headers(trim($body_part)));
// Include it as part of the mail object.
$mailer->Body = $body_part;
$mailer
->IsHTML(TRUE);
$mailer->ContentType = 'multipart/mixed';
}
elseif (strpos($body_part, 'Content-Disposition: attachment;') && !isset($message['params']['attachments'])) {
$file_path = $this
->_get_substring($body_part, 'filename=', '"', '"');
$file_name = $this
->_get_substring($body_part, ' name=', '"', '"');
$file_encoding = $this
->_get_substring($body_part, 'Content-Transfer-Encoding', ' ', "\n");
$file_type = $this
->_get_substring($body_part, 'Content-Type', ' ', ';');
if (file_exists($file_path)) {
if (!$mailer
->AddAttachment($file_path, $file_name, $file_encoding, $file_type)) {
drupal_set_message(t('Attahment could not be found or accessed.'));
}
}
else {
// Clean up the text.
$body_part = trim($this
->_remove_headers(trim($body_part)));
if (drupal_strtolower($file_encoding) == 'base64') {
$attachment = base64_decode($body_part);
}
elseif (drupal_strtolower($file_encoding) == 'quoted-printable') {
$attachment = quoted_printable_decode($body_part);
}
else {
$attachment = $body_part;
}
$attachment_new_filename = drupal_tempnam('temporary://', 'smtp');
$file_path = file_save_data($attachment, $attachment_new_filename, FILE_EXISTS_REPLACE);
$real_path = drupal_realpath($file_path->uri);
if (!$mailer
->AddAttachment($real_path, $file_name)) {
drupal_set_message(t('Attachment could not be found or accessed.'));
}
}
}
}
break;
default:
$mailer->Body = $body;
break;
}
// Process mimemail attachments, which are prepared in mimemail_mail().
if (isset($message['params']['attachments'])) {
foreach ($message['params']['attachments'] as $attachment) {
if (isset($attachment['filecontent'])) {
$mailer
->AddStringAttachment($attachment['filecontent'], $attachment['filename'], 'base64', $attachment['filemime']);
}
if (!isset($attachment['filepath']) && isset($attachment['uri'])) {
$attachment['filepath'] = $attachment['uri'];
}
if (isset($attachment['filepath'])) {
$filename = isset($attachment['filename']) ? $attachment['filename'] : basename($attachment['filepath']);
$filemime = isset($attachment['filemime']) ? $attachment['filemime'] : file_get_mimetype($attachment['filepath']);
$mailer
->AddAttachment($attachment['filepath'], $filename, 'base64', $filemime);
}
}
}
// Process inline images.
if (!empty($message['params']['images'])) {
foreach ($message['params']['images'] as $image) {
if (!empty($image['filepath']) && !empty($image['cid'])) {
if (file_exists($image['filepath'])) {
$image_extension = pathinfo($image['filepath'], PATHINFO_EXTENSION);
$image_mime_type = PHPMailer::_mime_types($image_extension);
if (empty($image['name'])) {
$image_name = pathinfo($image['filepath'], PATHINFO_FILENAME);
}
else {
$image_name = $image['name'];
}
$mailer
->AddEmbeddedImage($image['filepath'], $image['cid'], $image_name, 'base64', $image_mime_type);
}
}
}
}
// Set the authentication settings.
$username = variable_get('smtp_username', '');
$password = variable_get('smtp_password', '');
// If username and password are given, use SMTP authentication.
if ($username != '' && $password != '') {
$mailer->SMTPAuth = TRUE;
$mailer->Username = $username;
$mailer->Password = $password;
}
// Set the protocol prefix for the smtp host.
switch (variable_get('smtp_protocol', 'standard')) {
case 'ssl':
$mailer->SMTPSecure = 'ssl';
break;
case 'tls':
$mailer->SMTPSecure = 'tls';
break;
default:
$mailer->SMTPSecure = '';
}
// Set SSL stream context options
if (variable_get('smtp_protocol', 'standard') != 'standard') {
$smtp_allow_self_signed = array(
'allow_self_signed' => variable_get('smtp_allow_self_signed', FALSE),
);
if (version_compare(phpversion(), '5.6.0', '>=')) {
$smtp_verify_peer = array(
'verify_peer' => variable_get('smtp_verify_peer', TRUE),
);
$smtp_verify_peer_name = array(
'verify_peer_name' => variable_get('smtp_verify_peer_name', TRUE),
);
$mailer->SMTPOptions = array(
'ssl' => array_merge($smtp_verify_peer, $smtp_verify_peer_name, $smtp_allow_self_signed),
);
}
else {
$smtp_verify_peer = array(
'verify_peer' => variable_get('smtp_verify_peer', FALSE),
);
$mailer->SMTPOptions = array(
'ssl' => array_merge($smtp_verify_peer, $smtp_allow_self_signed),
);
}
}
// Set other connection settings.
$mailer->Host = variable_get('smtp_host', '') . ';' . variable_get('smtp_hostbackup', '');
$mailer->Port = variable_get('smtp_port', '25');
$mailer->Mailer = 'smtp';
// Integration with the Maillog module.
if (module_exists('maillog')) {
if (variable_get('maillog_log', TRUE)) {
$record = new stdClass();
// In case the subject/from/to is already encoded, decode with
// mime_header_decode.
$record->header_message_id = isset($mailer->MessageID) ? $mailer->MessageID : NULL;
$record->subject = drupal_substr(mime_header_decode($mailer->Subject), 0, 255);
$record->header_from = $from;
$record->header_to = $to;
$record->header_reply_to = isset($headers['Reply-To']) ? $headers['Reply-To'] : '';
$record->header_all = serialize($headers);
$record->sent_date = REQUEST_TIME;
// Used to separate different portions of the body string.
$divider = str_repeat('-', 60) . "\n";
// Load the attachments.
$attachments = $mailer
->GetAttachments();
$record->body = '';
// If there's more than one item to display, add a divider.
if (!empty($mailer->AltBody) || !empty($attachments)) {
$record->body .= t('Body') . ":\n";
$record->body .= $divider;
}
// Add the body field.
if (isset($mailer->Body)) {
$record->body .= $mailer->Body;
}
else {
$record->body .= t('*No message body*') . ":\n";
}
// The AltBody value is optional.
if (!empty($mailer->AltBody)) {
$record->body .= "\n";
$record->body .= $divider;
$record->body .= t('Alternative body') . ":\n";
$record->body .= $divider;
$record->body .= $mailer->AltBody;
}
// List the attachments.
if (!empty($attachments)) {
$record->body .= "\n";
$record->body .= $divider;
$record->body .= t('Attachments') . ":\n";
$record->body .= $divider;
foreach ($attachments as $file) {
$record->body .= t('Filename') . ':' . $file[1] . "\n";
$record->body .= t('Name') . ':' . $file[2] . "\n";
$record->body .= t('Encoding') . ':' . $file[3] . "\n";
$record->body .= t('Type') . ':' . $file[4] . "\n";
$record->body .= "\n";
}
}
drupal_write_record('maillog', $record);
}
// Display the e-mail using Devel module.
if (variable_get('maillog_devel', TRUE) && function_exists('dpm')) {
$devel_msg = array();
$devel_msg[t('Subject')] = $mailer->Subject;
$devel_msg[t('From')] = $from;
$devel_msg[t('To')] = $to;
$devel_msg[t('Reply-To')] = isset($headers['Reply-To']) ? $headers['Reply-To'] : NULL;
$devel_msg[t('Headers')] = $headers;
$devel_msg[t('Body')] = $mailer->Body;
$devel_msg[t('Alternative body')] = $mailer->AltBody;
$devel_msg[t('Attachments')] = $mailer
->GetAttachments();
dpm($devel_msg, 'maillog');
}
}
$error = FALSE;
// Email delivery was disabled.
if (!variable_get('smtp_deliver', TRUE)) {
if ($logging) {
$params = array(
'@from' => $from,
'@to' => $to,
);
watchdog('smtp', 'Email delivery is disabled, did not send email from @from to @to.', $params);
}
}
else {
if (!$mailer
->send()) {
$params = array(
'@from' => $from,
'@to' => $to,
'!error_message' => $mailer->ErrorInfo,
);
if (variable_get('smtp_queue_fail', FALSE)) {
if ($logging) {
watchdog('smtp', 'Error sending e-mail from @from to @to, will retry on cron run : !error_message.', $params, WATCHDOG_ERROR);
}
smtp_failed_messages($message);
}
elseif ($logging) {
$error = TRUE;
watchdog('smtp', 'Error sending e-mail from @from to @to : !error_message', $params, WATCHDOG_ERROR);
}
}
elseif (variable_get('smtp_debugging', SMTP_LOGGING_ERRORS) == SMTP_LOGGING_ALL) {
watchdog('smtp', 'Sent mail to: @to', array(
'@to' => $to,
));
}
}
$mailer
->SmtpClose();
return !$error;
}