Email Management Details

In this second part of a two-part article, you’ll learn how to manage email headers when creating a PHP email program, attach a file to a message, and more. This article is excerpted from chapter eight of the Zend PHP Certification Study Guide, written by Zend Technlogies (Sams; ISBN: 0672327090).

Managing Email Headers

Email headers are lines of text that go at the start of an email message. Headers hold information used by MTAs and MUAs. If you pass a list of additional headers into the mail() function, it will automatically add these headers to your email message. Each header in the list must be separated by rn.

The Cc: and Bcc: Headers

The Cc: and Bcc: headers allow you to send a copy of an email message to other people. All recipients will be able to see the list of addresses in the To: and Cc: lines of the email, but will not be able to see the list of addresses in the Bcc: line.

The Cc: and Bcc: headers are optional. If you provide either of them (or both of them), they must follow the same rules about email addresses as the to parameter to mail().

The From: Header

The From: header tells the MTA who is sending the email message.

If you do not provide a From: header, PHP might or might not add one for you:

  • If you are sending email via the sendmail wrapper, PHP will leave it to the MTA to add a default From: header.

  • If you are sending email on Windows without using the sendmail wrapper, PHP will use the sendmail_from setting in php.ini to set a default From: header.

Setting the Subject

The second parameter to mail() is a string containing the "subject" of the email. Whatever you put in this string will appear in the Subject: header of the email.

Formatting an Email Message

The third parameter to mail() is the email message itself.

Plain-Text Emails

Plain-text emails are normal 7-bit US-ASCII strings with each line terminated by rn. The following code will send a plain-text email, as long as PHP is configured to correctly send email and the MTA is working, too.


Note - Some MTAs on UNIX will accept messages that just use n as the end-of-line sequence. This is nonstandard behavior, and you should expect to have problems eventually.


<?php

// who is the email going to?
// change this to be *your* email address ;-)

$to = "stuart";

// what is the message?

$message = "This is my first email message, sent
from PHP.rn" . "This is a second line of textrn"; // who else do we want to send the message to? $more_headers = "Cc: stuartrn"; // send the email $result = mail ( $to, "My first e-mail sent from PHP", $message, $more_headers ); ?>

By default, all emails sent via mail() are plain-text emails. If you want to send HTML emails, you need to create a simple MIME-encoded email.

Basic HTML Emails

The Multipurpose Internet Mail Extensions (MIME) define a standardized way of sending emails with attachments, and/or with content that isn’t 7-bit US-ASCII.

You can find a reference to the MIME standard in the "Further Reading" section at the end of this chapter.

To send a basic HTML email, all you need to do is this:

  • Add these additional headers:

  • MIME-Version: 1.0 Content-Type: text/html; charset="iso-8859-1" Content-Transfer-Encoding: 7bit

  • Pass your HTML content in a string as the third parameter to mail().

Any images, links, stylesheets—anything at all that the web browser has to download—must be full URLs. Note that, for security and privacy reasons, most email clients will not automatically download anything that’s referenced in an HTML email.

If you want to add images to your email, you need to use attachments.

{mospagebreak title=Attaching a File to a Message}

To attach a file to an email message, you have to create a multipart MIME message.

  • Pass these headers as the fourth parameter to mail():

    MIME-Version: 1.0 Content-Type: multipart/mixed;
    boundary="php-12345"

    Note the boundary on the end of the Content-Type. The boundary is an arbitrary US-ASCII string that tells MUAs when the end of a MIME block has been reached. You can set it to be whatever you want, provided you set it to something that isn’t going to appear in your email message.

  • The first part of your message string should be a plain text message like this:

    If you are reading this, it means that your email
    client does not support MIME. Please upgrade your email
    client to one that supports MIME. —php-12345

    Note the boundary marker after the message. This tells MIME that you’ve reached the end of this particular part of the email message. You can now add more parts to your email message.

  • The second part of your "message" string should be the message itself. You need to add Content-Type and Content-Transfer-Encoding headers to the message, followed by the message itself.

    Content-Type: text/plain; charset="iso-8859-1"
    Content-Transfer-Encoding: 7bit
    Hello, this is my plain text message. If you can see
    this, then hopefully my MIME email is working fine.
    —php-12345

    Note the boundary marker after the message. You have to put the boundary marker at the end of each part of the message.

  • Next come the attachments. Each attachment gets added to the "message" string as well. You need to add Content-Type and Content-Transfer-Encoding headers, and then the attachment.

    If the attachment isn’t plain text, you should encode it using base64 encoding:

    Content-Type: image/jpeg
    Content-Transfer-Encoding: base64
    <message goes here>
    —php-12345
