php mail sends the mail but body is not visiable

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
collette
Forum Newbie
Posts: 10
Joined: Thu Mar 15, 2007 1:23 pm

php mail sends the mail but body is not visiable

Post by collette »

Below is the source of an email, the way mozilla mail shows it. But the body of the mail is not visiable in the normal way. So, if I start mozilla mail and check for new mail, I see the header and below that its blank. Only when I click "view source" I get this:

Code: Select all

From - Thu Mar 15 19:18:14 2007
X-UIDL: 1173982686._smtp.mxdrop29.16846,S=3017
X-Mozilla-Status: 0001
X-Mozilla-Status2: 00000000
Return-Path: <anonymous@somedomain>
Received: from ns1.somedomain(
Received: (qmail 387 invoked by uid 48); 15 Mar 2007 19:18:04 +0100
Date: 15 Mar 2007 19:18:04 +0100
Message-ID: <20070315181804.386.qmail@somedomain>
To: colweb@xs4all.nl
Subject: Test HTML email
From: website@mydomain
Reply-To: webmaster@mydomain
Content-Type: multipart/alternative; boundary="PHP-alt-9b219c8fff7fe3cfea4f4a8b88470cb6"
X-XS4ALL-DNSBL-Checked: mxdrop29.xs4all.nl checked 62.148.174.180 against DNS blacklists
X-Virus-Scanned: by XS4ALL Virus Scanner
X-XS4ALL-Spam-Score: 0.6 () DK_POLICY_SIGNSOME,HTML_MESSAGE,MIME_HEADER_CTYPE_ONLY,NO_REAL_NAME
X-XS4ALL-Spam: NO
Envelope-To: colweb@xs4all.nl
X-UIDL: 1173982686._smtp.mxdrop29.16846,S=3017

--PHP-alt-9b219c8fff7fe3cfea4f4a8b88470cb6 

Content-Type: text/plain; charset=iso-8859-1

Content-Transfer-Encoding: 8bit

Bestelling VVV Actief Gids en/of Kaart.

Uw naam: 

Adres: 

Postcode: 

Plaats: 

e-mail adres: 



VVV Actief gids, aantal: 1 - prijs: 1.00

VVV Actief kaart, aantal: 1 - prijs: 1.00

Sub totaal.........................: 2.00

Korting............................: 0.50

Verzend en administratie kosten....: 2.50

Totaal.............................: 4.00



Bedankt voor uw bestelling. Levertijd is circa 2 werkdagen.

--PHP-alt-9b219c8fff7fe3cfea4f4a8b88470cb6 

Content-Type: text/html; charset=iso-8859-1

Content-Transfer-Encoding: 8bit

<html>

<head></head>

<body>

<table border="1" cellpadding="3" cellspacing="3">

    <tr><td colspan="5"><center>Bestelling VVV Actief Gids en/of Kaart</center></td></tr>

    <tr><td rowspan="8" style="vertical-align: top;">

        <table border="0" cellpadding="0" cellspacing="3">

            <tr><td>Uw naam:</td><td></td></tr>

            <tr><td>Adres:</td><td></td></tr>

            <tr><td>Postcode:</td><td></td></tr>

            <tr><td>Plaats:</td><td></td></tr>

            <tr><td>e-mail adres:</td><td></td></tr>

        </table>

    </td></tr>

    <tr><th>Produkt</th><th>Prijs</th><th>Aantal</th><th>Totaal</th></tr>

    <tr><td>VVV Actief gids</td><td>&euro; 1,00 </td><td>1</td><td>1.00</td></tr>

    <tr><td>VVV Actief kaart</td><td>&euro; 1,00 </td><td>1</td><td>1.00</td></tr>

    <tr><td colspan="3" align="right">Sub totaal: &euro;&nbsp;</td><td>2.00</td></tr>

    <tr><td colspan="3" align="right">Korting: &euro;&nbsp;</td><td>0.50</td></tr>

    <tr><td colspan="3" align="right">Verzend en administratie kosten: &euro;&nbsp;</td><td>2.50</td></tr>

    <tr><td colspan="3" align="right">Totaal: &euro;&nbsp;</td><td>4.00</td></tr>

    <tr><td colspan="5" align="center">Bedankt voor uw bestelling. Levertijd is circa 2 werkdagen.</td></tr>

</table>

</body>

</html>

--PHP-alt-9b219c8fff7fe3cfea4f4a8b88470cb6--


--PHP-alt-9b219c8fff7fe3cfea4f4a8b88470cb6--
The code to produce this mail is:

Code: Select all

<?php
$naam = $_POST['naam'];
$adres = $_POST['adres'];
$pcode = $_POST['pcode'];
$plaats = $_POST['plaats'];
$email = $_POST['email'];
$gids_aantal = $_POST['gids_aantal'];
$gids_totaal = $_POST['gids_totaal'];
$kaart_aantal = $_POST['kaart_aantal'];
$kaart_totaal = $_POST['kaart_totaal'];
$sub_tot = $_POST['sub_tot'];
$korting = $_POST['korting'];
$verzend = $_POST['verzend'];
$totaal = $_POST['totaal'];
//define the receiver of the email
$to = 'colweb@xs4all.nl';
//define the subject of the email
$subject = 'Test HTML email';
//create a boundary string. It must be unique
//so we use the MD5 algorithm to generate a random hash
$random_hash = md5(date('r', time()));
//define the headers we want passed. Note that they are separated with \r\n
$headers = "From: website@mydomain\r\nReply-To: webmaster@mydomain";
//add boundary string and mime type specification
$headers .= "\r\nContent-Type: multipart/alternative; boundary=\"PHP-alt-".$random_hash."\"";
//define the body of the message.
ob_start(); //Turn on output buffering
?>
--PHP-alt-<?php echo $random_hash; ?> 
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 8bit
Bestelling VVV Actief Gids en/of Kaart.

Uw naam: <?php echo "$naam\r\n"; ?>
Adres: <?php echo "$adres\r\n"; ?>
Postcode: <?php echo "$pcode\r\n"; ?>
Plaats: <?php echo "$plaats\r\n"; ?>
e-mail adres: <?php echo "$email\r\n"; ?>

VVV Actief gids, aantal: <?php echo $gids_aantal; ?> - prijs: <?php echo "$gids_totaal\r\n"; ?>
VVV Actief kaart, aantal: <?php echo $kaart_aantal; ?> - prijs: <?php echo "$kaart_totaal\r\n"; ?>
Sub totaal.........................: <?php echo "$sub_tot\r\n"; ?>
Korting............................: <?php echo "$korting\r\n"; ?>
Verzend en administratie kosten....: <?php echo "$verzend\r\n" ?>
Totaal.............................: <?php echo "$totaal\r\n" ?>

Bedankt voor uw bestelling. Levertijd is circa 2 werkdagen.
--PHP-alt-<?php echo $random_hash; ?> 
Content-Type: text/html; charset=iso-8859-1
Content-Transfer-Encoding: 8bit
<html>
<head></head>
<body>
<table border="1" cellpadding="3" cellspacing="3">
    <tr><td colspan="5"><center>Bestelling VVV Actief Gids en/of Kaart</center></td></tr>
    <tr><td rowspan="8" style="vertical-align: top;">
        <table border="0" cellpadding="0" cellspacing="3">
            <tr><td>Uw naam:</td><td><?php echo $naam; ?></td></tr>
            <tr><td>Adres:</td><td><?php echo$adres; ?></td></tr>
            <tr><td>Postcode:</td><td><?php echo $pcode; ?></td></tr>
            <tr><td>Plaats:</td><td><?php echo $plaats; ?></td></tr>
            <tr><td>e-mail adres:</td><td><?php echo $email; ?></td></tr>
        </table>
    </td></tr>
    <tr><th>Produkt</th><th>Prijs</th><th>Aantal</th><th>Totaal</th></tr>
    <tr><td>VVV Actief gids</td><td>&euro; 1,00 </td><td><?php echo $gids_aantal; ?></td><td><?php echo $gids_totaal; ?></td></tr>
    <tr><td>VVV Actief kaart</td><td>&euro; 1,00 </td><td><?php echo $kaart_aantal; ?></td><td><?php echo $kaart_totaal ?></td></tr>
    <tr><td colspan="3" align="right">Sub totaal: &euro;&nbsp;</td><td><?php echo $sub_tot; ?></td></tr>
    <tr><td colspan="3" align="right">Korting: &euro;&nbsp;</td><td><?php echo $korting ?></td></tr>
    <tr><td colspan="3" align="right">Verzend en administratie kosten: &euro;&nbsp;</td><td><?php echo $verzend; ?></td></tr>
    <tr><td colspan="3" align="right">Totaal: &euro;&nbsp;</td><td><?php echo $totaal; ?></td></tr>
    <tr><td colspan="5" align="center">Bedankt voor uw bestelling. Levertijd is circa 2 werkdagen.</td></tr>
</table>
</body>
</html>
--PHP-alt-<?php echo $random_hash; ?>--
<?
//copy current buffer contents into $message variable and delete current output buffer
$message = ob_get_clean();
//send the email
$mail_sent = @mail( $to, $subject, $message, $headers );
//if the message is sent successfully print "Mail sent". Otherwise print "Mail failed" 
echo $mail_sent ? "Mail sent" : "Mail failed";
?>
The mail source and php code contain 'mydomain' and 'somedomain'. In real the right domain names are filled in here.

Things become even stranger when I use my ISP webmail service. Then the mail body is shown. Can somebody point out what is going wrong here?

Thanks.
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

If your server runs linux you need to use \n not \r\n.
collette
Forum Newbie
Posts: 10
Joined: Thu Mar 15, 2007 1:23 pm

Post by collette »

The server indeed runs linux. But changing \r\n to only \n does not solve anything. The reason to use \r\n is because most users will be using a mail client in windows. Linux mail clients seem to know what to do with \r\n but windows clients don't understand \n only. They need \r\n.
User avatar
abeterosso
Forum Newbie
Posts: 11
Joined: Fri Mar 16, 2007 8:50 am
Location: Italy

Post by abeterosso »

//create a boundary string. It must be unique
//so we use the MD5 algorithm to generate a random hash
$random_hash = md5(date('r', time()));

Hi, I'm new to php. Can you explain me this part of your code? Why do you need a random number? Thanks
collette
Forum Newbie
Posts: 10
Joined: Thu Mar 15, 2007 1:23 pm

Post by collette »

Because the email contains both text and html it is a Mime type mail. Mime is specified in these RFC's : 2045, 2046, 2047, 2048 and 2077. But that is not what you were asking.....
It is up to the sending mail client to choose a boundary string that doesn't clash with the body text. Typically this is done by inserting a large random string.
Don't remember where I found this, but I always use some form of random to create the mime boundary. It is possible (or at least it was possible) with uuencoded messages to have a boundary that is the same as some part of the uuencoded stuff. At least at one occasion it happened to me. That was years ago, before I used this random boundary method.
User avatar
abeterosso
Forum Newbie
Posts: 11
Joined: Fri Mar 16, 2007 8:50 am
Location: Italy

Post by abeterosso »

...thank you very much!
your answer is very useful for me 'cause I'm developing an application where a confirmation by email is due...
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

collette wrote:The server indeed runs linux. But changing \r\n to only \n does not solve anything. The reason to use \r\n is because most users will be using a mail client in windows. Linux mail clients seem to know what to do with \r\n but windows clients don't understand \n only. They need \r\n.
Yep, well this is why mail() sucks. Even the manual says to try \n if \r\n is giving double lines but the fact is, you need to do this:

Code: Select all

if (substr(PHP_OS, 0, 3) != "WIN"))
{
    //use \n
}
else
{
    //use \r\n
}
collette
Forum Newbie
Posts: 10
Joined: Thu Mar 15, 2007 1:23 pm

