Introducing the EmailLib

This is a good example of how useful it can be to even extend some basic core classes to enhance them and fit them to your needs.

In this case we extend the CakeEmail Utility Lib class and add some fixes as well as some enhancements.
The full list can be obtained from the documentation of the class itself which can be found in the Tools Plugin.

Usage

First things first: How will it be used? Not so much different from the core class. But we don’t need to set the defaults (as the wrapper utility takes care of that). The idea is to make it as DRY (don’t repeat yourself) as possible.
So it is just:

App::uses('EmailLib', 'Tools.Lib');
$this->Email = new EmailLib();
$this->Email->to($email, $name);
$this->Email->replyTo(Configure::read('Config.adminEmail')); //optional
$this->Email->subject($subject);
$text = '...';
$this->Email->viewVars(compact('text'));
return $this->Email->send();

As you can see the from part is also set automatically (with the Configure::read('Config.admin_email') setting).
The replyTo part is optional but very handy if you want to send emails to users in have of other users (then the reply to part would be set to the other user’s email address). You should never set "from" to anything but your own mail server to avoid your emails being marked as spam.

It is also a good idea to store all site wide email addresses in your Configure, as well. In the above example the admin email + name for the optional replyTo part. Never write those addresses in your code – it will end up redundant at some point and lead to problems.

Requirements

You should set the following config values in Configure:

Configure::write('Config.adminEmail', 'youremail');
Configure::write('Config.adminName', 'yourname');

There are some more optional Config settings. See the code for details.

Main improvements

I will outline only the most important ones which made me use this wrapper class in all 10+ projects for a clean and easy email functionality.

Easy config switching based on the environment

Via Configure config settings you can easily adjust your Email config to apply for different productive vs test environments.

Extended Logging

With logReport=>true you get quite verbose log output saved to email (to, from, subject) and email_error for SMTP and other errors. Additionally, with logTrace=>true the email_trace log (complete email content) is filled – as it internally enables the logging of the content upon delivery via Transport class.

No mails in debug mode

If you are in debug mode the emails get only saved to the above email_trace.log – they will not actually be sent.
This is very helpful in development (no accidental emails to live customers etc).

Note: This requires the BaseEmailConfig of the Setup plugin (you can also copy and paste that piece of code, of course).
The setup for your APP/Config/email.php would then be:

App::uses('BaseEmailConfig', 'Setup.Lib');

class EmailConfig extends BaseEmailConfig {
    ...
}

It also allows you to set your Email configs more dynamically (using Configure::read/write) – see "other improvements" below.

Embedded Attachments

This will automatically set the contentId and mimeType of the file. This is necessary for embedded attachments.

$this->Email->addEmbeddedAttachment('/some/file.ext', 'Some custom name');

Blob Attachments – as real attachment

This will automatically set the mimeType of the file (using the filename you provide).

$this->Email->addBlobAttachment($somePngFileBlobContent, 'my_filename.png');

Embedded Blob Attachments

This will also automatically set the mimeType of the file as above. But it will set the contentId, as well. This is necessary for embedded attachments.

$this->Email->addEmbeddedBlobAttachment($somePngFileBlobContent, 'my_filename.png');

No Exceptions thrown outside the wrapper

This is quite important because usually no one wraps his email sending functionality with try-catch-blocks.
The wrapper catches those exceptions and logs them and will simply return false.

Other improvements

There is more, of course. Like the possibility to set the password and other security sensitive information via non-version-controlled config file (Configure::read/write). But those a minor things that will probably only be used by me.
Or the possibility to override the X-Mailer header.

Example on how to set the configs dynamically via config:

// only the pwd
Configure::write('Email.Pwd.default', 'mypwd');

// complete email config
Configure::write('Mail.useSmtp', true);
Configure::write('Mail.smtpUsername', 'username');
Configure::write('Mail.smtpPassword', 'pwd');
...

Main fixes

The core class has a problem with valid message ids in shell environment as of cake2.1 and will probably be fixed in 2.2.
Until then the wrapper also takes care of that.

You can just set the domain manually from the CLI to "simulate" the environment you are under:

$this->Email->domain('www.mydomain.com');

This will make your Emails use this domain instead of an empty string in your messageId.

Note: This is already part of the core now (2.2).

Update 2013-06

Further improvements (see the inline class doc block for details):

  • allow wrapLength to be adjusted
  • Configure::read(‘Config.x-mailer’) can modify the x-mailer
  • basic validation supported
  • allow priority to be set (1 to 5)

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.