Composing Messages in HTML for MIME Email with PHP

Welcome to the fourth episode of the series, "Sending MIME email with PHP." In this article, I’m going to show you how to provide the MIME mailer class with the ability to send email messages in HTML format. This will greatly extend its functionality, so don’t miss this tutorial.

The Multipurpose Internet Mail Extension (short for MIME) permits, among other things, sending email messages in HTML format, working with different types of attached files, and so forth. But, the good news here is that you can use all the features offered by MIME directly with PHP. You can develop applications that dispatch MIME-compliant messages to a bunch of recipients.

Naturally, sending MIME email with PHP can be done using either a procedural or an object-oriented approach. If you’re interested in utilizing this latter, you’ll find a friendly guide on building a highly modular MIME mailer class in this series of articles. It utilizes this extension in order to send messages in both plain text and HTML format. It also supports working with file attachments.

At this point, I should assume that you’re well aware of the goals of this series. Thus, it’s an excellent time to rehash the topics covered in the last tutorial, in case you haven’t had the chance to read it yet. In that particular article, I demonstrated how to improve the signature of the MIME mailer class that I built in the beginning of this series by adding a brand new property, called “$mimeTypes,” to it. This helped store all the MIME types supported by the class, when dealing with file attachments.

Of course, after introducing this minor modification to the signature of the aforementioned mailer class, its whole structure looked more compact and more efficient. Nonetheless, my primary intention here is to teach you how to create an expansible PHP class that takes real advantage of the MIME extension.

With the preliminaries out of our way, let’s jump forward and see how to add HTML capabilities to this MIME mailer class. It’s going to be an instructive experience!

{mospagebreak title=Review: sending MIME-compliant messages in plain text format}

Before I get my hands dirty and teach you how to provide the MIME mailer class with the ability to send email messages in HTML format, first I’d like to list its current signature, so you can recall how it looked originally.

Here’s the full source code that corresponds to the “Mailer” class built during the previous tutorial:


class Mailer{

var $sender;

var $recipient;

var $subject;

var $headers=array();

var $mimeTypes=array();

var $attachments=array();

function Mailer($sender,$recipient,$subject,$message){

// validate incoming parameters

if(!preg_match("/^.+@.+$/",$sender)){

trigger_error(‘Invalid value for email sender.’);

}

if(!preg_match("/^.+@.+$/",$recipient)){

trigger_error(‘Invalid value for email recipient.’);

}

if(!$subject||strlen($subject)>255){

trigger_error(‘Invalid length for email subject.’);

}

if(!$message){

trigger_error(‘Invalid value for email message.’);

}

$this->sender=$sender;

$this->recipient=$recipient;

$this->subject=$subject;

$this->message=$message;

// define some default MIME headers

$this->headers['MIME-Version']=’1.0′;

$this->headers['Content-Type']=’multipart/mixed;boundary="MIME_BOUNDRY"';

$this->headers['From']='<‘.$this->sender.’>';

$this->headers['Return-Path']='<‘.$this->sender.’>';

$this->headers['Reply-To']=$this->sender;

$this->headers['X-Mailer']=’PHP5′;

$this->headers['X-Sender']=$this->sender;

$this->headers['X-Priority']=’3′;

// define some default MIME types

$this->mimeTypes['image/jpeg']=’jpg';

$this->mimeTypes['image/jpg']=’jpg';

$this->mimeTypes['image/gif']=’gif';

$this->mimeTypes['text/plain']=’txt';

$this->mimeTypes['text/html']=’htm';

$this->mimeTypes['text/xml']=’xml';

$this->mimeTypes['application/pdf']=’pdf';

}

// create text part of the message

function buildTextPart(){

return "–MIME_BOUNDRYnContent-Type: text/plain; charset=iso-8859-1nContent-Transfer-Encoding: quoted-printablennn".$this->message."nn";

}

// create attachments part of the message

function buildAttachmentPart(){

if(count($this->attachments)>0){

$attachmentPart=”;

foreach($this->attachments as $attachment){

$fileStr=file_get_contents($attachment);

$fileStr=chunk_split(base64_encode($fileStr));

$attachmentPart.="–MIME_BOUNDRYnContent-Type: ".$this->getMimeType($attachment)."; name="".basename($attachment).""nContent-disposition: attachmentnContent-Transfer-Encoding: base64nn".$fileStr."nn";

}

return $attachmentPart;

}

}

// create message MIME headers

function buildHeaders(){

foreach($this->headers as $name=>$value){

$headers[]=$name.': ‘.$value;

}

return implode("n",$headers)."nThis is a multi-part message in MIME format.n";

}

// add new MIME header

function addHeader($name,$value){

$this->headers[$name]=$value;

}

// add new attachment

function addAttachment($attachment){

if(!file_exists($attachment)){

trigger_error(‘Invalid attachment.’,E_USER_ERROR);

}

$this->attachments[]=$attachment;

}

// get MIME Type of attachment

function getMimeType($attachment){

$attachment=explode(‘.’,basename($attachment));

if(!$mimeType=array_search(strtolower($attachment[count($attachment)-1]),$this->mimeTypes)){

trigger_error(‘MIME Type not found.’,E_USER_ERROR);

}

return $mimeType;

}

// send email

function send(){

$to=$this->recipient;

$subject=$this->subject;

$headers=$this->buildHeaders();

$message=$this->buildTextPart().$this->buildAttachmentPart()."–MIME_BOUNDRY–n";

if(!mail($to,$subject,$message,$headers)){

trigger_error(‘Error sendind email.’,E_USER_ERROR);

}

}

}


