Occupied, DND, Away

A busy guys notes on web development.
18  02 2008

Zend_Mail Obstacles

I just finished developing a newsletter-script for a client.
I encountered some problems during the development and want to publish the solutions here.

I used Zend_Mail and Zend_Mime to create HTML-mails with inline images. I used the last stable Zend Framework version available right now: 1.0.3.

Microsoft Outlook 2007 displays odd characters, Thunderbird doesn’t

Check if you use:
new Zend_Mail('utf8');
If you do, change it to:
new Zend_Mail('utf-8');
Outlook doesn’t like the non-dashed version of the UTF-8 charset.

Inline images are displayed as attachments

You need to set the type of the mail to Multipart/Related:
$mail->setType(Zend_Mime::MULTIPART_RELATED);
Add the images like this:
$mail->createAttachment($imageData, $imageType, Zend_Mime::DISPOSITION_INLINE, Zend_Mime::ENCODING_BASE64);
Add the HTML-Version of the mail like this:
$mail->setBodyHtml($htmlMessage, null, Zend_Mime::MULTIPART_RELATED);

The subject displays odd characters

There’s a bug in Zend_Mail that causes subjects longer than 200 characters to be malformed in the mail. It’s also causing problems in the Zend Framework version 1.5 preview. The solution is to use subjects shorter than 200 characters until a fix is integrated in Zend_Mail.

Zend_Mail throws a 501 exception on international mail-addresses

If your email addresses are pointing to domains like hpphör.de, your SMTP-server might prevent you from sending to them, causing Zend_Mail to throw a 501 exception. A possible solution is to convert the domainname to the IDN equivalent (hpphör.de results in xn--hpphr-mua.de). Currently, there is no ZendFramework module available to do the conversion. Maybe the IDN Pecl package can help you on this subject.

Note: Malformed mail addresses also cause a 501 exception to be thrown. Catching a 501 exception does not guarantee an IDN domain-address!

The HTML layout is totally messed up

Don’t use CSS for styling, go back to Table-based styling. Most mail-clients still don’t display HTML correctly. Use inline-style definitions, even though they produce redundant code.

Get more information on HTML mail styling here:

I hope this helps a bit if you find yourself in the position to code a PHP mail-script.

At SitePoint I found a very good article that covers how to design HTML mails from the content point of view. I recommend to read the first two pages if you need to write the content by yourself!


4 Responses to “Zend_Mail Obstacles”

  1. new Zend_Mail(’utf-8′);
    thank !!!

  2. Thanks for your post on ‘Inline images are displayed as attachments’ … we have REALLY battled to find any help on attaching images inline with the zend_mail… do you by any chance have a full example of how you attached the images into the body, without the image showing as a jpeg?
    thanks a mill!!

  3. @Wayne: I try to extract the important things from my script for you.
    Here’s how to determine the image type:

    // getimagesize returns false, if the URL does not exist if (file_exists($imagePath) || getimagesize($imagePath)) { $image = file_get_contents($imagePath); if (function_exists('exif_imagetype') && function_exists('image_type_to_mime_type')) { $imageType = image_type_to_mime_type(exif_imagetype($imagePath)); } }

    I did this to replace all image-tags in my mail template with references to the attached images (cid):

    if (!is_null($image)) { $cid = md5($image) .'.'. md5(microtime()); $images[$cid] = array($image, $imageType); if (trim($src[1]) == " && trim($src[2]) != ") { $templateMessageTemp = preg_replace('/(<img\\s[^>]*src=)(?:"' . preg_quote($src[2], '/') .'"|\\\". preg_quote($src[2], '/') .'\\\')([^>]*>)/i', '${1}"cid:'. $cid .'"${2}', $templateMessage); } elseif (trim($src[1]) != ") { $templateMessageTemp = preg_replace('/(<img\\s[^>]*src=)(?:"' . preg_quote($src[1], '/') .'"|\\\". preg_quote($src[1], '/') .'\\\')([^>]*>)/i', '${1}"cid:'. $cid .'"${2}', $templateMessage); } if ($templateMessageTemp == $templateMessage) { // nothing was replaced (duplicate images whas used), ignore this image unset($images[$cid]); } $templateMessage = $templateMessageTemp; }

    Here is how I attached the images with the right cid:

    // attach images foreach ($images as $cid => $image) { $imageData = $image[0]; $imageType = $image[1]; if ($imageType === false) { $at = $mail->createAttachment($imageData); } else { $at = $mail->createAttachment($imageData, $imageType, Zend_Mime::DISPOSITION_INLINE, Zend_Mime::ENCODING_BASE64); } $at->id = $cid; }

    I hope this helps you!

  4. Thank you for posting the hint about
    $mail->setType(Zend_Mime::MULTIPART_RELATED);

    I tried for hours to send a mail with inline images and this was the only thing I did not do.
    After adding this line it worked perfectly, thanks again!

Leave a Reply

« Google Suggest Banning What you pay for sending 10 million spam mails a day »