Introduction
Mail Transport Abstraction
Mime Handling
Other Goodies
Conclusion
About the Author
Revision Date

Introduction

In this overview I'm going to introduce you to some of the delights hidden away in PEAR's Mail category.

There are many useful classes in PEAR that can help save you time and money in your everyday use of PHP. Not least among these are the PEAR Mail classes. These classes are focused into two key areas: sending and MIME handling. First I'm going to elaborate on the sending classes, and then on the more complicated area of MIME handling. Following that, we will look at a couple of other useful bits of pre-written code.

Mail Transport Abstraction

At some point, most web applications will need to send mail. Thankfully, in PHP this is made easy by the built-in mail() function. This function enables you to send an email without the complexities of accessing a SMTP server, or the non-portable practice of using platform-specific commands. However, sometimes there is a need for more abstraction than mail() provides.

This is where the mail sending classes come in. They enable you to abstract mail transport to a level where you're not dependent on PHP functions. You can write new transport code and use it with only minimal changes to your application. This also helps you to respond quickly to changing demands on your code, supporting new formats, protocols or requirements with relative ease.

So how does it work? The code is split into a single parent class, Mail, and child driver classes (Mail_mail, Mail_smtp, Mail_sendmail). The parent class provides, most notably, the factory method, which is used to create an object based on the desired driver class. This object is then returned to the calling script, and can be used to send mail using the send() method common to all the driver classes. It is this that provides the abstraction. Although each driver class needs slightly different configuration parameters, these are supplied to the factory method at object creation time as an associative array. So, while not 100% abstract, these configuration parameters can be neatly tucked away in a config or auto prepend file.

Mime Handling

One of the hardest things when it comes to mail is handling MIME types, and possibly the easiest way of coding MIME handlers is to let someone else do it. Fortunately, PEAR is strong when it comes to this. There are two classes that deal with creating MIME mail, and one that deals with decoding it.

The Mail_mime class, unsurprisingly, creates MIME email. It benefits from an easy-to-use API that makes it simple to understand, and even simpler to incorporate into your scripts. After creating a Mail_mime object you can use the methods setTXTBody(), setHTMLBody(), addHTMLImage and addAttachment to define your mail, followed by the get() and headers() methods to build your mail and return the results. The added bonus is that these last two methods return their data in formats that can be passed directly to the mail abstraction send() methods. Now isn't that wonderful?

Additionally, various parameters such as encoding or character sets can be controlled by supplying arguments to some of the methods. Mail_Mime is very useful if you want a quick and simple way to send complex mail, but if your needs are a little more advanced then you should look at using Mail_mimePart - which, incidentally, is used during the build process of the Mail_mime class.

Mail_mimePart is a small class designed so that each instance represents a single MIME part, hence the name. When creating a Mail_mimePart object, you supply all the details of the MIME part to the constructor, including the content type, the encoding, the actual data, etc. You then have two options: either the encode() method, or the addSubPart() method. The addSubPart() method does exactly as its name suggests: it adds another MIME part, as a child of the object being used. Importantly, it returns a reference to the object it adds inside the parent. Using this reference, you can add further subparts, allowing some pretty complicated structures to be built up.

The encode() method is where the magic happens. This method takes the parameters you've supplied along with the data (if any) and creates the appropriate MIME encoding. If there are subparts, their encode() methods are called and the results incorporated. This whole business is a bit complicated, but the documentation is very helpful should you require aid, as it has some excellent example code.

The Mail_mimeDecode class is where it's at when it comes to decoding MIME structures. Taking an email as input, along with various configuration parameters, it will return the structure in the form of a tree made up of arrays and objects. While this is not very useful in itself, it's a small task to create a function that will traverse this structure, and pick out the bits you're interested in. For example you could write a function to pick out all the attachments and store them to disk, while displaying the textual content on screen. The class will handle pretty much anything you can throw at it, though an unknown content type may throw it off-track. In these rare cases, however, it's simple to add support for the new content type. It also has functionality to uudecode attachments given a block of text, however this is not part of the main decoding routine and has to be invoked separately.

An interesting related feature that's part of this class is XML conversion. After decoding an email, you can pass the resulting structure to the getXML() method and it will convert it to XML, retaining the tree structure. This could be useful if you need to pass the structural data to other applications, or to other programming languages. A DTD and XSL stylesheet are available as part of PEAR's Mail_Mime package.

Other Goodies

Creating and sending mail is only half the story. If you're lucky enough to have a friend or two, you're going to receive email from time to time. So what if you want your PHP scripts to experience this joyous occasion? You have a few options, of which one of the easiest is to check a POP3 mailbox. POP3 is a basic plain text protocol with few commands, meaning it's easy to understand and easy to implement. The Net_POP3 PEAR class has two methods of usage, the primary being a set of abstract methods to list, retrieve and manipulate the mailbox. Methods such as getListing(), getBody() and getParsedHeaders (amongst others) give you an easy to use API to work with. These methods use internal (pseudo private) methods that issue the actual commands to the POP3 server. The internal methods are the second way you can use the class. Despite being marked as private methods, there is no mechanism in PHP 4 to prevent you from accessing them, so you can use methods such as _cmdUser(), _cmdPass(), and _cmdTop() to do your bidding instead if you wish.

Email addresses can be a royal pain to work with. Recognising what's good and what's trash can be both easy and hard at the same time. Take the easy road with a simple regular expression and while you might match the regular internet addresses, you'd miss out on the more complicated ones. For example, take the following address: Richard Heyes <richard@phpguru.org>. Although neither complex nor rare, this email address would be marked as invalid by most simple regular expressions, despite being perfectly valid (and no, double quotes around the name are not required!).

If you're interested in having email addresses validated as close as possible to the RFC822 (now 2822) specification then you may wish to look into the Mail_RFC822 class in PEAR::Mail. However, although it does cater for pretty much any valid email address, it can be a significant overhead, weighing in at a hefty ~700 lines of code.

Conclusion

The PEAR mail utilities can save you time in common tasks, and aid you in building better applications and websites. I highly recommend that you investigate the utilities described here, and indeed the rest of PEAR (as this is just the tip of a rather substantial iceberg).

About the Author

Richard Heyes has been developing websites and web applications, primarily with PHP, for the last five years, and is currently freelancing. He is the author of a popular webmail application, bizarrely named Frederick (http://www.phpguru.org/frederick.html) which, unsurprisingly, utilises many of the tools described here.

Revision Date

This article was last revised on 18th December 2004.