Handling mail and mime in PHP using the Zend Framework

Open Source PHP Web development Zend Framework July 18th, 2008 by Eran Galperin

Handling mail is a very common requirement in web applications. Even the most basic sites usually have a contact form that sends a mail through the server instead of putting a contact mail address for spam-spiders to find. Using PHP's built in function (aptly named mail() ) is relatively straightforward - until you need slightly more advanced features, such as adding and encoding email headers or sending multiple mails efficiently.

Fortunately, the Zend Framework comes with a very capable mail component called Zend_Mail. Zend_Mail abstracts some of the more tedious aspects of mail handling with PHP, including:

  1. Adding and encoding email headers
  2. Protection against header injection
  3. Multiple mail transports (SMTP is useful for sending multiple mails)
  4. Creating and handling mime-compliant multipart messages
  5. Composing HTML emails
  6. Reading mail boxes

Sending mails

Using Zend_Mail is extremely straightforward: (Taken from the ZF documentation)

  1. require_once 'Zend/Mail.php';
  2. $mail = new Zend_Mail();
  3. $mail->setBodyText('This is the text of the mail.'); //Alternatively using setBodyHtml for HTML messages
  4. $mail->setFrom('somebody@example.com', 'Some Sender'); //Adds a 'from' header
  5. $mail->addTo('somebody_else@example.com', 'Some Recipient');
  6. $mail->setSubject('TestSubject');
  7. $mail->send();

Simple.

For sending multiple mails it is better to use the SMTP protocol for performance reasons. Doing this manually with PHP is quite elaborate however, but with Zend_Mail it is almost as simple as before:

  1. require_once 'Zend/Mail.php';
  2.  
  3. // Create transport
  4. require_once 'Zend/Mail/Transport/Smtp.php';
  5. $transport = new Zend_Mail_Transport_Smtp('localhost');
  6.  
  7. // Sending out multiple mails at once
  8. for ($i = 0; $i > 5; $i++) {
  9. $mail = new Zend_Mail();
  10. $mail->addTo('studio@peptolab.com', 'Test');
  11. $mail->setFrom('studio@peptolab.com', 'Test');
  12. $mail->setSubject('Demonstration - Sending Multiple Mails per SMTP Connection');
  13. $mail->setBodyText('...Your message here...');
  14. $mail->send($transport); //Using the SMTP transport for sending the mail
  15. }

* SMTP connections can be secured with SSL or TLS for sending sensitive mails.

This procedure reuses the SMTP connection for the lifetime of the entire process which is much better than sending out mails using the mail() function.

Reading mail boxes

Reading mail boxes is similarly simple. Zend_Mail supports POP3 and IMAP for remote connections, and Mbox and Maildir for local connections (mail boxes residing on the same server). Sample usage:

  1. $mail = new Zend_Mail_Storage_Pop3( //Configuring with host and credentials
  2. array('host' => 'example.com',
  3. 'user' => 'test',
  4. 'password' => 'test'
  5. )
  6. );
  7.  
  8. echo $mail->countMessages() . " messages found\n"; //Outputting message count in mail box
  9. foreach ($mail as $message) { //Outputting message subjects
  10. echo "Mail from " . $message->from . ": " . $message->subject . "\n";
  11. }

Using the different storage options is very similar. Messages returned are instances of the Zend_Mail_Message class, which provides an API for manipulating mail messages.

Advanced Usage

Working with multipart MIME messages is very tedious. The MIME specifications are rather complex and MIME messages aren't very readable to humans, and therefor we would like to be able to use Zend_Mail_Message API to reduce the pains of dealing with MIME messages. There are several general cases when working with MIME messages:

  1. Working with messages which are stored as strings in a database
  2. Working with messages which are read from files
  3. Working with incoming messages directly (from an input stream)

