Sending templated emails with CSS and inline images

Mark Sch edited this page Oct 25, 2016 · 4 revisions

For CakePHP 2.x

When sending templated HTML emails, your layout.ctp or template.ctp contains usually a few images. Those you should transform into inline attachments. You should also try to avoid inline CSS for creating templates, as this is hard to maintain. CSS should be transformed into inline CSS upon sending. Both tasks can be done using a helper and its afterLayout() callback via CakeEmail class.

Additionally you can use the helper to transform any absolute non-protocol URLs to ones with http:// added. So clicking the links from emails will actually work, in case you are using snippets that don't automatically make full URLs. I bet there are more use cases of post-processing generated emails prior to actually delivering them.

Actual work

Ideally, you use a helper and its afterLayout callback to finalize/modify the rendered HTML. Something like that:

App::uses('InlineCssLib', 'Tools.Lib');

class EmailProcessingHelper extends AppHelper {

    /**
     * Process Email HTML content after rendering of the email
     *
     * @param string $layoutFile The layout file that was rendered.
     * @return void
     */
    public function afterLayout($layoutFile) {
        $content = $this->_View->Blocks->get('content');
        $content = $this->_prepareHtmlContent($content); // Transforming images/urls

        if (!isset($this->InlineCss)) {
            $this->InlineCss = new InlineCssLib();
        }
        $content = trim($this->InlineCss->process($content)); // Transforming CSS

        $this->_View->Blocks->set('content', $content);
    }

}

Then add your helper to the Email object:

$this->Email->helpers(array_merge($this->helpers, ['EmailProcessing' => ['email' => $this->Email]]));