Gmail无法在电子邮件中渲染HTML内容。

4

我将用一个非常基本的例子再试一次。当我使用PHP发送电子邮件到其他电子邮件客户端时,除了Gmail以外,我没有任何问题。当我在Gmail中查看邮件时,我只看到邮件代码。 Gmail不显示HTML,它只显示代码。以下是我的脚本:

<?php
$to = "someone@gmail.com";
$subject = "Test HTML E-mail";
$random_hash = md5(date("r", time()));
$mID = md5($to);
$headers = "From: admin@yellowcas.com" . "\n" . "Reply-To: admin@yellowcas.com" . "\n";
$headers .= "Errors-To: someone@yahoo.com" . "\n";
$headers .= "MIME-Version: 1.0" . "\n";
$headers .= "Content-Type: multipart/alternative; boundary=". $random_hash ." ; Message-ID: <" . $mID . ">" . "\n"; 
ob_start();
?>
--<?php echo $random_hash; ?> 
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Hello, Tom!!! 
This is simple text email message.

--<?php echo $random_hash; ?> 
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: 7bit

<!doctype html>
<head>
<title>Untitled Document</title>
</head>
<body>
<h2>Hello, Tom!</h2>
<p>This is something with <strong>HTML</strong> formatting.</p>
</body>
</html>

--<?php echo $random_hash; ?>-- 

<?php
$message = ob_get_clean();
$mail_sent = @mail( $to, $subject, $message, $headers );
echo $mail_sent ? "Mail sent" : "Mail failed";
?>

我已经尝试过该脚本,不带DOCTYPE和带DOCTYPE。我认为HTML没有问题。我相信 Gmail 之所以无法识别边界字符串是由于某种原因。当我打开电子邮件时,我看到以下内容:

--111f3d21df6a6eb40a42e9337a600c21
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Hello, Tom!!!
This is simple text email message.

--111f3d21df6a6eb40a42e9337a600c21
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: 7bit

<!doctype html>
<head>
<title>Untitled Document</title>
</head>
<body>
<h2>Hello, Tom!</h2>
<p>This is something with <strong>HTML</strong> formatting.</p>
</body>
</html>

--111f3d21df6a6eb40a42e9337a600c21--

请问有人能告诉我为什么Gmail会渲染整个消息而不是编码HTML吗?就好像Gmail不认识分界字符串一样。我该怎么解决呢?

另外,这是一个我在互联网上找到的基本的PHP电子邮件脚本。虽然我已经做了一些修改,但它在Gmail中仍然无法工作。所有其他电子邮件客户端都可以正常呈现。敬请帮忙!我已经懵了。谢谢。

当我在由Fred -ii-提交的代码示例下面添加了$headers行时,Gmail渲染了HTML,但仍然显示分界字符串和纯文本消息。这是电子邮件的样子:

--f8451c07b6649388e8938cfa12ea21e6 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 7bit Hello, Greg!!! This is simple text email message. --f8451c07b6649388e8938cfa12ea21e6 Content-Type: text/html; charset=iso-8859-1 Content-Transfer-Encoding: 7bit

Hello, Tom!

This is something with HTML formatting.
--f8451c07b6649388e8938cfa12ea21e6--

希望翻译得没问题。


你的初始标头需要包含$headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";,就像http://php.net/mail中所述,在`$headers .= "MIME-Version: 1.0" . "\n";`下面。 - Funk Forty Niner
停止使用 mail() 函数,改用 PHP Mailer 或 Swift Mailer。 - user557846
@Fred-ii 我刚刚尝试将其放入其中。问题是它是一个多部分消息。它有一个纯文本部分和一个html部分。我还被告知gmail不会接受\r字符。它会导致插入额外的一行。这就是为什么我的代码中没有任何东西的原因。 - Greg G
Gmail 接受 \r 字符。我在所有的脚本中使用 \r\n,所有的电子邮件客户端包括 Gmail 都能正常接收。我甚至用它测试了下面的答案 $headers .= "MIME-Version: 1.0" . "\r\n";,结果也很好。 - Funk Forty Niner
@Fred -ii- 这是我看到的一篇帖子,说在代码中不要使用 \r。http://stackoverflow.com/questions/10327354/how-to-send-html-emails-to-gmail-with-php-yahoo-works-not-gmail?rq=1 - Greg G
我看到了你的回答中的Edit 2,谢谢。 - Funk Forty Niner
2个回答

