Laravel 5向电子邮件发送错误

时间:2015-10-16 06:30:11

标签: php laravel

我想知道如何在Laravel 5中向我的电子邮件发送错误。我没有找到任何好资源的运气。

以前有很好的包装: https://github.com/TheMonkeys/laravel-error-emailer 这在Laravel 4中为你做到了这一点。

他们还没有发布Laravel5更新,因为他们改变了错误处理的方式......我也不熟悉。

我需要监控一些Laravel 5应用程序,但除了检查存储上的错误日志之外,我还需要一种更有效的方法。

非常感谢任何帮助。我知道还有其他人也在寻找这些信息。

9 个答案:

答案 0 :(得分:26)

您可以通过捕获App\Exceptions\Handler::report()中的所有错误来执行此操作。因此,在您App/Exceptions/Handler.php中添加report函数(如果尚未存在)。

/**
 * Report or log an exception.
 *
 * This is a great spot to send exceptions to Sentry, Bugsnag, etc.
 *
 * @param  \Exception  $e
 * @return void
 */
public function report(\Exception $e)
{
    if ($e instanceof \Exception) {
        // emails.exception is the template of your email
        // it will have access to the $error that we are passing below
        Mail::send('emails.exception', ['error' => $e->getMessage()], function ($m) {
            $m->to('your email', 'your name')->subject('your email subject');
        });
    }

    return parent::report($e);
}

如果您需要更多信息,请参阅laravel文档表单mailererrors

答案 1 :(得分:7)

编辑:我找到了为Laravel

构建的第三方日志系统

www.understand.io

非常好的解决方案,不会给我发电子邮件,但这适用于我需要的。

我玩弄了这个并浏览了Laravel核心文件,并提出了类似于您在错误页面上看到的内容。

您只需要创建一个回显电子邮件的$ content的视图文件

.excerpt p:last-child::after {
    content: '..';
}

答案 2 :(得分:2)

您可以使用Exception Handler。将您的邮件代码放在报告功能中,每次发生时都会通过电子邮件向您发送错误。

答案 3 :(得分:2)

其他答案似乎很正确。我们刚刚做了这个,发现了一个很大的问题:如果mail命令失败,可能会导致无限循环抛出错误并尝试发送相应的电子邮件,这将导致再次失败...将很快填满日志并杀死你的服务器。

牢记这一点,在这种情况下不要发送电子邮件。

旁注:我决定将其放在答案中,因为它与所有答案相关,不应隐藏在一条评论中。

答案 4 :(得分:1)

以下是Laravel 5.3的解决方案

#file:   /app/Exceptions/Handler.php

public function report(Exception $e)
{
    if($this->shouldReport($e)){

        \Mail::send(
            ['html' => 'error.emails.exception'],
            ['content' => $data['content']],
            function ($m) {
                $m->from(['myemail@from.com']);
                $m->to(['myemail@to.com']);
                $m->subject('Crash Report');
            }
        );
    }

    parent::report($e);
}
  • 您需要在/ resources / views / emails
  • 中创建exception.blade.php文件
  • 我建议您使用this content,使电子邮件看起来与Laravel的错误页面相同。

答案 5 :(得分:1)

我扩展了West55的答案,在电子邮件中包含一些请求信息。知道很有用,特别是当你想尝试自己复制错误时。它包含在try / catch中,以确保在获取请求信息时不会抛出另一个异常。

 public function report(Exception $e)
{
    if ($e instanceof Exception){

        $debugSetting = \Config::get('app.debug');
        // email err if debug off (in prod env)
        if (!$debugSetting){
            \Config::set('app.debug', true);
            if (ExceptionHandler::isHttpException($e)) {
                $content = ExceptionHandler::toIlluminateResponse(ExceptionHandler::renderHttpException($e), $e);
            } else {
                $content = ExceptionHandler::toIlluminateResponse(ExceptionHandler::convertExceptionToResponse($e), $e);
            }
            \Config::set('app.debug', $debugSetting);

            $lc2 = (isset($content->original)) ? $content->original : $e->getMessage();

            // add request info to err msg
            $lc1= '';
            try{
                $request= request();
                $lc1=
                    "<div>" .
                    "-- Request --<br>" .
                    "<br>Method: " . $request->getMethod() .
                    "<br>Uri: " . $request->getUri() .
                    "<br>Ip: " . $request->getClientIp() .
                    "<br>Referer: " . $request->server('HTTP_REFERER') .
                    "<br>Is secure: " . $request->isSecure() .
                    "<br>Is ajax: " . $request->ajax() .
                    "<br>User agent: " . $request->server('HTTP_USER_AGENT') .
                    "<br>Content:<br>" . nl2br(htmlentities($request->getContent())) .
                    "</div>";
            }catch (Exception $e2){}

            if (strpos($lc2, '</body>') !== false){
                $lc2= str_replace('</body>', $lc1 . '</body>', $lc2);
            }else{
                $lc2.= $lc1;
            }
            $la2['content']= $lc2;      //put into array for blade

            $ln1= Mail::send('emails.exception2', $la2, function($m){
                    $m->to('support@mydomain.com')
                    ->subject('Fatal Error');
            });
        }
    }
    parent::report($e);
}

答案 6 :(得分:1)

这里https://github.com/designmynight/laravel-log-mailer有一个软件包,可以在Laravel 5.6的LogManager中添加一个邮件驱动程序,该软件包应该可以完全满足您的需求。

