How to report exceptions via email automatically in Symfony 1.4 using sfErrorNotifierPlugin

Applications fail due to bad quality coding or just because you forgot to catch some code that wasn't supposed to fail at all. Whatever the reason is, you will obviously want to know when this happens to apply a counter measure. In symfony 1.4 there's a pretty easy way to do it attaching some action to the event dispatcher.

In this article, we will explain you briefly how to report exceptions of your Symfony 1.4 application via email automatically.

1. Create plugin structure

Inside the plugins directory, you will need to create a directory with the name of the plugin namely sfErrorEmailNotifierPlugin. Inside this directory you will create 2 directories with 2 classes as the following list shows:

  • sfErrorEmailNotifierPlugin
    • config
      • sfErrorEmailNotifierPluginConfiguration.class.php
    • lib
      • sfErrorEmailNotifierPlugin.php

We will provide you with the content of every class on the next steps, the important step by now is to create the directory with the mentioned structure (yourproject/plugins).

2. Create notification class

The sfErrorEmailNotifier class will contain the code that will be executed when an unhandled exception is thrown on your application. The dispatcher that will be connected to the application.throw_exceptions event of the application, will trigger the defined static function in the specified class. In our case, we will have a method namely notify that receives as first argument an sfEvent object and it will basically manipulate the event to extract the error information and send an email with it:

<?php

/**
 * This class notifies via Email details about exceptions on the application.
 * 
 * @package    symfony
 * @subpackage plugin
 * @author     Carlos Delgado <dev@ourcodeworld.com>
 */
class sfErrorEmailNotifier {

    static public function notify(sfEvent $event) {
        $email = "email@email.com";
        $passwordEmail = "12345";
        $date = date('d/m/Y H:i:s');
        
        $exception = $event->getSubject();
        
        $context = sfContext::getInstance();

        $env = 'n/a';

        if ($conf = sfContext::getInstance()->getConfiguration()) {
            $env = $conf->getEnvironment();
        } 

        // The notification should be sent only in production mode, not in development environment
        if($env == "prod"){
            try{
                $data = array();
                $data['className'] = get_class($exception);
                $data['message'] = !is_null($exception->getMessage()) ? $exception->getMessage() : 'n/a';
                $data['moduleName'] = $context->getModuleName();
                $data['actionName'] = $context->getActionName();
                $data['uri'] = $context->getRequest()->getUri();
                $data['line'] = $exception->getLine();
                $data['file'] = $exception->getFile();
                
                $subject = "Unhandled exception: {$_SERVER['HTTP_HOST']} Exception - $env - {$data['message']}";

                // 1. Build email HTML
                $emailContent = <<<EOF
    <h1>Automatic error report in your application</h1>
    <p>Date: {$fecha}</p>
    <br>
    <p>Subject: <b>{$subject}</b></p>
    <br>
    <p>An exception has been registered on the production environment, details as follow:</p>
        <ul>
            <li>Exception type: <b>{$data['className']}</b></li>
            <li>Message: <b>{$data['message']}</b></li>
        </ul>
    <p>The exception was thrown in:</p>
        <ul>
            <li>URI: <b>{$data['uri']}</b></li>
            <li>Module: <b>{$data['moduleName']}</b></li>
            <li>Action: <b>{$data['actionName']}</b></li>
            <li>File: <b>{$data['file']}</b></li>
            <li>Line: <b>{$data['line']}</b></li>
        </ul>
EOF;
                
                // 2. Send email
                // The transport message configuration may change according to your email service
                $transport = \Swift_SmtpTransport::newInstance('smtp.mailserver.com', 465, 'ssl')
                    ->setUsername($email)
                    ->setPassword($passwordEmail);

                $mailer = \Swift_Mailer::newInstance($transport);

                $message = \Swift_Message::newInstance("Automatic error report in {$nombreAplicacion}")
                    ->setFrom(array(
                        $email => 'Automatic error report'
                    ))
                    ->setTo(array(
                        "targetemail@mail.com" => "targetemail@mail.com"
                    ))
                    ->setBody($emailContent, 'text/html');

                // Enviar mail
                $mailer->send($message);
            }catch(Exception $e){}
        }
    }
}

3. Create plugin configuration class

Now that you have the code to send emails, you need to create a configuration class that will initialize the plugin when we register it later, the content of the sfErrorEmailNotifierPluginConfiguration.class.php will be the following (yourproject/plugins/sfErrorEmailNotifierPlugin/config/sfErrorEmailNotifierPluginConfiguration.class.php):

<?php

/**
 * Plugin configuration.
 * 
 * @package    symfony
 * @subpackage sfErrorEmailNotifier
 * @author     Carlos Delgado <dev@ourcodeworld.com>
 */
class sfErrorEmailNotifierPluginConfiguration extends sfPluginConfiguration {

    public function initialize() {
        // Registrar a evento global de reporte de errores
        $this->dispatcher->connect('application.throw_exception', array('sfErrorEmailNotifier', 'notify'));
    }
}

4. Enable Plugin

Finally, to enable the created plugin you need to add it to the application using the enablePlugins method in your sfProjectConfiguration class (yourproject/config/ProjectConfiguration.class.php):

<?php

require_once dirname(__FILE__) . '/../symfony-1.4.27/lib/autoload/sfCoreAutoload.class.php';

sfCoreAutoload::register();

class ProjectConfiguration extends sfProjectConfiguration {

    public function setup() {
        // 1. Enable plugin
        $this->enablePlugins(array(
            'sfErrorEmailNotifierPlugin'
        ));
    }
}

After saving the changes in the file, clear your project application with php symfony cache:clear and when there's an unhandled exception in your app, an email will be sent to notify you about the exception (with description).

Happy coding !

This could interest you

Become a more social person