Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

divspace's avatar

How to monitor and log all email that is sent out?

Currently, I'm monitoring a lot of various things that happen when users update their contact information, invite a member to their team (I'm using Laravel Spark as well), etc.

We archive all of our mail that's sent out via SendGrid on the production server (log on local and MailTrap on dev, test, and demo servers), but want to store it on our audit/activity log database to get rid of the archive we hold).

I'm thinking I need an Event/Listener, but honestly don't know where to start on this. I'd basically be logging everything about the email (from address, to address, subject, body, time sent, etc.). So regardless of how mail is sent (previously mentioned), I want to catch all the data as well.

Thoughts?

Oh, and currently on Laravel 5.3.30 and Laravel Spark 3.0.1.

Much appreciated!

0 likes
9 replies
bobbybouwmann's avatar
Level 88

Laravel is throwing an event called MessageSending for which you can write listeners and log the data in there.

This events has the variable $message which holds the full Swift_Message object of the email, so it's everything you need.

You probably would have a listener that parses the Swift_Message object to a string and log that. Something like this

namespace App/Listeners;

use Illuminate\Mail\Events\MessageSending;

class LogEmail
{
    public function handle(MessageSending $event)
    {
        $message = $event->message;

        // The Swift_Message has a __toString method so you should be able to log it ;)
        Log::info($message);
    }
}

Documentation: https://laravel.com/docs/5.3/mail#events

6 likes
bobbybouwmann's avatar

Note that in Laravel 5.5 it has two events as you can see in the docs. Upgrading to 5.5 gives you the change to log when the email is actually send. Right now you can only log when the message is going to be send and you don't know if it's send.

Documentation: https://laravel.com/docs/5.5/mail#events

divspace's avatar

Thanks, that makes sense now. I was watching on something completely different for some reason. I can get specific parts of the email (from, to, subject, message) but just get the full raw output, which I don't want to store obviously in the audit_log table, because knowing who the user is allows me to set specific things required in the table (I can pull more info about the user, such as their ID and so on). I see the toString() function in swiftmailer\swiftmailer\lib\classes\Swift\Message.php but not sure how to extract specific data.

bobbybouwmann's avatar

With the toString method I meant if you pass it to the log message it will convert the object to a string and log that for you. This means you have the full object in your audit_log table. However it's recommended to only log the important things. For example the to, subject etc. You don't need the full email. You can determine what email was sent based on the subject and so on.

You can also build a mailer class that will send the email for you and fire of your own event with listener (or just log it there). You can then log the name of the view and the passed data to the email as well. Let me know if you need some kind of example ;)

Anyway Happy New Year and a 2018 full of Laravel :D

divspace's avatar

Actually, yes, I do need some kind of example.

I registered Laravel's MessageSending in the EventServiceProvider and point it to Listeners\AuditLog\LogSentMessage where I have access to the $event->message but need to see how to pull the individual data.

Here's my EventServiceProvider:

'Illuminate\Mail\Events\MessageSending' => [
    'App\Listeners\AuditLog\LogSentMessage',
],

And here's my LogSentMessage:

<?php

namespace App\Listeners\AuditLog;

use Illuminate\Support\Facades\Log;

class LogSentMessage
{
    /**
     * Handle the event.
     *
     * @param  Illuminate\Mail\Events\MessageSending $event
     * @return void
     */
    public function handle($event)
    {
        Log::info($event->message);
    }
}

For now I'm just logging it so I can see the output, but would be saving this to the audit_logs table with the log type (email in this case) user's ID, IP address, User Agent, and then store the relevant information as a JSON object (because I track so much other information it really only records the "thing/person" that performed the action (if any) and what they performed it on (if any), and any additional information goes in a properties column so I can filter the output on the Audit Log page by log type (e.g. user, invitation, order, queue, etc.) which is handled by Vue.

Thanks so much for your help, and Happy New Years!

Edit: Actually, I got it figured out, didn't realize you could do things like:

$event->message->getSubject();
$event->message->getBody();
$event->message->getHeaders();
4 likes
carlospc's avatar

This is just the example that I needed. Thank you very much for posting it.

mary_anne's avatar

@djokic_kg How can I modify the body? Like every other thing is saving in the table but not the body. Is there any way to fix this?

Please or to participate in this conversation.