config / logging.php文件中有一些配置设置,您可以创建用于将信息记录到不同收件人的不同邮件通道。电子邮件模板也是可自定义的。

答案 7 :(得分:0)

/config/logging.php

// ...
        'monitoring-mail' => [
            'driver' => 'custom',
            'via' => App\Logging\Mail::class,
            'level' => env('LOG_MONITORING_MAIL_LEVEL', 'error'),
            'to' => env('LOG_MONITORING_TO'),
            'from' => env('LOG_MONITORING_FROM'),
        ],
// ...

/app/Logging/Mail.php

<?php

namespace App\Logging;

use App\Helpers\Log\MailHandler;
use Monolog\Logger;

class Mail
{
    public function __invoke(array $config)
    {
        $handler = new MailHandler($config['to'], $config['level'], $config['bubble'] ?? true, $config);
        return new Logger('mail', [$handler]);
    }
}

/app/Helpers/Log/MailHandler.php

<?php

namespace App\Helpers\Log;

use Illuminate\Mail\Message;
use Illuminate\Support\Facades\Mail;
use Monolog\Handler\AbstractProcessingHandler;
use Monolog\Logger;

class MailHandler extends AbstractProcessingHandler
{
    /** @var string */
    protected $to;

    /** @var array */
    protected $config;

    public function __construct(string $to, $level = Logger::DEBUG, bool $bubble = true, ?array $config = null)
    {
        parent::__construct($level, $bubble);
        if (empty($to)) {
            throw new \InvalidArgumentException('"To" cannot be empty');
        }
        $this->to = $to;
        $this->config = (array) $config;
    }

    protected function write(array $record): void
    {
        $body = $record['formatted'] ?? $record['message'] ?? '<empty>';
        Mail::raw($body, function (Message $message) use ($record) {
            $subject = ($record['level_name'] ?? 'ERROR') . ': ' . ($record['message'] ?? '<empty>');
            $message->to($this->to);
            $message->subject($subject);
            if (!empty($this->config['from'])) {
                $message->from($this->config['from']);
            }
        });
    }
}

答案 8 :(得分:0)

在这里,您有一个Laravel 6.x解决方案,其中包含html错误描述,跟踪和所有var(如果有人希望增加),还应该为可添加到此html正文中的mysql查询提供一个呈现器。 / p>

重要!不要忘记将Debug配置设为false ,您可以在env文件设置中做到这一点:

APP_DEBUG=false

或者您也可以在/config/app.php文件中对其进行更改

 /*
|--------------------------------------------------------------------------
| Application Debug Mode
|--------------------------------------------------------------------------
|
| When your application is in debug mode, detailed error messages with
| stack traces will be shown on every error that occurs within your
| application. If disabled, a simple generic error page is shown.
|
*/

//'debug' => env('APP_DEBUG', false),
//to
'debug' => false, //now not lookin for the envfile value

否则,所有用户都将看到带有大量私人信息的DEBUG SCREEN。

解决方案是将Handler扩展为 /app/Exceptions/Handler.php

并替换下一个代码的渲染功能。

public function render($request, Exception $exception)
{
    $html = $this->renderExceptionWithSymfony($exception, true);

    $array = $this->convertExceptionToArray($exception);

    $html .= $this->renderVars($_SERVER, "Server Vars");
    $html .= $this->renderVars($_REQUEST, "Requests Vars");
    $html .= $this->renderVars($_COOKIE, "Cookies");
    
    \Mail::send('emails.error', ['html'=>$html], function ($m) {
        $m->to('developer@mail.com', 'Server Message')->subject('WEB ERROR');
    });
    
    return parent::render($request, $exception);
}

并在新渲染器旁边添加新功能renderVars。该功能将转换服务器,将cookie数组请求为清晰的

public function renderVars($vars, $titulo)
{
    $html = '<table class="trace-details">
                <thead class="trace-head">
                    <tr>
                        <th><h3 class="trace-class"><span class="exception_title">'.$titulo.'</span></h3></th>
                    </tr>
                </thead>
                <tbody>';
            forEach($vars as $key=>$value)
            {
                $html .= '<tr>
                                    <td>
                                        <span class="block trace-file-path">
                                            <span title="'.$key.'"><strong>'.$key.'</strong></span>
                                        </span>
                                    </td>
                                    <td>
                                        <span class="block trace-file-path">';
                                        if(!is_array($value))
                                        {
                                            $html .= '<span title="'.$value.'"><strong>'.$value.'</strong></span>';
                                        }
                                        else
                                        {
                                            $html .= '<span title="ARR | '.implode(', ', $value).'">ARR | <strong>'.implode(', ', $value).'</strong></span>';
                                        }
                                        $html .= '</span>
                                    </td>';
                                $html .= '</tr>';
            }
                    $html .= '</tbody>
                                </table>';
    return $html;
}

最后,您需要在/resources/views/emails/error.blade.php文件夹中创建一个刀片视图,在这种情况下,此刀片仅打印从render函数格式化的html错误。邮件功能发送数组参数并转换为视图。

在这种情况下,刀片错误模板(/resources/views/emails/error.blade.php)的代码仅为:

<?=$html?>

打印收到的格式化的html。

此外,如果要自定义错误前端屏幕,则需要在文件夹(/resources/views/errors/.blade.php)中创建一个新的刀片服务器模板,如下所示: 500.blade.php ---->用于内部服务器错误 404.blade.php ---->找不到错误。 如果您不想这样做,laravel将显示默认的错误模板。

我希望这对其他人有帮助。

最好的问候, Reb duvid。