<?php

// who is the email going to?
// change this to be *your* email address ;-)

$to = "stuart";

// what is the message?

$message = "This is my third email sent from "
         . "<a
href="http://www.php.net">PHP</a>.rn" . "This email has an attached imagern"; // don't forget our blank line $blank_line = "rn"; // define our boundary $boundary_text = "php-12345"; $boundary = "—" . $boundary_text . "rn"; $last_boundary = "—" . $boundary_text . "—rn"; // add the MIME headers $more_headers = "MIME-Version: 1.0rn" . "Content-Type: multipart/mixed;
boundary="" . $boundary_text . ""rn"; // create the first part of the message $mime_message = "If you are reading this, it means
that your e-mail clientrn" . "does not support MIME. Please
upgrade your e-mail clientrn" . "to one that does support MIME.rn" . $boundary; // add the second part of the message $mime_message .= "Content-Type: text/html;
charset="iso-8859-1"rn" . "Content-Transfer-Encoding:
7bitrn" . $blank_line . $message . $boundary; // now add the attachment $mime_message .= "Content-Type: image/gif;
name="php.gif"rn" . "Content-Transfer-Encoding:
base64rn" . "Content-disposition: attachment;
file="php.gif"rn" . $blank_line . chunk_split(base64_encode
(file_get_contents("php.gif"))) . "rn" . $last_boundary; // send the email $result = mail ( $to, "My first HTML e-mail with an attachment", $mime_message, $more_headers ); ?>

You can add as many attachments as you want, but remember—they can make the email quite large to download, and many users are still using dial-up rather than broadband!

The last boundary marker in the email message must end with . For example, if our boundary marker is

—php-12345

the last marker in the email message would be

—php-12345—

instead.

{mospagebreak title=Attached Images for HTML Emails}

HTML emails will attempt to download their images and stylesheets from your web server. Because of security and privacy reasons, many MUAs will refuse to attempt these downloads, ruining the look of your HTML email message.

You can add your images as attachments to your email, and then point your HTML at the attached images:

  • Change the first Content-Type of your email to be multipart/related. Don’t forget to include the boundary definition.

  • When you add an image as an attachment, include this additional header:

  • Content-Location: URL

  • URL is the URL that you use inside the <img> tag to include your image.

<?php

// who is the email going to?
// change this to be *your* email address ;-)

$to = "stuart";

// what is the URL of the image?

$image = http://static.php.net/http://www.php.net/
images/php.gif; // what is the message? $message = "This is my fourth email sent from " . "<a
href="http://www.php.net">PHP</a>.rn" . "This email has an image " . "<img src="" . $image . ""> here.rn"; // don't forget our blank line $blank_line = "rn"; // define our boundary $boundary_text = "php-12345"; $boundary = "—" . $boundary_text . "rn"; $last_boundary = " . $boundary_text . "—rn"; // add the MIME headers $more_headers = "MIME-Version: 1.0rn" . "Content-Type: multipart/related;
boundary="" . $boundary_text . ""; type="text/html"rn"; // create the first part of the message $mime_message = "If you are reading this, it means
that your e-mail clientrn" . "does not support MIME. Please
upgrade your e-mail clientrn" . "to one that does support MIME.rn" . $boundary; // add the second part of the message $mime_message .= "Content-Type: text/html;
charset="iso-8859-1"rn" . "Content-Transfer-Encoding:
7bitrn" . $blank_line . $message . $boundary; // now add the attachment $mime_message .= "Content-Type: image/gif;
name="php.gif"rn" . "Content-Transfer-Encoding:
base64rn" . "Content-Location: " . $image . "rn" . $blank_line . chunk_split(base64_encode
(file_get_contents("php.gif"))) . "rn" . $last_boundary; // send the email $result = mail ( $to, "My first HTML e-mail with an embedded
image", $mime_message, $more_headers ); ?>

