Laravel のエラーをメール通知する

Laravel でエラーが発生したときに Slack で通知する機能については、マニュアルにも記載があるのですが、より基本的(?)な気がするメール通知については Laravel の標準機能として用意されておらず、マニュアルにもそれっぽい記述がありません。必要に迫られたので、できるだけ Laravel の機能を使いながら実装してみました。環境は Laravel 9.x です。

メール通知用クラスの作成

まず、メール通知用のクラスを作成します。作成場所は /app/Logging/ あたりでよいと思います。後で説明する /config/logging.php で指定した情報は、$config['キー名'] で取得することができます。

<?php

namespace App\Logging;

use Monolog\Logger;
use Monolog\Handler\SymfonyMailerHandler;
use Symfony\Component\Mailer\Mailer;
use Symfony\Component\Mailer\Transport\Dsn;
use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransportFactory;
use Symfony\Component\Mime\Email;

class SendMail
{
    public function __invoke($config): Logger
    {
        $logger = new Logger('local');

        $levels = [
            'debug'     => Logger::DEBUG,
            'info'      => Logger::INFO,
            'notice'    => Logger::NOTICE,
            'warning'   => Logger::WARNING,
            'error'     => Logger::ERROR,
            'critical'  => Logger::CRITICAL,
            'alert'     => Logger::ALERT,
            'emergency' => Logger::EMERGENCY,
        ];

        // メール通知のための設定
        $subject = 'エラーレポート(' . config('app.name') . ')';

        $email = (new Email())
            ->from($config['from'])
            ->to($config['to'])
            ->subject($subject);

        $dsn = new Dsn(
            'smtp',
            $config['host'],
            $config['user'],
            $config['password'],
            $config['port'],
            $config['smtp_options']
        );

        $factory   = new EsmtpTransportFactory();
        $transport = $factory->create($dsn);
        $mailer    = new Mailer($transport);

        // エラーレベルが指定のレベル以上のエラーが発生したときはメール通知する
        return $logger->pushHandler(new SymfonyMailerHandler($mailer, $email, $levels[$config['level']]));
    }

}

ログ設定ファイルから呼び出す

次に、/config/logging.php で先ほど作成したクラスを呼び出すカスタムチャンネルを設定します。stack ドライバを使って、ログファイルへの記録とメール通知を有効にしています。

メール送信に必要な情報は、.env ファイルで設定してください。

<?php

use Monolog\Handler\NullHandler;
use Monolog\Handler\StreamHandler;
use Monolog\Handler\SyslogUdpHandler;

return [
    'default' => env('LOG_CHANNEL', 'stack'),

    'channels' => [
        'stack' => [
            'driver'            => 'stack',
            'channels'          => ['daily', 'mail'],
            'ignore_exceptions' => false,
        ],

        (略)

        'mail' => [
            'driver'       => 'custom',
            'from'         => env('MAIL_FROM_ADDRESS'),
            'to'           => env('ERROR_REPORT_TO'),
            'host'         => env('MAIL_HOST'),
            'user'         => env('MAIL_USER'),
            'password'     => env('MAIL_PASSWORD'),
            'port'         => env('MAIL_PORT'),
            'smtp_options' => [
                'verify_peer' => env('VERIFY_PEER', true),
            ],
            'via'          => App\Logging\SendMail::class,
            'level'        => 'error',
        ]
    ],
];

以上で、ログレベルが error 以上の場合に指定したメールアドレス宛にメールが届くようになります。なんとなく車輪の再発明感がありますが、同じことで悩んでいる方の参考になれば。

この記事を書いた人
グッドネイバー

“ Webに悩むお客さまの「よき隣人」でありたい ” をモットーに、Web システム開発(主に Laravel)、Web マーケティング支援の仕事をしています。お仕事のご依頼・ご相談はこちらからお気軽にどうぞ。