Fork me on GitHub

laravel在发生异常错误时如何发送邮件通知


知识太多了就容易装B,知识太少就容易犯浑,像我这样不多不少刚刚好,想装B就装B,想犯浑就犯浑。

我们建了一个新的laravel项目并部署到了生产服务器,一切都工作正常,直到一个客户因为我们的bug遇到了一个问题,随即用户离开了我们的程序, 在我们发现这个bug之前,同样的问题发生在了越来越多的客户身上.随后你修复了bug, 所有的都恢复到了正常.但是如果你能在bug发生时得到邮件通知并很快修复他,在laravel中, 这个很容易实现;
在laravel项目中, 所有的异常都是App\Exceptions\Handler 这个类处理的,这个类包含了两个方法:reportrender. 现在我们只关心report这个方法. 这个类使用日志记录异常或者是发送异常到一些其他的服务像Bugsna或者Sentry. 默认情况下, report这个方法只是简单的传递异常到基类中,进而被写到日志里.然而,我们也可以发送邮件给开发者关于这些异常.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* Report or log an exception.
*
* This is a great spot to send exceptions to Emails.
*
* @param \Exception $exception
* @return void
*/
public function report(Exception $exception)
{
if ($this->shouldReport($exception)) {
$this->sendEmail($exception); // sends an email
}
return parent::report($exception);
}
/**
* Sends an email to the developer about the exception.
*
* @param \Exception $exception
* @return void
*/
public function sendEmail(Exception $exception)
{
// sending email
}

Here we are using shouldReport method to ignore exceptions which are listed in the $dontReport property of the exception handler.

Each type of email sent by the application is represented as a “mailable” class in Laravel. So, we need to create our mailable class using the make:mail command:

1
$ php artisan make:mail ExceptionOccured

This will create a class ExceptionOccured in the app/Mail directory.

Merely sending the mail will not solve the problem. We need the full stack trace of the exception. And for that, we can use the Symfony’s Debug component.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public function sendEmail(Exception $exception)
{
try {
$e = FlattenException::create($exception);
$handler = new SymfonyExceptionHandler();
$html = $handler->getHtml($e);
Mail::to('developer@gmail.com')->send(new ExceptionOccured($html));
} catch (Exception $ex) {
dd($ex);
}
}

Make sure you add the following code at the top of the file:

1
2
3
4
se Mail;
use Symfony\Component\Debug\Exception\FlattenException;
use Symfony\Component\Debug\ExceptionHandler as SymfonyExceptionHandler;
use App\Mail\ExceptionOccured;

Note—We have used the try block to avoid the infinite loop if the mail command fails.

Then, in your ExceptionOccured mailer class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
class ExceptionOccured extends Mailable
{
use Queueable, SerializesModels;
/**
* The body of the message.
*
* @var string
*/
public $content;
/**
* Create a new message instance.
*
* @return void
*/
public function __construct($content)
{
$this->content = $content;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->view('emails.exception')
->with('content', $this->content);
}
}

Add the following code in your emails.exception view file:

1
{!! $content !!}

Now, whenever an exception is thrown in your application, you will receive an email with full stack trace. Cool!

I have created a Laravel package named squareboat/sneaker(https://packagist.org/packages/squareboat/sneaker) to do all this cumbersome work for you so you can concentrate on solving the bug.

Some of the features of the sneaker are:
– On/off emailing using .env file.
– Customizing the email body.
– Ignoring the exception generated by bots.

and more to come.

If you want the complete source code for this(https://github.com/akaamitgupta/laravel-error-emailer-demo), I’m more than happy to share it and you can find the source code on Github

https://laravel-news.com/email-on-error-exceptions