4

编辑 #4

以下是另一个不错的版本,看起来更容易使用:

<?php
//define the receiver of the email
$to = 'email@example.com';
//define the subject of the email
$subject = 'Test HTML email';
 
// Generate a random boundary string
$mime_boundary = '_x'.sha1(time()).'x';
 
// Using the heredoc syntax to declare the headers
$headers = <<<HEADERS
From: Test <email@example.com>
MIME-Version: 1.0
Content-Type: multipart/alternative;
 boundary="PHP-alt$mime_boundary"
HEADERS;
 
// Use our boundary string to create plain text and HTML versions
$message = <<<MESSAGE
--PHP-alt$mime_boundary
Content-Type: text/plain; charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
 
This Is a Plain Text Email
 
This message has no HTML. http://www.google.com
 
--PHP-alt$mime_boundary
Content-type: text/html; charset=iso-8859-1
Content-Transfer-Encoding: 7bit
 
<html>
<body>
<h1>This Is an HTML Email</h1>
<p>
This message is composed in <a href="http://www.google.com">GOOGLE, click here</a>.
</p>
</body>
</html>
--PHP-alt$mime_boundary--
MESSAGE;
 
// Send the message
if(!mail($to, $subject, $message, $headers))
{
// If the mail function fails, return an error message
echo "Something went wrong!";
}
else
{
// Return a success message if nothing went wrong
echo "Message sent successfully. Check your email!";
}
?>

编辑3

另一种经过测试的方法:(迄今为止是更好的方法)


<?php

function send_email(

$to='email@example.com', 
$from='email@example.com', 
$subject='test', 
$html_content='<b>HELLO in HTML bold</b>', 
$text_content='Hi there in plain text', 
$headers='') 

{ 
    # Setup mime boundary
    $mime_boundary = 'Multipart_Boundary_x'.md5(time()).'x';

    $headers  = "MIME-Version: 1.0\r\n";
    $headers .= "Content-Type: multipart/alternative; boundary=\"$mime_boundary\"\r\n";
    $headers .= "Content-Transfer-Encoding: 7bit\r\n";

    $body    = "This is a multi-part message in mime format.\n\n";

    # Add in plain text version
    $body   .= "--$mime_boundary\n";
    $body   .= "Content-Type: text/plain; charset=\"charset=us-ascii\"\n";
    $body   .= "Content-Transfer-Encoding: 7bit\n\n";
    $body   .= $text_content;
    $body   .= "\n\n";

    # Add in HTML version
    $body   .= "--$mime_boundary\n";
    $body   .= "Content-Type: text/html; charset=\"UTF-8\"\n";
    $body   .= "Content-Transfer-Encoding: 7bit\n\n";
    $body   .= $html_content;
    $body   .= "\n\n";

    # Attachments would go here
    # But this whole email thing should be turned into a class to more logically handle attachments, 
    # this function is fine for just dealing with html and text content.

    # End email
    $body   .= "--$mime_boundary--\n"; # <-- Notice trailing --, required to close email body for mime's

    # Finish off headers
    $headers .= "From: $from\r\n";
    $headers .= "X-Sender-IP: $_SERVER[SERVER_ADDR]\r\n";
    $headers .= 'Date: '.date('n/d/Y g:i A')."\r\n";

    # Mail it out
    return mail($to, $subject, $body, $headers);
}
send_email(); // call the function
?>

编辑 2

这个方法起作用了,在Gmail中只显示了HTML格式,因此纯文本理论上也应该可以。

<?php

$notice_text = "This is a multi-part message in MIME format.";
$plain_text = "This is a plain text email.\r\nIt is very cool.";
$html_text = "<html><body>This is an <b style='color:purple'>HTML</b>" .
             "text email.\r\nIt is very cool.</body></html>";

$semi_rand = md5(time());
$mime_boundary = "==MULTIPART_BOUNDARY_$semi_rand";
$mime_boundary_header = chr(34) . $mime_boundary . chr(34);