Zend_Mail_Messsage can receive either a raw message string in its constructor, a file name or a file handle. Examples of instancing a Zend_Mail_Message object with all three:

  1. //From a raw string
  2. $message = new Zend_Mail_Message(array('raw' => $rawMessage));
  3.  
  4. //From a file name
  5. $message = new Zend_Mail_Message(array('file' => '/path/to/mail/message'));
  6.  
  7. //From a file handle
  8. $handle = fopen('/path/to/mail/message');
  9. $message = new Zend_Mail_Message(array('file' => $handle));

The last one might seem a bit redundant. However it opens up creative ways to intercept mail directly using the input wrapper:

  1. $handle = fopen("php://stdin", "r");
  2. $message = new Zend_Mail_Message(array('file' => $handle));

The tricky part is directing the mail message stream into the script. You can read more about that in this nice tutorial from evolt.

Some minor bugs and fixes

Nothing is perfect however. Current version of Zend_Mail (shipped with the Zend_Framework ver. 1.5.2) has a buggy implementation of the headers encoding. This will become noticeable when working with UTF encoded mails. Fortunately there is a quick fix for that posted in the ZF issue tracker (and hopefully will be tested and integrated in the next release).

Tags:

Enter your email address to receive notification about new posts.

If you liked this article you should follow me on Twitter and/or share below:
  • http://www.held.org.il Oren

    Hi,

    Nice post.
    Why is SMTP quicker? What happens in the non-smtp way? Executing the sendmail binary like the php simple mail() command?

  • http://www.held.org.il Oren

    Hi,

    Nice post.
    Why is SMTP quicker? What happens in the non-smtp way? Executing the sendmail binary like the php simple mail() command?

  • http://www.techfounder.net Eran Galperin

    The problem with the mail() function is that it opens a separate socket connection for each mail. The PHP manual recommends using wrappers that send mail via SMTP – http://www.php.net/manual/en/function.mail.php (scroll down to the notes).

  • http://www.techfounder.net Eran Galperin

    The problem with the mail() function is that it opens a separate socket connection for each mail. The PHP manual recommends using wrappers that send mail via SMTP – http://www.php.net/manual/en/function.mail.php (scroll down to the notes).

  • http://www.chrisabernethy.com Chris Abernethy

    Nice introduction to Zend_Mail! I’m currently working on porting a rather large web application to use Zend Framework, and I will definitely be looking at replacing our use of the mail() function with Zend_Mail.

  • http://www.chrisabernethy.com Chris Abernethy

    Nice introduction to Zend_Mail! I’m currently working on porting a rather large web application to use Zend Framework, and I will definitely be looking at replacing our use of the mail() function with Zend_Mail.

  • Rauan Maemirov

    Thanks for nice post. But that fixes in bug tracker didn’t help me and completely broke my encoding instead of fixing it. I’ll try to investigate it soon.

  • Rauan Maemirov

    Thanks for nice post. But that fixes in bug tracker didn’t help me and completely broke my encoding instead of fixing it. I’ll try to investigate it soon.

  • http://www.techfounder.net Eran Galperin

    Don’t forget to contribute your findings in the bug tracker ;)

  • http://www.techfounder.net Eran Galperin

    Don’t forget to contribute your findings in the bug tracker ;)

  • http://wiip.fr Maxence Delannoy

    You can use the constant STDIN instead of fopen(“php://stdin”, “r”);

  • http://wiip.fr Maxence Delannoy

    You can use the constant STDIN instead of fopen(“php://stdin”, “r”);

  • http://tripodsys.com kuleshwar

    hi,
    i want to use zend mail but i don’t no how to start it & what will be its structure.

  • http://tripodsys.com kuleshwar

    hi,
    i want to use zend mail but i don’t no how to start it & what will be its structure.

  • Pingback: Getting started sending emails with the Zend Framework - The Disgruntled Developer

  • Pingback: The personal portfolio of Andrew Havens, website designer and developer. » Getting started sending emails with the Zend Framework

  • Pingback: procmail don’t execute php script - Admins Goodies