News:

Want to get involved in developing SMF, then why not lend a hand on our github!

Main Menu

Email to Hotmail accounts fail with a blank email without subject and text?

Started by Lotti, December 09, 2006, 09:21:44 PM

Previous topic - Next topic

Lotti

When i send email from my SMF Forum (1.1) to hotmail account, and only to this type of account, the email that the user receive is without text, subject, and other.
The forum is http://www.letterefilosofiasapienza.it/forum
And this is an example of the email that hotmail receive (with smtp option on the forum, and the same with php);

X-Message-Status: n:0
X-SID-PRA: [email protected]
X-Message-Info: txF49lGdW41fRlWtM4mtS2//Jw+aJEo8th0+t6jJBjI=
Received: from m-03.th.seeweb.it ([217.64.195.224]) by bay0-mc4-f10.bay0.hotmail.com with Microsoft SMTPSVC(6.0.3790.2444);
Sat, 9 Dec 2006 18:06:14 -0800
Received: from mail.letterefilosofiasapienza.it (w-03.th.seeweb.it [217.64.195.223])
(authenticated bits=0)
by m-03.th.seeweb.it (8.13.4/8.13.4/Debian-3sarge3) with ESMTP id kBA2671R026708
for <[email protected]>; Sun, 10 Dec 2006 03:06:07 +0100
Message-Id: <[email protected]>
Subject:
To: <[email protected]>
From: "" <[email protected]>
Date: Sun, 10 Dec 2006 02:08:00 +0000
X-Mailer: SMF
Mime-Version: 1.0
Content-Type: multipart/alternative; boundary="SMF-e4889652a7d4b8b453c467b719b6ba98"
Content-Transfer-Encoding: 7bit
Return-Path: [email protected]
X-OriginalArrivalTime: 10 Dec 2006 02:06:15.0158 (UTC) FILETIME=[C5BEE160:01C71BFF]


--SMF-e4889652a7d4b8b453c467b719b6ba98
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit


--SMF-e4889652a7d4b8b453c467b719b6ba98
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit


--SMF-e4889652a7d4b8b453c467b719b6ba98--


jerm


quake101

I have the same problem. I've had many members contact me about this same problem. I don't see anything in the errors logs also. Odd...

???

quake101

I believe I have fixed the problem. I don't know if this is the correct way of doing it but it works. :)

Find:
Quotefunction sendmail($to, $subject, $message, $from = null, $message_id = null, $send_html = false, $priority = 1, $hotmail_fix = null)

Replace:
Quotefunction sendmail($to, $subject, $message, $from = null, $message_id = null, $send_html = false, $priority = 1, $hotmail_fix = false)

Lotti

Yes, this is a problem only of this release.