$to = "Me <email@example.com>";
// $bcc = "You <you@you.com>, Them <them@them.com>";
$from = "Him <another@example.com>";
$subject = "My Email";

$body = "$notice_text

--$mime_boundary
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

$plain_text

--$mime_boundary
Content-Type: text/html; charset=us-ascii
Content-Transfer-Encoding: 7bit

$html_text

--$mime_boundary--";

if (@mail($to, $subject, $body, 
    "From: " . $from . "\n" . 
    "bcc: " . $bcc . "\n" . 
    "MIME-Version: 1.0\n" . 
    "Content-Type: multipart/alternative;\n" . 
    "     boundary=" . $mime_boundary_header))
    echo "Email sent successfully.";
else
    echo "Email NOT sent successfully!";

?>

编辑1

尝试使用此版本:(在任何其他地方均未测试附加代码)

<?php
$to = "someone@gmail.com";
$subject = "Test HTML E-mail";

$headers = "From: admin@yellowcas.com" . "\n" . "Reply-To: admin@yellowcas.com" . "\r\n";
$headers .= "MIME-Version: 1.0\r\n";

//unique boundary
$boundary = uniqid("HTMLDEMO");

//tell e-mail client this e-mail contains//alternate versions
$headers .= "Content-Type: multipart/mixed; boundary = $boundary\r\n\r\n";

//plain text version of message
$body = "--$boundary\r\n" .
   "Content-Type: text/plain; charset=ISO-8859-1\r\n" .
   "Content-Transfer-Encoding: base64\r\n\r\n";
$body .= chunk_split(base64_encode("

Hello, Tom!!! 
This is simple text email message.

"));

//HTML version of message
$body .= "--$boundary\r\n" .
   "Content-Type: text/html; charset=ISO-8859-1\r\n" .
   "Content-Transfer-Encoding: base64\r\n\r\n";
$body .= chunk_split(base64_encode("

<!doctype html>
<head>
<title>Untitled Document</title>
</head>
<body>
<h2>Hello, Tom!</h2>
<p>This is something with <strong>HTML</strong> formatting.</p>
</body>
</html>


"));
ob_start();

?>

<?php
$message = ob_get_clean();
$mail_sent = mail( $to, $subject, $body, $headers );
echo $mail_sent ? "Mail sent" : "Mail failed";
?>

您需要在初始标题中使用以下内容:
$headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";

below:

$headers .= "MIME-Version: 1.0" . "\n";

根据PHP.net手册,已经进行了测试(成功以HTML格式发送到我的Gmail,而非代码)。
<?php
$to = "someone@gmail.com";
$subject = "Test HTML E-mail";
$random_hash = md5(date("r", time()));
$mID = md5($to);
$headers = "From: admin@yellowcas.com" . "\n" . "Reply-To: admin@yellowcas.com" . "\n";
$headers .= "Errors-To: someone@yahoo.com" . "\n";
$headers .= "MIME-Version: 1.0" . "\n";
$headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
$headers .= "Content-Type: multipart/alternative; boundary=". $random_hash ." ; Message-ID: <" . $mID . ">" . "\n"; 
ob_start();
?>

// rest of code below...

我成功渲染了HTML,但仍然看到边界字符串和纯文本消息。 - Greg G
这段代码比我的代码更好。现在它可以显示消息而不带边界字符串了。唯一的问题是它同时显示了纯文本和HTML文本。有什么想法吗? - Greg G
请参见Edit 3,它仅显示HTML,但是当您查看完整的标头时,它将显示纯文本中的“Hi there” @GrG。 - Funk Forty Niner
非常感谢!编辑2完美地运行了!在雅虎和Gmail中都呈现出色。现在我可以尝试修改此脚本以发送更复杂的HTML电子邮件。非常感谢您的所有帮助!我还接受了您在此帖子上的答案。 - Greg G
非常感谢,很高兴能够帮助您。第三种方法也不错。@GrG - Funk Forty Niner
显示剩余4条评论

1

好的,我只是通过添加这三行头文件就使它工作了,所以你可以试一下并让我知道结果。

$headers = "MIME-Version: 1.0" . "\r\n";
$headers .= "Content-type:text/html;charset=UTF-8" . "\r\n";

// More headers
$headers .= 'From: <example@gmail.com>' . "\r\n";


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接