HTML Email Using Zend_Mail

The Zend Framework provides an extremely handy component for sending out Emails from your web applications – Zend_Mail

You no longer have to struggle with the nitty-gritty of smtp headers. Sending HTML mail using  this component is pretty straight-forward:

$mail = new Zend_Mail();
$mail->setBodyHtml($msg);
$mail->setFrom($from_email);
$mail->setSubject($subject);
$mail->addTo($toAddress);
$mail->send();

The code shown above is the “minimal” configuration, and gets the job done in most cases. However, with spam control being widely adopted, it is imperative that you follow certain guidelines so that your mail does not get blocked or sent to the spam or junk folder (in Outlook).

It took me a day of tweaking to figure out the issues with my code above that were causing MS Outlook to redirect mails, that were generated by the code above, to the “Junk” folder.

The first step is to fixing this is to understand the “internet headers” that get generated when email is sent. In Outlook 2007, You can view this information by right-clicking on the message and selecting “Message Options”. The internet headers are displayed at the bottom in a read-only text area.

Our work email server uses a Barracuda spam filter(additionally). Barracuda uses a set of rules to deduce whether an email is “spam-like”.  Outlook uses a similar engine to compute the spam probability of EVERY mail that it receives. The higher the score (sum of points), the more likely it is that the email is spam.

The barracuda spam report gets conveniently included in the internet headers for us, and is a good starting point to figure out the problem areas. Here is what my header looks like:

 

X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.2.15034
    Rule breakdown below
     pts rule name              description
    —- ———————- ————————————————–
    0.00 NO_REAL_NAME           From: does not include a real name
    0.00 HTML_MESSAGE           BODY: HTML included in message
    0.00 MIME_HTML_ONLY         BODY: Message only has text/html MIME parts
    0.01 BSF_SC0_SA_TO_FROM_DOMAIN_MATCH Sender Domain Matches Recipient
                               Domain

X-MS-Exchange-Organization-SCL: 5
X-MS-Exchange-Organization-PCL: 2

 

Note that the X-MS-Exchange-Organization-SCL score is ‘5’. This is the Exchange “Spam Confidence Level” on a range of 0-9. A number >=5 automatically classifies the email as Junk.

Notice that the “points” assigned for the first 3 items are “0”. So, from the Barracuda point of view, it is informational only. However, Outlook assigns different points to these items (and, we have no way of viewing the score assigned by Outlook). So, we need to take a look at ALL the barracuda messages one by one.

1. NO_REAL_NAME : Easy fix.. use the overloaded forms of setFrom, addTo, addCC, addBcc that allow including the real name.

2 & 3. HTML_MESSAGE and MIME_HTML_ONLY:

These messages are linked. Most modern email clients allow users the option of viewing “text-only” versions. So, whenever you send out HTML mail, you SHOULD ALSO ALWAYS use the setBodyText() method to send the alternative plain text mail.

4. BSF_SC0_SA_TO_FROM_DOMAIN_MATCH : This means that the domain from where we are sending emails matches the destination. Yes.. we are trying to send emails internally within the organization… so, we just have to take this as an informational message and move along.

After making the above changes, our code looks like:

        $mail = new Zend_Mail();
        $mail->setBodyText(strip_tags($msg));
        $mail->setBodyHtml($msg);
        $mail->setFrom($from_email,”my name”);
        $mail->setSubject($subject);
        $mail->addTo($toAddress,$toName);
        $mail->send();

I have used the strip_tags PHP function to generate a text only version of the HTML message.

A couple of important pointers here:

  1. The html and text version should differ .. Otherwise, it will trigger another rule  (Note the MPART_ALT_DIFF message) :

    X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.2.15146
        Rule breakdown below
         pts rule name              description
        —- ———————- ————————————————–
        0.00 HTML_MESSAGE           BODY: HTML included in message
        0.14 MPART_ALT_DIFF         BODY: HTML and text parts are different
        0.01 BSF_SC0_SA_TO_FROM_DOMAIN_MATCH Sender Domain Matches Recipient
                                   Domain

  2. Do ensure that the HTML message that you send into in the setBodyHtml is WELL FORMED. Errors in your html will cause the message to be classified as spam.
  3. The “from address” MUST be a valid/existing email address.. Using fictitious email addresses is a sure way to increase the spam score.

After the modifications, mail was being routed correctly. Here’s a peek at the internet header of the delievered mail:

X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.2.15375
    Rule breakdown below
     pts rule name              description
    —- ———————- ————————————————–
    0.00 HTML_MESSAGE           BODY: HTML included in message
    0.01 BSF_SC0_SA_TO_FROM_DOMAIN_MATCH Sender Domain Matches Recipient
                               Domain
X-MS-Exchange-Organization-SCL: 4
X-MS-Exchange-Organization-PCL: 2

Ok.. so now, notice that the MS-Exchange-Organization-SCL score is at 4.

 

UPDATE (Nov 24, 2009): The above process worked yesterday.. but today, the score is back to 5. The kicker is that it is not consistent! Some emails get redirected to the junk and some are delivered ok.

So, finally, I decided to avoid HTML email altogether. I changed my emails to include only text along with a URL to view detail in all HTML glory. Outlook has made it too cumbersome to dependably send HTML formatted email.

Leave a comment