Sending Laravel exceptions to your email

Sending Laravel exceptions to your email

19th of July, 2018 - Mark Halcroft

In this quick tutorial, I'd like to show you a practical example of how I send Laravel "Whoops" exceptions to my email.

Creating the Mailer

First, let's create the Mailer class that will handle sending the exception to our email. In your terminal, navigate to your project and run the following artisan command:

$ php artisan make:mail Exception

Open your newly created Mailer class from app/Mail/Exception.php and use the following:

<?php

namespace App\Mail;

use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;

class Exception extends Mailable
{
    use Queueable, SerializesModels;

    public $data;

    /**
     * Create a new message instance.
     *
     * @param $data
     */
    public function __construct($data)
    {
        $this->data = $data;
    }

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        return $this->view('emails.exception')
            ->subject('Exception Logged!')
            ->from('exceptions@domain.com')
            ->to('youremail@domain.com')
            ->with([
                'data' => $this->data,
            ]);
    }
}

Updating the Exception Handler

Now that we have our Mailer class, we can go and make some changes the default Exception Handler class at app/Exceptions/Handler.php.

<?php

namespace App\Exceptions;

use Exception;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Support\Facades\Mail;

use Symfony\Component\Debug\Exception\FlattenException;
use Symfony\Component\Debug\ExceptionHandler as SymfonyExceptionHandler;
use App\Mail\Exception as ExceptionMail;

class Handler extends ExceptionHandler
{
    /**
     * A list of the exception types that are not reported.
     *
     * @var array
     */
    protected $dontReport = [
        //
    ];

    /**
     * A list of the inputs that are never flashed for validation exceptions.
     *
     * @var array
     */
    protected $dontFlash = [
        'password',
        'password_confirmation',
    ];

    /**
     * Report or log an exception.
     *
     * @param  \Exception $exception
     * @return void
     * @throws Exception
     */
    public function report(Exception $exception)
    {
        if ($this->shouldReport($exception)) {
            $this->sendExceptionEmail($exception);
        }

        parent::report($exception);
    }

    /**
     * Parse the exception and send email
     *
     * @param Exception $exception
     */
    public function sendExceptionEmail(Exception $exception)
    {
        try {
            $e = FlattenException::create($exception);

            $handler = new SymfonyExceptionHandler();

            $html = $handler->getHtml($e);

            Mail::queue(new ExceptionMail($html));
        } catch (Exception $e) {
            //
        }
    }

    /**
     * Render an exception into an HTTP response.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Exception  $exception
     * @return \Illuminate\Http\Response
     */
    public function render($request, Exception $exception)
    {
        /**
         * Had to put this in because it was throwing an exception if the user wasn't unauthenticated
         */
        if ( ! $this->shouldReport($exception)) {
            return parent::render($request, $exception);
        }

        if(config('app.debug')) {
            return parent::render($request, $exception);
        }

        return response()->view('errors.custom', [], 500);
    }
}

Create the view

This is the easy part. Simply create a new blade view file at views/emails/exception.blade.php and add the following:

{!! $data !!}

 That's it!


Hi

My name is Mark Halcroft. I am a web developer and founder of Brainbook where we make websites and web apps for - but not limited to - the A/V industry. We specialise in Laravel and PHP and are based in Melbourne, Australia.