Skip to content

EmailLib

Mark Sch edited this page Oct 20, 2016 · 18 revisions

-- CakePHP 2.x --

The EmailLib extends the CakeEmail class and acts as a more intelligent wrapper class. It adds some more usefulness and makes debugging/testing easier.

See introducing-the-emaillib.

Goodies

  • Auto-set "from" as admin email (no need to do that in the code unless needs overwriting).
  • Catches the exception and logs it away. This way most user land code can be kept simple as the try catch block is not needed. It will simply return boolean/success.
  • Enable easier attachment adding (and also from blob):
    • addAttachment($file, $name = null, $fileInfo = array())
    • addBlobAttachment($content, $name, $mimeType = null, $fileInfo = array())
  • Enable embedded images in html mails:
    • addEmbeddedAttachment($file, $name = null, $contentId = null, $options = array())
    • addEmbeddedBlobAttachment($content, $name, $mimeType = null, $contentId = null, $options = array())
  • Can work with foreign attachments/images (different domains and alike)
  • Auto mimetype detection for attachments (inline or not).
  • Allow wrapLength to be adjusted: wrapLength($length = null).
  • Configure::read('Config.xMailer') can modify the x-mailer header.
  • Basic validation supported.
  • Allow priority to be set (1 to 5): priority($priority = null).
  • Quick way to send system emails/reports: App::uses() + EmailLib::systemEmail($subject, $message).
  • Extensive logging and error tracing as well as debugging using getDebug()/getError().
  • Don't send emails without Configure::write('Email.live'), but log them away verbosely. For testing.
  • Security measure: Don't send emails to actual addresses in debug mode, they will be sent to Configure::read('Config.adminEmail') instead. Same for cc/bcc.

Setup

It is easiest to extend the Tools plugin BaseEmailConfig class. It provides a wrapper to set many of the above on its own. It also helps to have settings in configs_private.php files instead of actually committing them into the email.php class (which might want to be kept in version control in a stubbed way.

// Config/email.php
App::uses('BaseEmailConfig', 'Tools.Config');

class EmailConfig extends BaseEmailConfig {

	public $default = array(
		'host' => 'example.de',
		'port' => 465,
		'username' => '[email protected]',
		'password' => '', // Will be set via Configure and configs_private
		'template' => 'custom',
		'layout' => 'custom',
		'transport' => 'Smtp',
		'trace' => true, // Detailed trace log (including email content) for debugging
		'log' => true // Report log entry
	);

	public $mandrill = array(
		'transport' => 'Mailchimp.Mandrill',
	);

}
// Config/configs_private.php
Configure::write('Email.Pwd.default', 'mypwd');

default maps to the attribute public $default here.

If want to use some special "transport type" based setting, overwrite them all in your private config. Let's say for live we need a different SMTP setting then for stage.

Configure::write('Email.Smtp.host', 'example.de');
Configure::write('Email.Smtp.username', '[email protected]');
Configure::write('Email.Smtp.password', 'somepwd');
// Same for port, timeout, tls, ...

This is mainly to being able to more dynamically adjust the Transport class and its settings at runtime.

For the actual EmailLib you will need some Configure keys, as well:

// Main system email, will be used as default "from"
Configure::write('Config.systemName', 'Our webseite');
Configure::write('Config.systemEmail', '[email protected]');

// Main admin email, will be used as fallback if no systemEmail is set/needed
Configure::write('Config.adminName', 'dereuromark');
Configure::write('Config.adminEmail', '[email protected]');

// I also set and use this for some Emails (optional - you need to use those manually and overwrite the default from)
Configure::write('Config.noReplyName', 'dereuromark');
Configure::write('Config.noReplyEmail', '[email protected]');

Note that the name is optional whereas the email is necessary (for system and admin anyway).

For EmailLib::systemEmail() messages "systemEmail" will sent to "adminEmail". For all others "systemEmail" will send to the actual addresses if debug mode is off - and Configure::write('Email.live') is true.

Usage

// At the top of the file
App::uses('EmailLib', 'Tools.Lib');

// In your action / model method / shell command etc
$this->Email = new EmailLib();
$this->Email->to($user['User']['email'], $user['User']['username']);
$this->Email->subject($subject);
$this->Email->template($template, $layout);
$this->Email->viewVars(compact('someVariable'));
if (!$this->Email->send()) {
	return false;
}
return true;

Tip: Sending mails in other's names

If you plan on sending mails from user x (email xx) to user y (email yy) and you don't "own" the domain of email xx you will usually not be able to send it properly (it will easily be spam-flagged as you as the owner cannot be authenticated - a faked sender address is among the #1 signs for spam).

If you are not able to use this user's SMTP data (for security reasons of course), you should send it from your "from" address and set the user's email in the "reply to" part. This way, the email gets delivered for sure. When the user clicks on reply it will not reply to you then, though, but to the actual user x - mission accomplished.

$this->Email->from(Configure::read('Config.noReplyEmail'), Configure::read('Config.noReplyName'));
$this->Email->replyTo($userX['User']['email'], $userX['User']['username']);		
$this->Email->to($userY['User']['email'], $userY['User']['username']);	

Instead of the noReplyName you can probably also use his username $userX['User']['username'].

Clone this wiki locally