Using Extra Command-Line Parameters

The fifth argument to mail() is a list of parameters to use when executing the sendmail wrapper.

These parameters have no effect at all if you are using PHP on Windows without a sendmail wrapper.

{mospagebreak title=A Word About Email Delivery}

mail() returns TRUE if the email is accepted for delivery. This does not guarantee that the email will be delivered.

Internet email is an unguaranteed delivery system.

Email messages can be lost at any point between your MTA and your user’s MUA. This is often caused by a catastrophic disk failure on an MTA, combined with inadequate backups. When email messages are lost, there is no automatic mechanism to trigger re-sending the email message. Lost email messages are never delivered to the intended recipient.

A more common problem is email messages that get rejected by the user’s MTA. Causes include

  • Inbox over quota

  • Email too large to accept

  • Disabled user account

  • Misspelled email address name

  • Virus scanner detected a virus in an attachment

When an MTA rejects an email message, it normally sends back the email message with a description of why the email was rejected. These ‘bounced’ email messages are never delivered to the intended recipient.

If the email message is successfully delivered to the intended recipient, this can still cause problems. The user might use a filter that bounces email from senders not in a whitelist. The user might have set up a vacation auto-responder, which automatically sends back a message saying that the user is currently out of the office.

It’s therefore essential that your PHP application can cope with these situations:

  • Every single email you send should have a valid Reply-To: header, to allow receipt of bounced email messages. You should set up a mailbox just for bounces to emails sent from your PHP scripts. It’s a good idea to have someone go through the mailbox once a day, just in case there is anything you can do about the bounced email.

  • Normally, there should be a way for the user of your PHP script to make your script send the email again.

  • Any order confirmations, receipts, and invoices that you send via email should also be available through some other means—either via your website, or via snail mail. Apart from being good customer service, many of these documents are legally important.

Further Reading

The standards for email handling are defined by the RFC series of documents, which you can find at http://www.rfc-editor.org/.

  • RFC’s 821 and 822 are the current standards on SMTP and plain-text emails, respectively.

  • RFC’s 2045, 2046, 2047, 2048, and 2049 define the MIME standard.

  • RFC 1896 discusses the "text/enriched" MIME content type. This is very similar—but not the same as—HTML email.

  • RFC 2557 defines the use of Content-IDs to use attached images in HTML emails.

  • RFC 2554 defines the use of SASL for authenticating connections to an MTA.

  • Internet Mail Consortium home page http://www.imc.org/. In particular, http://www.imc.org/terms.html is an excellent reference.