Post by collette »

Have changed \r\n in \n but that does not solve it.

After removing the text part (and boundary stuff), the remaining html mail is visiable in mozilla mail. Same goes for removing the html part and only leave the text part in. It has to be something with the header or mime boundary wy mozilla mail won't show the body.

Have written some php mail scripts before but can't find out what I'm doing wrong here. Anybody?
User avatar
John Cartwright
Site Admin
Posts: 11470
Joined: Tue Dec 23, 2003 2:10 am
Location: Toronto
Contact:

Post by John Cartwright »

d11wtq wrote:
collette wrote:The server indeed runs linux. But changing \r\n to only \n does not solve anything. The reason to use \r\n is because most users will be using a mail client in windows. Linux mail clients seem to know what to do with \r\n but windows clients don't understand \n only. They need \r\n.
Yep, well this is why mail() sucks. Even the manual says to try \n if \r\n is giving double lines but the fact is, you need to do this:

Code: Select all

if (substr(PHP_OS, 0, 3) != "WIN"))
{
    //use \n
}
else
{
    //use \r\n
}
Why not use PHP_EOL constant instead?
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

I was about to say because I didn't kno it existed. But it won't work on a Mac because EOL is \r in that case.
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

collette wrote:Have changed \r\n in \n but that does not solve it.

