function sendmail($to, $subject, $message, $from = null, $message_id = null, $send_html = false, $priority = 3, $hotmail_fix = null, $is_private = false) { global $webmaster_email, $context, $modSettings, $txt, $scripturl; // Use sendmail if it's set or if no SMTP server is set. $use_sendmail = empty($modSettings['mail_type']) || $modSettings['smtp_host'] == ''; // Line breaks need to be \r\n only in windows or for SMTP. $line_break = $context['server']['is_windows'] || !$use_sendmail ? "\r\n" : "\n"; // So far so good. $mail_result = true; // If the recipient list isn't an array, make it one. $to_array = is_array($to) ? $to : array($to); // Once upon a time, Hotmail could not interpret non-ASCII mails. // In honour of those days, it's still called the 'hotmail fix'. if ($hotmail_fix === null) { $hotmail_to = array(); foreach ($to_array as $i => $to_address) { if (preg_match('~@(att|comcast|bellsouth)\\.[a-zA-Z\\.]{2,6}$~i', $to_address) === 1) { $hotmail_to[] = $to_address; $to_array = array_diff($to_array, array($to_address)); } } // Call this function recursively for the hotmail addresses. if (!empty($hotmail_to)) { $mail_result = sendmail($hotmail_to, $subject, $message, $from, $message_id, $send_html, $priority, true); } // The remaining addresses no longer need the fix. $hotmail_fix = false; // No other addresses left? Return instantly. if (empty($to_array)) { return $mail_result; } } // Get rid of entities. $subject = un_htmlspecialchars($subject); // Make the message use the proper line breaks. $message = str_replace(array("\r", "\n"), array('', $line_break), $message); // Make sure hotmail mails are sent as HTML so that HTML entities work. if ($hotmail_fix && !$send_html) { $send_html = true; $message = strtr($message, array($line_break => '<br />' . $line_break)); $message = preg_replace('~(' . preg_quote($scripturl, '~') . '(?:[?/][\\w\\-_%\\.,\\?&;=#]+)?)~', '<a href="$1">$1</a>', $message); } list(, $from_name) = mimespecialchars(addcslashes($from !== null ? $from : $context['forum_name'], '<>()\'\\"'), true, $hotmail_fix, $line_break); list(, $subject) = mimespecialchars($subject, true, $hotmail_fix, $line_break); // Construct the mail headers... $headers = 'From: "' . $from_name . '" <' . (empty($modSettings['mail_from']) ? $webmaster_email : $modSettings['mail_from']) . '>' . $line_break; $headers .= $from !== null ? 'Reply-To: <' . $from . '>' . $line_break : ''; $headers .= 'Return-Path: ' . (empty($modSettings['mail_from']) ? $webmaster_email : $modSettings['mail_from']) . $line_break; $headers .= 'Date: ' . gmdate('D, d M Y H:i:s') . ' -0000' . $line_break; if ($message_id !== null && empty($modSettings['mail_no_message_id'])) { $headers .= 'Message-ID: <' . md5($scripturl . microtime()) . '-' . $message_id . strstr(empty($modSettings['mail_from']) ? $webmaster_email : $modSettings['mail_from'], '@') . '>' . $line_break; } $headers .= 'X-Mailer: SMF' . $line_break; if (!empty($modSettings['simplesef_enable'])) { SimpleSEF::fixEmailOutput($subject, $message, $headers); } // Pass this to the integration before we start modifying the output -- it'll make it easier later. if (in_array(false, HookAPI::callHook('integrate_outgoing_email', array(&$subject, &$message, &$headers)), true)) { return false; } // Save the original message... $orig_message = $message; // The mime boundary separates the different alternative versions. $mime_boundary = 'SMF-' . md5($message . time()); // Using mime, as it allows to send a plain unencoded alternative. $headers .= 'Mime-Version: 1.0' . $line_break; $headers .= 'Content-Type: multipart/alternative; boundary="' . $mime_boundary . '"' . $line_break; $headers .= 'Content-Transfer-Encoding: 7bit' . $line_break; // Sending HTML? Let's plop in some basic stuff, then. if ($send_html) { $no_html_message = un_htmlspecialchars(strip_tags(strtr($orig_message, array('</title>' => $line_break)))); // But, then, dump it and use a plain one for dinosaur clients. list(, $plain_message) = mimespecialchars($no_html_message, false, true, $line_break); $message = $plain_message . $line_break . '--' . $mime_boundary . $line_break; // This is the plain text version. Even if no one sees it, we need it for spam checkers. list($charset, $plain_charset_message, $encoding) = mimespecialchars($no_html_message, false, false, $line_break); $message .= 'Content-Type: text/plain; charset=' . $charset . $line_break; $message .= 'Content-Transfer-Encoding: ' . $encoding . $line_break . $line_break; $message .= $plain_charset_message . $line_break . '--' . $mime_boundary . $line_break; // This is the actual HTML message, prim and proper. If we wanted images, they could be inlined here (with multipart/related, etc.) list($charset, $html_message, $encoding) = mimespecialchars($orig_message, false, $hotmail_fix, $line_break); $message .= 'Content-Type: text/html; charset=' . $charset . $line_break; $message .= 'Content-Transfer-Encoding: ' . ($encoding == '' ? '7bit' : $encoding) . $line_break . $line_break; $message .= $html_message . $line_break . '--' . $mime_boundary . '--'; } else { // Send a plain message first, for the older web clients. list(, $plain_message) = mimespecialchars($orig_message, false, true, $line_break); $message = $plain_message . $line_break . '--' . $mime_boundary . $line_break; // Now add an encoded message using the forum's character set. list($charset, $encoded_message, $encoding) = mimespecialchars($orig_message, false, false, $line_break); $message .= 'Content-Type: text/plain; charset=' . $charset . $line_break; $message .= 'Content-Transfer-Encoding: ' . $encoding . $line_break . $line_break; $message .= $encoded_message . $line_break . '--' . $mime_boundary . '--'; } // Are we using the mail queue, if so this is where we butt in... if (!empty($modSettings['mail_queue']) && $priority != 0) { return AddMailQueue(false, $to_array, $subject, $message, $headers, $send_html, $priority, $is_private); } elseif (!empty($modSettings['mail_queue']) && !empty($modSettings['mail_limit'])) { list($last_mail_time, $mails_this_minute) = @explode('|', $modSettings['mail_recent']); if (empty($mails_this_minute) || time() > $last_mail_time + 60) { $new_queue_stat = time() . '|' . 1; } else { $new_queue_stat = $last_mail_time . '|' . ((int) $mails_this_minute + 1); } updateSettings(array('mail_recent' => $new_queue_stat)); } // SMTP or sendmail? if ($use_sendmail) { $subject = strtr($subject, array("\r" => '', "\n" => '')); if (!empty($modSettings['mail_strip_carriage'])) { $message = strtr($message, array("\r" => '')); $headers = strtr($headers, array("\r" => '')); } foreach ($to_array as $to) { if (!mail(strtr($to, array("\r" => '', "\n" => '')), $subject, $message, $headers)) { log_error(sprintf($txt['mail_send_unable'], $to)); $mail_result = false; } // Wait, wait, I'm still sending here! @set_time_limit(300); if (function_exists('apache_reset_timeout')) { @apache_reset_timeout(); } } } else { $mail_result = $mail_result && smtp_mail($to_array, $subject, $message, $headers); } // Everything go smoothly? return $mail_result; }