anty.info

Comments and help 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!


13 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!

  5. I found this helpful but I think it’s slightly simpler in Zend Framework 1.7. This seemed to work for me:

    $mail = new Zend_Mail(); $msg = 'This image should be inline.'; $image = file_get_contents('image.gif'); $im = $mail->createAttachment($image, 'image/gif', Zend_Mime::DISPOSITION_INLINE, Zend_Mime::ENCODING_BASE64); $im->id = 'someid'; $mail->setBodyHtml($msg) ->send();

  6. It seems that the HTML tags got removed from my last post.

    I would suggest using htmlentities() instead of strip_tags()

    :)

  7. Thanks for the suggestion Ben. It’s actually the blogging software “WordPress” that strips all but a few styling tags. I would search for or write a plugin that replaces strip_tags() with htmlentities(), but that would take away the option to post formatted comments.
    Thank you for your comments, Ben!

  8. $mail->setType(Zend_Mime::MULTIPART_RELATED);

    ^ That was exactly what was missing from my emails. Thanks!

  9. Thank you so much! Didn’t know about the multipart/related type and that this is important for thunderbird to display properly inline images. Nice website but the black background makes it kind of hard to read :)

  10. Thanks for the feedback Giannis, I’ll consider a white background next time I change my template!

  11. But how exactly do you use those attached images within the body html?

  12. Randell, you attach them to your mail.
    Here’s the documentation for attaching files in Zend_Mail.

  13. Hi:

    After several hours struggling with this, I found this post and all worked like a charm.

    I’m using zend Framework 1.11.3

    My working code is this:

    $mailImage = file_get_contents('path/to/filename');
    $at = new Zend_Mime_Part($mailImage);
    $at->type = 'image/jpeg';
    $at->disposition = Zend_Mime::DISPOSITION_INLINE;
    $at->encoding = Zend_Mime::ENCODING_BASE64;
    $mail = new Zend_Mail('utf-8');
    $mail->setType(Zend_Mime::MULTIPART_RELATED);
    //$mail->setBodyText('This is the text of the mail.');
    $mail->setBodyHtml($mailHtml, null, Zend_Mime::MULTIPART_RELATED);
    $mail->setFrom('[email protected]', 'Some Sender');
    $mail->addTo('[email protected]', 'Some Recipient');
    $mail->setSubject("mailSubject");
    $mail->addAttachment($at);
    $mail->send();

    Hope it helps someone.

Leave a Reply

« »