After removing the text part (and boundary stuff), the remaining html mail is visiable in mozilla mail. Same goes for removing the html part and only leave the text part in. It has to be something with the header or mime boundary wy mozilla mail won't show the body.

Have written some php mail scripts before but can't find out what I'm doing wrong here. Anybody?
Sory, but I have to ask, have you looked at Swift Mailer?

http://www.swiftmailer.org/

You'd probably have this working in 10 mins if you did ;)

EDIT | Your ob_start() could be causing issues with the LE if you're sending via SMTP in which case you'll need to run some LE fixes on the string.

EDIT 2 | Upon closer inspection of your message body you have numerous issues that are going to prevent your mail from working with various clients. The big one... you have no blank line after any of your headers.
collette
Forum Newbie
Posts: 10
Joined: Thu Mar 15, 2007 1:23 pm

Post by collette »

Sory, but I have to ask, have you looked at Swift Mailer?
Just looked at it. Don't have time today to test and see what it will do for me, but will do so tomorrow. Looks like it will do what I need.
EDIT | Your ob_start() could be causing issues with the LE if you're sending via SMTP in which case you'll need to run some LE fixes on the string.

EDIT 2 | Upon closer inspection of your message body you have numerous issues that are going to prevent your mail from working with various clients. The big one... you have no blank line after any of your headers
What kind of fixes on the string are needed? When I remove the html part and still use ob_start() , the text message is shown in mozilla mail. Same goes for the header.
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