{mospagebreak title=Exam Prep Questions}

  1. Your company sells a shopping cart written in PHP. Matching common industry practice, the shopping cart sends a confirmational email to the user after he has checked out.

    Your team has just ported the shopping cart from PHP on Gentoo Linux to PHP running on Windows Server 2003. They’ve correctly set the SMTP, smtp_port, and sendmail_from settings in php.ini, but this error appears when the shopping cart tries to send the confirmation email:

    Could not execute mail delivery program
    'sendmail'

    This is your team’s first project using Windows Server, and everyone’s a bit confused as to why this error is happening. The php.ini settings work fine on Linux, so what could be the problem?

    Choose from one of the following: 

    A.  The smtpserver service hasn’t been started.

    B.  sendmail_path in php.ini needs to be commented out.

    C.  Microsoft Exchange needs configuring to accept email from PHP.

    D.  PHP cannot send email when running on Windows.

    The correct answer is B.

  2. Flush with the success of the shopping cart on Windows Server 2003, your company has decided that it would be a good idea to add Solaris to the list of supported operating systems. Because the shopping cart is already proven to work on Linux, it should be no trouble at all to get the cart working on Solaris.

    Your team goes out and buys a new Sun server. As Solaris doesn’t come with PHP, you have to compile PHP by hand. At the same time, your network administrator decides to un-install the Solaris version of sendmail and replace it with the company’s standard MTA—postfix—instead. He forgets to tell you that he’s done this.

    When the time comes to test your shopping cart on Solaris, there’s a problem. When the shopping cart tries to send the confirmation email, you get this error message:

    Call to undefined function: mail()

    What can you do to fix this problem?

    A.  Put an @ symbol in front of your call to mail() so that PHP does not output the error message.

    B.  Put sendmail back on the machine. Postfix doesn’t provide a sendmail wrapper anyway.

    C.  Use mb_send_mail() instead.

    D.  Recompile PHP—after asking your network administrator to leave the MTA alone until the recompilation of PHP has completed

    The correct answer is D.

  3. All the new customers you’re attracting on Solaris are very pleased with your shopping cart. Your product is earning them a lot of new customers also.

    However, like all customers, they want new features. Specifically, they want you to create and attach a simple comma-separated file that users can import into products such as Microsoft Money. This will make it easier for customers to manage their finances. Besides, it’s a cool feature that none of your competitors have, so the marketing department has told your boss to get it done.

    At the moment, the shopping cart sends out RFC-822–compliant plain-text emails. What do you need to change to make it send the attachment as well?

    Choose from one of the following:

    A.  Replace your plain-text emails with MIME-encoded emails.

    B.  Refuse to do it. RFC-822 doesn’t allow attachments, and your company should not be shipping products that go against Internet standards.

    C.  Put the CSV file on a web server, and put a link to it in the email.

    D.  Ditch PHP’s built-in mail() function, and use the system() command to call sendmail directly.

    The correct answer is A.

  4. A rival has just launched a new version of his shopping cart. Unlike yours—which only sends plain-text emails—his shopping cart sends out confirmation emails that look more like a web page. These emails look so much nicer, and he’s starting to eat into your sales as a result. It’s a good thing his cart only runs on Windows; otherwise, you’d have no customers left!

    Something must be done, and marketing has decided that if you can’t beat them, join them. Your long-suffering boss has been told to make your shopping cart send out nice-looking emails too. In the best tradition of pointy-haired bosses, he’s dumped the whole problem in your lap, and is waiting for you to tell him how this can be done.

    What could you do to make this work? Choose one or more of the following:

    A.  Change your emails to send text/html MIME-encoded emails.

    B.  It’s time to ditch mail() again and call sendmail directly.

    C.  Change your emails to send text/enriched MIME-encoded emails.

    D.  Tell your boss that this only works on Windows because PHP on Windows handles emails very differently.

    The correct answers are A and C.

  5. During testing of your new, much nicer-looking confirmation emails, you notice that there’s a problem. The email uses quite a few images—including the all-important company logo. All of these images are stored on your web server, and the email uses standard "<img src=...>" tags to include them. The images look great in your email client—but appear as missing images when you send the email to your boss to show him the results of your hard work.

    Your boss isn’t pleased, and neither is the marketing department, who make it very clear that you can’t ship the code until the company logo shows up.

    The good news is that it isn’t just your email. The confirmation emails sent by your rival also have this problem. If you can figure out how to make it work, not only will you be playing catch-up to your rival, but you’ll also be back in the lead. This mollifies your boss, but gets you nowhere nearer to solving the problem.

    What could you change to make this work? Choose one or more of the following:

    A.  sendmail is too old. Replace it with a modern MTA instead.

    B.  Add all the images to the email as attachments with Content-Locations, and make your email use the attachments rather than the images on the website.

    C.  Add a piece of inline JavaScript in your email that temporarily changes the security settings of the email client. This will enable the images to be downloaded.

    D.  File a bug with the author of the email client that your boss uses. Something must be wrong with the way it handles RFC-1896–compliant email messages.

    The correct answer is B—and only B.

  6. With all the problems overcome, your company’s shopping cart now sends email messages that not only look great, but also work where your rival’s do not. Marketing is pleased, and has awarded your boss a bonus in return. Isn’t that typical?

    However, the support team leader isn’t happy. Since the release of your latest shopping cart marvel, there has been a large increase of bug reports about your new style email messages. It seems that many users won’t accept HTML emails at all, and would like to be able to send plain-text emails instead.

    Seeing as he just got a nice bonus for adding HTML emails, your boss isn’t too sympathetic to the idea of getting rid of them again. In desperation, the support team leader turns to you, and asks you to convince your boss.

    Draft out a short email message to your boss, explaining why plain-text emails are a good idea. As all consultants need to be politicians at heart, it might help to think about how you can keep both your boss and the support team leader happy.

[gp-comments width="770" linklove="off" ]
antalya escort bayan antalya escort bayan