Summary
In this article we describe how to send MIME email with PHP's Pear::Mail and Pear::Mail_mime packages. To ensure that your MIME email can be displayed properly on all the major Web email providers, including Yahoo! Mail, Google Mail, Windows Live Hotmail, you need to set properly the encodings for the text and HTML parts of your email as well as the encodings for mail transfer. We call out a few issues that you should take note of. For example, for Windows Live Hotmail, we suggest you use base64 mail transfer encoding for your HTML file to work around the display problem that Microsoft SafeHTML generator may cause. In the end we provide sample PHP files which you can try out and adapt to your need.
Introduction
When developing your web site, you often need to send out MIME email to your users. There are many benefits of using MIME email. One is that you can specify character sets other than US-ASCII. For example, with UTF-8 you can encode almost all the characters from most of the world's languages so you can easily use multiple languages in one email to target users who speak different languages. The other is that you can send the same content with different formats, e.g., one in plain text and the other in HTML. So you don't penalize your users who prefer working with a text terminal while at the same time you can providing graphics-rich content to your users who use Web mail or any other GUI-based email clients.
Implementation with PHP
If you use PHP, you can use the Pear::Mail and Pear::Mail_mime packages from PEAR, the PHP Extension and Application Repository. Since these packages are written in pure PHP, you can check their source code in case the document is not clear or you want to know more details about the implementation.
When you use these packages, please note that there are two types of encodings involved. One type is the encoding of the original file, be it a plain text file or an HTML file. In the HTML file, you need to specify the character set even though it is optional. The other type is the encoding used when transmitting the email to the server at the other end. The commonly used encodings for mail transfer are quoted-printable and base64 because they are 8-bit safe and clean.
Generally speaking, if your message contains mostly English letters, quoted-printable is better because the raw content of your message is still intelligible even without decoding. In contrast, the raw content of a base64-encoded message is unintelligible without decoding it first. If your message contains mostly non-English letters, then base64 encoding is more space efficient.
Because of these types of encodings, you need to make conscious choices about them when programming with the Pear::Mail and Pear::Mail_mime packages. Default values from these packages may be right in some cases but not appropriate in other cases. Below is an example on how to set the encodings for various parts of your message:
$mime = new Mail_mime();
$options['head_encoding'] = 'quoted-printable';
$options['text_encoding'] = 'quoted-printable';
$options['html_encoding'] = 'base64';
$options['html_charset'] = 'utf-8';
$options['text_charset'] = 'utf-8';
$body = $mime->get($options);
Please note that in fact different encodings can be specified for the header, text and HTML parts of the message. The text and HTML parts can also have different character sets. All these come from the flexibility of MIME email.
With the Pear::Mail package, you can specify which mailer you want to use. If
it is a Linux server and you don't need authentication, for example when sending
out newsletters, you can choose sendmail. The relevant code
looks like this:
$mailer = Mail::factory('sendmail');
$mailer->send($recipients, $headers, $body);
When you call the mailer's send method, it is very important that
you specify all the recipients' addresses including those on the CC and BCC
lists, otherwise they won't get the email even if you list them in the headers.
Just remember that because you can put almost whatever you want in the headers,
you can never decide who are the actual recipients from these headers.
When implementing mail in PHP, as a good practice you should keep the code that handles mailing separate from the code that generates the dynamic HTML or plain text file that you need to send out. Such separation allows you to modify them independently and it is not difficult to do.
For example, if you want to use the output of executing the
lanting.php script as the HTML content of your email, then you can
use PHP's ob_* functions to buffer and save the output to a
temporary variable and then use it to set the HTML body of your email:
ob_start();
$html_file = "lanting.php";
include($html_file);
$html_output = ob_get_contents();
ob_end_clean();
$ret = $mime->setHTMLBody($html_output, false);
Common issues and resolutions
Sometimes you may find that when MIME email on Windows Live Hotmail is displayed, some characters are lost or replaced by weird question marks or equal signs.
The reason may be that you use the quoted-printable mail transfer encoding and the HTML generator (called Microsoft SafeHTML) used by Windows Live Hotmail fails to concatenate the lines properly due to different line endings under Windows and Unix systems. Under Windows, a text line is terminated by "\r\n" while under Unix it is just "\n." (For completeness, line ending under Mac OS is just "\r.")
Rather than messing with line breaks by yourself which in theory should have been handled properly by all the servers involved, you can use base64 encoding to transfer your email so it can be displayed properly. Besides, base64 encoding is more space efficient. As far as we know Yahoo! Mail and Google Mail don't have this problem, you can be almost 100 percent sure that it is not all your fault. :-)
Source files
You can download the sample PHP script that sends out MIME email that can be be displayed properly by all the major Web mail providers and its supporting plain-text file and HTML file for the famous Chinese calligraphy masterpiece "Preface to the Poems Composed at the Orchid Pavilion."