HTML Emails displaying as raw source


I’ve built a system for sending out HTML emails via PHP with a plain text alternative. It works fine on all the systems I’ve tested it on (Mac/PC, Outlook, Apple Mail, Thunderbird, Hotmail, Yahoo, GMail, Android) but not on the client’s PC (software unknown) and iPhone. What he gets is the raw source of the message, starting from just before the end of the headers.

In trying to work out why it wasn’t working I looked at some big-name HTML emails that I’d received. One of the main differences was that I was using this:

Content-Type: text/plain; charset="iso-8859-1"
Content-Transfer-Encoding: 7bit

whereas others were using:

Content-type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable

After much messing around I switched over to using quoted-printable (with short lines and encoded characters) and eventually got it working properly in all systems but still no iPhone.

Then I noticed that everyone else split the Content-type header onto two lines like this:

Content-Type: multipart/alternative;

I tried that and also tried a much shorter boundary string and that also made no difference.

I’ve spent most of the day on this and it’s starting to drive me mad so I hope someone can help. Here’s the source from a typical email (with a couple of bits omitted):

Received: by xx.xx.xx.xx with SMTP id da6cs21405vcb;
        Fri, 25 Mar 2011 08:56:16 -0700 (PDT)
Return-Path: <>
Received: from ( [])
        by with ESMTPS id o11si1892331wer.9.2011.
        (version=TLSv1/SSLv3 cipher=OTHER);
        Fri, 25 Mar 2011 08:56:14 -0700 (PDT)
Received-SPF: pass ( best guess record for ......
Received: (qmail 22592 invoked by uid 10006); 25 Mar 2011 15:56:14 +0000
Date: 25 Mar 2011 15:56:14 +0000
Message-ID: <>
Subject: ...
From: Sender <>
X-Mailer: PHP
MIME-Version: 1.0
Content-Type: multipart/alternative; boundary="PHP-alt-46832"
Content-Transfer-Encoding: quoted-printable

Content-type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable

[plain text content]

Content-type: text/html; charset=utf-8
Content-Transfer-Encoding: quoted-printable

[html content]


Anyone have any ideas? The problem systems start showing the raw source from the ‘MIME-Version’ line, though I’ve tried removing that line and the one before it but neither makes a difference.


Are you definitely appending \r
to X-Mailer: PHP?

I’ve seen this issue with malformed headers when each header line isn’t followed by a \r\

Hi, thanks for your reply. Yep, I think the headers are OK, though I did try removing the X-Mailer line in case it was causing the problem and that made no difference. Here are the (somewhat messy) lines in question:

    $headers = "From: $mail_name <$mail_from>\\r\
" . "Reply-To: $mail_from\\r\
" .'X-Mailer: PHP' . "\\r\
    $headers .= 'MIME-Version: 1.0' . "\\r\
    $headers .= "Content-Type: multipart/alternative; boundary=\\"".$random_hash."\\"" . "\\r\
    $headers .= 'Content-Transfer-Encoding: quoted-printable' . "\\r\

I also tried just sending the HTML part (ie. with a “Content-type: text/html” header) and that still just shows up as raw HTML.

Doesn’t the last header need a blank line - another \r\

  • after it to indicate when the content starts?

Mittineague is correct, there should be two new lines between your last header and the beginning of content

Hmm, it comes through with two lines between the header and the content (see first post) but I haven’t actually put them there myself. Thanks for the suggestion; I’ll try it when I get a mo and report back.

OK, I’ve added an extra \r
and also tried moving the MIME-Version line up but neither makes any difference.

Anyone have any other ideas? I’ve tried everything I can think of but nothing seems to work :frowning:

Update: I tried sending a test in the same way from another server and it worked fine. I then tried sending a mail directly from the command line with sendmail, with the same headers and body, and that also worked fine.

Thinking it might have been a PHP issue we upgraded the server to 5.3 and unfortunately it still doesn’t work :frowning:

Any other suggestions anyone? I can’t think of any PHP settings to tweak so I don’t really know what else to try.