I'm inclined to think the issues is temming from the lack of CRLF CRLF between then headers and the mime parts.

However, here's the way I correct EOL:

Code: Select all

/**
 * Fixes line endings to be whatever is specified by the user
  * SMTP requires the CRLF be used, but using sendmail in -t mode uses LF
  * This method also escapes dots on a start of line to avoid injection
  * @param string The data to fix
  * @return string
  */
  protected function fixLE($data, $le)
  {
      $data = str_replace(array("\r\n", "\r"), "\n", $data);
      if ($le != "\n") $data = str_replace("\n", $le, $data);
      return $data = str_replace($le . ".", $le . "..", $data);
  }
http://swiftmailer.svn.sourceforge.net/ ... iew=markup
collette
Forum Newbie
Posts: 10
Joined: Thu Mar 15, 2007 1:23 pm

Post by collette »

Sorry for the late reaction. Have changed so much to the original code that it isn't original code anymore. But it finally works.

The most important thing had to do with "\r\n" or "\n". So I included this code:

Code: Select all

// Is the OS Windows or Mac or Linux
if (strtoupper(substr(PHP_OS,0,3)=='WIN')) {
  $eol="\r\n";
} elseif (strtoupper(substr(PHP_OS,0,3)=='MAC')) {
  $eol="\r";
} else {
  $eol="\n";
}
I found this code on an other website dealing with sending mail with php. And inside the rest of the code changed "\r\n" and "\n" to .$eol;

So, for instance this line:

Code: Select all

$headers = "From: website@mydomain\r\nReply-To: webmaster@mydomain";
became:

Code: Select all

$headers = "From: website@mydomain".$eol;
$headers .= "Reply-To: webmaster@mydomain".$eol;
d11wtq was right about the hole end of line thing. Therefore thanks d11wtq. It took me some time to see what en where I had to make changes. If you wish to see the final code, please let me know.

You can see the form in action on http://www.vvv-wymbrits.nl (press the button: bestellen in the right column).
Post Reply