Does the above class ring any bells? I bet it does! As you can see, the class offers decent functionality, since it’s capable of sending MIME-compliant email messages; it supports working with file attachments as well.

To demonstrate how the above class does its business, I included a short script that puts it to work. Here it is:


// create a new instance of the ‘Mailer’ class

$mailer=&new Mailer(‘alejandro@mydomain.com,’mybuddy@yourdomain.com’,’Testing mailer class’,’Hello buddy. I am sending to you a couple of fun images.’);

// add some attachments

$mailer->addAttachment(‘file1.jpg’);

$mailer->addAttachment(‘file.jpg’);

// send MIME email

$mailer->send();


As you can see, the class is used to send a simple message with a couple of attached files to a hypothetical recipient. That was pretty simple to grasp, right?

At this point, you hopefully remember how to use the previous “Mailer” class. So, what’s the next step to take? As you may have noticed, this class is only capable of sending messages in plain text format, but as I explained in the beginning, the MIME extension allows you to send email in HTML very easily.

Thus, in the upcoming section I’m going to teach you how to add a brand new method to the aforementioned “Mailer” class that provides it with the capacity to send HTML-formatted email messages.

This topic will be discussed in detail in the next few lines, so go ahead and read them.

{mospagebreak title=Sending email messages in HTML format}

As I stated in the prior section, it’d be extremely convenient to provide the “Mailer” class with the ability to send email messages in HTML format. This would exploit all the features offered by the MIME extension.

Fortunately, incorporating this functionality to the mailer class is a only a matter of adding a pair of brand new methods, which, obviously, will be responsible for dispatching email messages formatted in HTML. However, this is merely theory that needs to be put into practice. Thus, let me show you the modified signature of the “Mailer” class, including the additional methods that send email in HTML.

Here’s the full source code of the class:


class Mailer{

var $sender;

var $recipient;

var $subject;

var $headers=array();

var $mimeTypes=array();

var $html=array();

var $attachments=array();

function Mailer($sender,$recipient,$subject,$message){

// validate incoming parameters

if(!preg_match("/^.+@.+$/",$sender)){

trigger_error(‘Invalid value for email sender.’);

}

if(!preg_match("/^.+@.+$/",$recipient)){

trigger_error(‘Invalid value for email recipient.’);

}

if(!$subject||strlen($subject)>255){

trigger_error(‘Invalid length for email subject.’);

}

if(!$message){

trigger_error(‘Invalid value for email message.’);

}

$this->sender=$sender;

$this->recipient=$recipient;

$this->subject=$subject;

$this->message=$message;

// define some default MIME headers

$this->headers['MIME-Version']=’1.0′;

$this->headers['Content-Type']=’multipart/mixed;boundary="MIME_BOUNDRY"';

$this->headers['From']='<‘.$this->sender.’>';

$this->headers['Return-Path']='<‘.$this->sender.’>';

$this->headers['Reply-To']=$this->sender;

$this->headers['X-Mailer']=’PHP 4/5′;

$this->headers['X-Sender']=$this->sender;

$this->headers['X-Priority']=’3′;

// define some default MIME types

$this->mimeTypes['image/jpeg']=’jpg';

$this->mimeTypes['image/jpg']=’jpg';

$this->mimeTypes['image/gif']=’gif';

$this->mimeTypes['text/plain']=’txt';

$this->mimeTypes['text/html']=’htm';

$this->mimeTypes['text/xml']=’xml';

$this->mimeTypes['application/pdf']=’pdf';

}

// add new MIME header

function addHeader($name,$value){

$this->headers[$name]=$value;

}

// add HTML to message

function addHTML($html){

if(!$html){

trigger_error(‘Invalid HTML.’,E_USER_ERROR);

}

$this->html[]=$html;

}

// add new attachment

function addAttachment($attachment){

if(!file_exists($attachment)){

trigger_error(‘Invalid attachment.’,E_USER_ERROR);

}

$this->attachments[]=$attachment;

}

// get MIME Type of attachment

function getMimeType($attachment){

$attachment=explode(‘.’,basename($attachment));

if(!$mimeType=array_search(strtolower($attachment[count($attachment)-1]),$this->mimeTypes)){

trigger_error(‘MIME Type not found.’,E_USER_ERROR);

}

return $mimeType;

}

// create message MIME headers

function buildHeaders(){

foreach($this->headers as $name=>$value){

$headers[]=$name.': ‘.$value;

}

return implode("n",$headers)."nThis is a multi-part message in MIME format.n";

}

// create text part of the message

function buildTextPart(){

return "–MIME_BOUNDRYnContent-Type: text/plain; charset=iso-8859-1nContent-Transfer-Encoding: quoted-printablennn".$this->message."nn";

}

// create HTML part of the message

function buildHTMLPart(){

if(count($this->html)>0){

$htmlPart=”;

foreach($this->html as $html){

$htmlPart.="–MIME_BOUNDRYnContent-Type: text/html; charset=iso-8859-1nContent-Transfer-Encoding: 8bitnnn".$html."nn";

}

return $htmlPart;

}

}

// create attachments part of the message

function buildAttachmentPart(){

if(count($this->attachments)>0){

$attachmentPart=”;

foreach($this->attachments as $attachment){

$fileStr=file_get_contents($attachment);

$fileStr=chunk_split(base64_encode($fileStr));

$attachmentPart.="–MIME_BOUNDRYnContent-Type: ".$this->getMimeType($attachment)."; name="".basename($attachment).""nContent-disposition: attachmentnContent-Transfer-Encoding: base64nn".$fileStr."nn";

}

return $attachmentPart;

}

}

// send email

function send(){

$to=$this->recipient;

$subject=$this->subject;

$headers=$this->buildHeaders();

$message=$this->buildTextPart().$this->buildHTMLPart().$this->buildAttachmentPart()."–MIME_BOUNDRY–n";

if(!mail($to,$subject,$message,$headers)){

trigger_error(‘Error sendind email.’,E_USER_ERROR);

}

}

}


Now the MIME mailer class defines and implements two additional methods, called “addHTML()” and “buildHTMLPart()” respectively. The first one allows you to aggregate HTML code to an existing email message, and the last one is tasked with assembling the corresponding HTML parts that will be added later to the whole multipart message.

This assembling process is performed by the “send()” method of the class, so you shouldn’t have major trouble understanding how it works.

So far, so good. At this stage you hopefully learned how to provide the previous “Mailer” class with the ability to send email messages in HTML format. This ability has to be added to the existing capacities, meaning the class is now much more powerful.

However, there’s one thing left undone in this specific case. Yes, you guessed right! Naturally, you must want to see how the class works. Therefore, in the last section of this article, I’m going to build a final hands-on example, aimed at demonstrating the improved functionality of the MIME mailer class.

All you have to do is click on the link that appears below and keep reading.

{mospagebreak title=Sending email in HTML format using the MIME mailer class}

Below I coded a basic script, which comes in handy for illustrating the functionality of the “Mailer” class, especially when it comes to sending email messages in HTML.

Here’s the corresponding code sample: 
 

// create a new instance of the ‘Mailer’ class

$mailer=&new Mailer(‘alejandro@mydomain.com,’mybuddy@yourdomain.com’,’Testing mailer class’,’Hello buddy. I am sending to you a couple of fun images.’);

$mailer->addHTML(‘<p>This is a simple paragraph formatted in HTML</p>’);

$mailer->addHTML(‘<p>This is another paragraph formatted in HTML</p>’);

// add some attachments

$mailer->addAttachment(‘file1.gif’);

$mailer->addAttachment(‘file2.gif’);

// send MIME email

$mailer->send();


As shown in the above example, I used the MIME mailer class to send a simple text message with a couple of attached files. However, I’m also sending HTML code embedded into the message in question.

As usual, I suggest you to test the previous “Mailer” class by incorporating your own improvements. It’s going to be an educational experience, trust me!

Final thoughts

That’s all for now. In this fourth installment of the series, I taught you how to build a modular MIME mailer class that’s capable of sending email in both plain text and HTML formats. In addition, the class supports working with file attachments, so I guess it should be quite helpful when it comes to learning the basics of sending MIME email with PHP.

In the last chapter, I’ll be porting the complete source code of the class to PHP 5. This will take advantage of its improved object model. Don’t miss the upcoming article!

[gp-comments width="770" linklove="off" ]

chat