I have rewrite the code of Subs-Post.php of version 1.1.1 (and the same with 1.1 final) with the code of the 1.1 RC2 that works correctly.
I have rewrite the 1.1.1 with this (old?) functions:
// Send off an email.
function sendmail($to, $subject, $message, $from = null, $message_id = null, $send_html = false)
{
global $webmaster_email, $context, $modSettings, $txt, $scripturl;

// 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);

// Get rid of slashes and entities.
$subject = un_htmlspecialchars(stripslashes($subject));
// Make the message use \r\n's only.
$message = str_replace(array("\r", "\n"), array('', "\r\n"), stripslashes($message));

list (, $from_name) = mimespecialchars(addcslashes($from !== null ? $from : $context['forum_name'], '<>[]()\'\\"'));
list (, $subject) = mimespecialchars($subject);

// Construct the mail headers...
$headers = 'From: "' . $from_name . '" <' . (empty($modSettings['mail_from']) ? $webmaster_email : $modSettings['mail_from']) . ">\r\n";
$headers .= $from !== null ? 'Reply-To: <' . $from . ">\r\n" : '';
$headers .= 'Return-Path: ' . (empty($modSettings['mail_from']) ? $webmaster_email: $modSettings['mail_from']) . "\r\n";
$headers .= 'Date: ' . gmdate('D, d M Y H:i:s') . ' +0000' . "\r\n";

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'], '@') . ">\r\n";
$headers .= "X-Mailer: SMF\r\n";

$charset = $txt['lang_character_set'];
$encoding = '';

list ($charset2, $message2) = mimespecialchars($message);

if ($message2 != $message || $charset2 != $charset)
{
$charset = $charset2;
$message = $message2;

if (preg_match('~^=\?' . preg_quote($charset2, '~') . '\?Q\?(.*)\?=$~s', $message, $match))
{
$message = $match[1];
$encoding = 'quoted-printable';
}
}

// Sending HTML?  Let's plop in some basic stuff, then.
if ($send_html)
{
// This should send a text message with MIME multipart/alternative stuff.
$mime_boundary = 'SMF-' . md5($message . time());
$headers .= 'Mime-Version: 1.0' . "\r\n";
$headers .= 'Content-Type: multipart/alternative; boundary="' . $mime_boundary . '"' . "\r\n";
$headers .= 'Content-Transfer-Encoding: ' . ($encoding == '' ? '7bit' : $encoding);

// Save the original message...
$orig_message = $message;

// But, then, dump it and use a plain one for dinosaur clients.
$message = un_htmlspecialchars(strip_tags(strtr($orig_message, array('</title>' => "\r\n")))) . "\r\n--" . $mime_boundary . "\r\n";

// This is the plain text version.  Even if no one sees it, we need it for spam checkers.
$message .= 'Content-Type: text/plain; charset=' . $charset . "\r\n";
$message .= 'Content-Transfer-Encoding: ' . ($encoding == '' ? '7bit' : $encoding) . "\r\n\r\n";
$message .= un_htmlspecialchars(strip_tags(strtr($orig_message, array('</title>' => "\r\n")))) . "\r\n--" . $mime_boundary . "\r\n";

// This is the actual HTML message, prim and proper.  If we wanted images, they could be inlined here (with multipart/related, etc.)
$message .= 'Content-Type: text/html; charset=' . $charset . "\r\n";
$message .= 'Content-Transfer-Encoding: ' . ($encoding == '' ? '7bit' : $encoding) . "\r\n\r\n";
$message .= $orig_message . "\r\n--" . $mime_boundary . '--';
}
// Text is good too.
else
{
$headers .= 'Content-Type: text/plain; charset=' . $charset . "\r\n";
if ($encoding != '')
$headers .= 'Content-Transfer-Encoding: ' . $encoding;
}

if (isset($modSettings['integrate_outgoing_email']) && function_exists($modSettings['integrate_outgoing_email']))
{
if ($modSettings['integrate_outgoing_email']($subject, $message, $headers) === false)
return false;
}

// SMTP or sendmail?
if (empty($modSettings['mail_type']) || $modSettings['smtp_host'] == '')
{
$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 = smtp_mail($to_array, $subject, $message, $send_html ? $headers : "Mime-Version: 1.0\r\n" . $headers);

// Everything go smoothly?
return $mail_result;
}


and

function mimespecialchars($old_string)
{
global $txt, $modSettings;

$charset = $txt['lang_character_set'];

// This is the fun part....
if (preg_match('~&#\d{3,8};~', $old_string) != 0)
{
$fixchar = create_function('$n', '
if ($n < 128)
return chr($n);
elseif ($n < 2048)
return chr(192 | $n >> 6) . chr(128 | $n & 63);
elseif ($n < 65536)
return chr(224 | $n >> 12) . chr(128 | $n >> 6 & 63) . chr(128 | $n & 63);
else
return chr(240 | $n >> 18) . chr(128 | $n >> 12 & 63) . chr(128 | $n >> 6 & 63) . chr(128 | $n & 63);');

// Attempt to convert to UTF-8, if we can... it might fail if the character set is unknown.
if ($txt['lang_character_set'] != 'UTF-8' && function_exists('iconv') && $old_string2 = @iconv($txt['lang_character_set'], 'UTF-8', $old_string))
{
$old_string2 = preg_replace('~&#(\d{3,8});~e', '$fixchar(\'$1\')', $old_string2);

// Converting back is potentially lossy; only do it if we're in "dumb email client" compat mode.
if (!empty($modSettings['disableQuotedPrintable']))
$old_string2 = @iconv('UTF-8', $txt['lang_character_set'] . '//IGNORE', $old_string2);
else
$charset = 'UTF-8';

$old_string = $old_string2;
}
else
{
$simple = true;

preg_match_all('~&#(\d{3,8});~', $old_string, $matches);
foreach ($matches[1] as $entity)
{
if ($entity > 255)
$simple = false;
}
unset($matches);

if ($simple)
$old_string = preg_replace('~&#(\d{3,8});~e', 'chr(\'$1\')', $old_string);
else
{
$old_string = preg_replace('~&#(\d{3,8});~e', '$fixchar(\'$1\')', $old_string);

// Unicode, baby.
$charset = 'UTF-8';
}
}
}

// This is as far as we go if quoted-printable is disabled.
if (!empty($modSettings['disableQuotedPrintable']))
return array($charset, $old_string);

$string = $old_string;
$i18n_char = false;

// Look for special characters...
for ($i = 0; $i < strlen($string); $i++)
if (ord($string{$i}) >= 128 || $string{$i} == '=' || $string{$i} == '?' || $string{$i} == '_')
{
$i18n_char |= ord($string{$i}) >= 128;

// Add on to the string whenever we find a special character.
$string = substr($string, 0, $i) . '=' . strtoupper(dechex(ord($string{$i}))) . substr($string, ++$i);
}

// We don't need to mess with the subject line if no special characters were in it..
if ($i18n_char)
return array($charset, '=?' . $charset . '?Q?' . $string . '?=');
else
return array($charset, $old_string);
}

// Send an email via SMTP.
function smtp_mail($mail_to_array, $subject, $message, $headers)
{
global $modSettings, $webmaster_email, $txt;

$modSettings['smtp_host'] = trim($modSettings['smtp_host']);

// Try POP3 before SMTP?
// !!! There's no interface for this yet.
if ($modSettings['mail_type'] == 2 && $modSettings['smtp_username'] != '' && $modSettings['smtp_password'] != '')
{
$socket = fsockopen($modSettings['smtp_host'], 110, $errno, $errstr, 2);
if (!$socket && (substr($modSettings['smtp_host'], 0, 5) == 'smtp.' || substr($modSettings['smtp_host'], 0, 11) == 'ssl://smtp.'))
$socket = fsockopen(strtr($modSettings['smtp_host'], array('smtp.' => 'pop.')), 110, $errno, $errstr, 2);

if ($socket)
{
fgets($socket, 256);
fputs($socket, 'USER ' . $modSettings['smtp_username'] . "\r\n");
fgets($socket, 256);
fputs($socket, 'PASS ' . base64_decode($modSettings['smtp_password']) . "\r\n");
fgets($socket, 256);
fputs($socket, 'QUIT' . "\r\n");

fclose($socket);
}
}

// Try to connect to the SMTP server... if it doesn't exist, only wait three seconds.
if (!$socket = fsockopen($modSettings['smtp_host'], empty($modSettings['smtp_port']) ? 25 : $modSettings['smtp_port'], $errno, $errstr, 3))
{
// Maybe we can still save this?  The port might be wrong.
if (substr($modSettings['smtp_host'], 0, 4) == 'ssl:' && (empty($modSettings['smtp_port']) || $modSettings['smtp_port'] == 25))
{
if ($socket = fsockopen($modSettings['smtp_host'], 465, $errno, $errstr, 3))
log_error($txt['smtp_port_ssl']);
}

// Unable to connect!  Don't show any error message, but just log one and try to continue anyway.
if (!$socket)
{
log_error($txt['smtp_no_connect'] . ': ' . $errno . ' : ' . $errstr);
return false;
}
}

// Wait for a response of 220, without "-" continuer.
if (!server_parse(null, $socket, '220'))
return false;

if ($modSettings['mail_type'] == 1 && $modSettings['smtp_username'] != '' && $modSettings['smtp_password'] != '')
{
// !!! These should send the CURRENT server's name, not the mail server's!

// EHLO could be understood to mean encrypted hello...
if (server_parse('EHLO ' . $modSettings['smtp_host'], $socket, null) == '250')
{
if (!server_parse('AUTH LOGIN', $socket, '334'))
return false;
// Send the username and password, encoded.
if (!server_parse(base64_encode($modSettings['smtp_username']), $socket, '334'))
return false;
// The password is already encoded ;)
if (!server_parse($modSettings['smtp_password'], $socket, '235'))
return false;
}
elseif (!server_parse('HELO ' . $modSettings['smtp_host'], $socket, '250'))
return false;
}
else
{
// Just say "helo".
if (!server_parse('HELO ' . $modSettings['smtp_host'], $socket, '250'))
return false;
}

// Fix the message for any lines beginning with a period! (the first is ignored, you see.)
$message = strtr($message, array("\r\n." => "\r\n.."));

// !! Theoretically, we should be able to just loop the RCPT TO.
$mail_to_array = array_values($mail_to_array);
foreach ($mail_to_array as $i => $mail_to)
{
// Reset the connection to send another email.
if ($i != 0)
{
if (!server_parse('RSET', $socket, '250'))
return false;
}

// From, to, and then start the data...
if (!server_parse('MAIL FROM: <' . (empty($modSettings['mail_from']) ? $webmaster_email : $modSettings['mail_from']) . '>', $socket, '250'))
return false;
if (!server_parse('RCPT TO: <' . $mail_to . '>', $socket, '250'))
return false;
if (!server_parse('DATA', $socket, '354'))
return false;
fputs($socket, 'Subject: ' . $subject . "\r\n");
if (strlen($mail_to) > 0)
fputs($socket, 'To: <' . $mail_to . ">\r\n");
fputs($socket, $headers . "\r\n\r\n");
fputs($socket, $message . "\r\n");

// Send a ., or in other words "end of data".
if (!server_parse('.', $socket, '250'))
return false;

// Almost done, almost done... don't stop me just yet!
@set_time_limit(300);
if (function_exists('apache_reset_timeout'))
apache_reset_timeout();
}
fputs($socket, "QUIT\r\n");
fclose($socket);

return true;
}

// Parse a message to the SMTP server.
function server_parse($message, $socket, $response)
{
global $txt;

if ($message !== null)
fputs($socket, $message . "\r\n");

// No response yet.
$server_response = '';

while (substr($server_response, 3, 1) != ' ')
if (!($server_response = fgets($socket, 256)))
{
// !!! Change this message to reflect that it may mean bad user/password/server issues/etc.
log_error($txt['smtp_bad_response']);
return false;
}

if ($response === null)
return substr($server_response, 0, 3);

if (substr($server_response, 0, 3) != $response)
{
log_error($txt['smtp_error'] . $server_response);
return false;
}

return true;
}


Nothing in the error logs.

If i copy only the first part (function sendmail) but not the second (function mimespecialchars etc), i have the correct subject but not the correct body. The body is like this:
Content-Type: text/plain; charset=ISO-8859-1

=?ISO-8859-1?B?Q29udGVudXRvDQoNClNhbHV0aSwNCkxvIFN0YWZmIGRpIEZvcnVtIGRlZ2xpIHN0dWRlbnRpIGRlbGxhIEZhY29sdOAgZGkgTGV0dGVyZSBlIEZpbG9zb2ZpYSBkZSAiTGEgU2FwaWVuemEiLg0KDQpodHRwOi8vd3d3LmxldHRlcmVmaWxvc29maWFzYXBpZW56YS5pdC9mb3J1bS9pbmRleC5waHA=?=

With the fix of quake101 all it's ok.

It's more good, for this moment, my fix, or the fix of quake101?

With my fix, the email that i receive, have this:
Content-Transfer-Encoding: quoted-printable

with the fix of quake101, the email that i receive, have this:
Content-Transfer-Encoding: base64

withouth any fix, the email have this:
Content-Type: multipart/alternative; boundary="SMF-0fa1b75dbba34513f8317d6d74e7009d"
Content-Transfer-Encoding: 7bit

Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

and nothing else, nothing in the subject, and the email address have only the email but not the forum name.

Please, fix really this problem in the next release. ;)

forum.Man

i'm having the same problem with emails sent to yahoo accounts.
SMF 1.1.2

i tried quake's fix and will see how that works.

Advertisement: