Forum Moderators: coopster

Message Too Old, No Replies

How to send HTML e-mail using mail()?

Can't find a tutorial on this - please help

         

mlkarie

10:06 am on Mar 24, 2004 (gmt 0)

10+ Year Member



This could be a bit of a newbie question:

I need to send an e-mail in HTML format (including images) using the PHP mail function.

I have tried placing HTML tags like <br> etc. How does one write this kind of e-mail so that the recipient's Outlook Express or whatever recognises and interprets the HTML format?

Where can I find a tutorial on this?

Would be grateful for some help.

jetboy_70

11:10 am on Mar 24, 2004 (gmt 0)

10+ Year Member



Here's the function that I use for multipart-MIME email. It's been tested across a wide range of email clients and seems pretty solid.

<?php

$to_name = 'Joe Bloggs';
$to_email = 'joe@joesemail.com';
$from_name = 'Your Name';
$from_email = 'you@youremail.com';
$subject = 'Mail Subject';
$body_simple = 'Simple content for non-MiME-compliant clients';
$body_plain = 'Plain text content';
$body_html = '<html><head></head><body>HTML content</body></html>';

echo api_email($to_name, $to_email, $from_name, $from_email,
$subject, $body_simple, $body_plain, $body_html);

// MIME email
function api_email($to_name, $to_email, $from_name, $from_email,
$subject, $body_simple, $body_plain, $body_html)
{
echo $to_name;
$boundary = api_password(16);
$headers = "From: \"".$from_name."\" <".$from_email.">\n";
$headers .= "To: \"".$to_name."\" <".$to_email.">\n";
$headers .= "Return-Path: <".$from_email.">\n";
$headers .= "MIME-Version: 1.0\n";
$headers .= "Content-Type: multipart/alternative; boundary=\"".$boundary."\"\n\n";
$headers .= $body_simple."\n";
$headers .= "--".$boundary."\n";
$headers .= "Content-Type: text/plain; charset=ISO-8859-1\n";
$headers .= "Content-Transfer-Encoding: 8bit\n\n";
$headers .= $body_plain."\n";
$headers .= "--".$boundary."\n";
$headers .= "Content-Type: text/HTML; charset=ISO-8859-1\n";
$headers .= "Content-Transfer-Encoding: 8bit\n\n";
$headers .= $body_html."\n";
$headers .= "--".$boundary."--\n";

mail('', $subject, '', $headers);

}

// Generate random alphanumeric password
function api_password($length = 8)
{
srand((double) microtime() * 1000000);
$alpha = array('a','b','c','d','e','f','g','h','i','j','k','l',
'm','n','o','p','q','r','s','t','u','v','w','x','y','z');
$options = array('alpha','number');

for ($i = 0; $i < $length; $i++)
{
$char = array_rand($options,1);
if ($options[$char] == 'alpha')
{
$random_letter = rand (0,25);
$password .= $alpha[$random_letter];
}
else
{
$random_number = rand (0,9);
$password .= $random_number;
}
}
return $password;
}

?>

Thing you should know:

. This version used UNIX \n line feeds. If on a Windows box they should be replaced with Windows line feeds

[Edit: Removed double underscore in $body_html]

[edited by: jetboy_70 at 12:02 pm (utc) on Mar. 24, 2004]

mlkarie

11:52 am on Mar 24, 2004 (gmt 0)

10+ Year Member



Many thanks, jetboy_70, for the quick reply. Will go and try it later today.

mlkarie

incywincy

12:38 pm on Mar 24, 2004 (gmt 0)

10+ Year Member



I've used Zend before and found it very easy to configure.

jurry

12:04 pm on Apr 9, 2004 (gmt 0)



sorry nice script, but how can i use this with an dbase from mysql so this would be a newsletter

mlkarie

7:29 pm on Apr 15, 2004 (gmt 0)

10+ Year Member



Have been away on holiday, hence the delay...

Below is the php file I wrote, having put together the code from above (from jetboy_70), in conjunction with what I found generated by Outlook Express when I sent an HTML email with one picture in it.

That's why I have two boundaries there.

It's now displaying the html content correctly, but the jpg file arrives as an attachment (*.txt file), and no picture is displayed.

Need to go and dig around in the code examples that I downloaded.. is this something to do with specifying "inline" somewhere?

Re mysql and the database:
Jurry, you and I are after the same end result. I take it that the html code will be stored in a database table, along with the names of the image files, and that I'll be writing code that fetches these.

However, first things first, which is to get the jpg file to display as a picture, not arrive as a *.txt attachment.

If anyone can help, that would be great.

Below is what arrives as a text file, and underneath that I'm pasting my code, for anyone that would like to have a look.

TEXT FILE (attachment) CONTENTS:

--6we5zg38a6l2341i
Content-Type: image/jpeg

name="crabtree.jpg"
Content-Transfer-Encoding: base64
Content-Description: "Photograph of a boat"
Content-ID: <000901c41180ff71a320fe41010a@laptop>
/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAoHBwcIBwoICAoPCgkKDxINCgoNEhQQEBEQEBQWERIS
EhIRFhQXGRoZFxQfHyEhHx8qKioqKi0tLS0tLS0tLS3/2wBDAQsLCw8PDxcRERcYFBMUGB4cHBwc
HiMeHh8eHiMnIi ....followed by rest of the base64 encoded stuff, followed by the last boundary marker: --6we5zg38a6l2341i--

MY PHP FILE:

<?php

$to_name = 'Joe Bloggs';
$to_email = 'someone@global.com';
$from_name = 'who_from';
$from_email = 'you@youremail.com';
$subject = 'Test: HTML Mail Subject';
$body_simple = 'Simple content for non-MiME-compliant clients';
$body_plain = 'Plain text content';
$body_html = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head></head><body>This email is testmail7 <br>HTML<strong> cont</strong>ent
<IMG alt="" hspace=0
src="cid:000901c41180ff71a320fe41010a@laptop"=20
align=baseline border=0>
</body></html>';

$fpath = '';
$fname = "crabtree.jpg";
$filedata = fread(fopen("crabtree.jpg","rb"), filesize("crabtree.jpg"));

$filedata = chunk_split(base64_encode($filedata));
$filedata = preg_replace("/\r\n/i", "\n", $filedata);


echo $to_name;
$boundary1 = api_password(16);
$boundary2 = api_password(16);
$headers = "From: \"".$from_name."\" <".$from_email.">\r\n";
$headers .= "To: \"".$to_name."\" <".$to_email.">\r\n";
$headers .= "Return-Path: <".$from_email.">\r\n";
$headers .= "MIME-Version: 1.0\r\n";

$headers .= "Content-Type: multipart/related; type=\"multipart/alternative\"; boundary=\"".$boundary2."\"\r\n\r\n";
$headers .= "This is a multi-part message in MIME format\r\n\r\n";
$headers .= "--".$boundary2."\r\n";

$headers .= "Content-Type: multipart/alternative; boundary=\"".$boundary1."\"\r\n\r\n";
$headers .= $body_simple."\r\n";
$headers .= "--".$boundary1."\r\n";

$headers .= "Content-Type: text/plain; charset=ISO-8859-1\r\n";
$headers .= "Content-Transfer-Encoding: 8bit\r\n\r\n";
$headers .= $body_plain."\r\n";
$headers .= "--".$boundary1."\r\n";

$headers .= "Content-Type: text/HTML; charset=ISO-8859-1\r\n";
$headers .= "Content-Transfer-Encoding: 8bit\r\n\r\n";
$headers .= $body_html."\r\n";
$headers .= "--".$boundary1."\r\n";

$headers .= "--".$boundary2."\r\n";

$headers .= "Content-Type: image/jpeg\r\n\r\n";
$headers .= "name= \"crabtree.jpg\"\r\n\r\n" ;
$headers .= "Content-Transfer-Encoding: base64\r\n\r\n";
$headers .= "Content-Description: \"Photograph of a boat\"\r\n\r\n";
$headers .= "Content-ID: <000901c41180ff71a320fe41010a@laptop>\r\n\r\n"; // copied this from testhtml.eml for now
$headers .= $filedata;
$headers .= "--".$boundary2."--\r\n";

mail('my_email_address', $subject, '', $headers);

// Generate random alphanumeric password
function api_password($length = 8)
{

$password = '';
srand((double) microtime() * 1000000);
$alpha = array('a','b','c','d','e','f','g','h','i','j','k','l',
'm','n','o','p','q','r','s','t','u','v','w','x','y','z');
$options = array('alpha','number');

for ($i = 0; $i < $length; $i++)
{
$char = array_rand($options,1);
if ($options[$char] == 'alpha')
{
$random_letter = rand (0,25);
$password .= $alpha[$random_letter];
}
else
{
$random_number = rand (0,9);
$password .= $random_number;
}
}
return $password;

}

?>

Netizen

9:24 pm on Apr 15, 2004 (gmt 0)

10+ Year Member



I haven't used this myself but a good place to look might be in the PEAR Mail_Mime [pear.php.net] class. This would make maintaining the code simpler.

bcolflesh

9:26 pm on Apr 15, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Save time and trouble - use the PHPMailer class free from SourceForge:

[phpmailer.sourceforge.net...]

jetboy_70

9:58 pm on Apr 15, 2004 (gmt 0)

10+ Year Member



mlkarie, maybe you should take their advice as I won't be able to help here. I dumped all my images onto the web and linked to them from the email. This is how Amazon, eBay etc. do theirs, so I figured I'd follow suit.

I'm also not sure that inline images (or whatever the correct term is) have the same level of support from the various email clients - particular webmail clients. And of course there's the extra overhead in sending out larger emails (and clogging up the readers' inboxes).

mlkarie

4:42 am on Apr 16, 2004 (gmt 0)

10+ Year Member



Gee whizz, have just got it right - yippee! :-)

There were two code glitches in the piece of code that I sent above.

I've had a brief look at the Pear Mail MIME class; if I read it correctly this class takes the file name of the image and puts that in the right place. Presume that means one would give the path to the file, which means the file resides on the server, etc.

The reason why I'm trying to send the inline stuff is so that these kind of newsletters can be read in full offline; maybe I'm just not quite understanding it yet.

However, what I do understand is that I SERIOUSLY (this one warrants capital letters) must start working in OOP, with PHP classes, etc.

I started learning PHP from scratch in July last year, using the tutorials on the web. (Thanks to all the guys who write tutorials.) However, the tutorials I used were not OOP based.

Must, must find the time now to get myself over the first hurdle re OOP, so that classes will be a breeze.

Thanks for all the help
mlkarie

Ps. If anyone wants the corrected version of the above code, just shout, and I'll send it.

HelenDev

8:58 am on Apr 16, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



jetboy_70, please accept my apologies if this is a dumb question, but what is the reason for the password bit in the code?

I am using php mail to send very simple plain text email using a short script I wrote like this...

mail("me@domain.com", "$subject", "$msgbody");

I'm just curious to understand the whole mail thing better, and know if I'm missing something I should be doing.

jetboy_70

9:30 am on Apr 16, 2004 (gmt 0)

10+ Year Member



No problem - not a dumb question.

Apparently you need a unique boundary between the different content types when using multipart MIME. In my code I only use one string, as I've only got text content. Thus a random string generator is overkill.

However, mlkarie's version calls the function twice (as there's image content in addition to the text), which results in two different boundaries. This is really why I put the code in, to make the email function scaleable beyond my immediate needs.

Why is it called 'api_password' when it's clearly got nothing to do with passwords? This is what I used the function for before I appropriated it for HTML email!

Unless you are sending multipart MIME emails (which from the sound of it you aren't), there's no need for any sort of boundary.