6

Is there a way to pass a callback function to Laravel's mailer?

I'm using the Mail facade with a mailable class, which is sending out an attachment. I would like to delete the attached file form storage once the email is sent.

The email job is being queue

Mail::to($user)->send(new MyMailable($file));

I wasn't able to use the Mailer fired event (https://laravel.com/docs/5.4/mail#events). One reason, because the event happens before the email is sent, meaning I wouldn't be able to delete the file at that moment, or the message won't have the attachment. Second, the application has multiple email jobs, some where the attachment must be deleted, and others where it won't be. The event data has the swiftmailer instance only, with no extra information about the job itself (data in mailable for ex.).

crabbly
  • 5,106
  • 1
  • 23
  • 46

1 Answers1

3

Laravel fires off an event right when the email is being sent. This does not mean that the message was queued, or that the user received it, but that it is sent.

Pop open your EventServiceProvider and add the following to the $listen array:

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

Then in the public function handle() method of the HandleSentMessage listener, accept the MessageSending $event as the first argument, such as:

public function handle(MessageSending $event) {
    //do whatever with the event data
}
Ohgodwhy
  • 49,779
  • 11
  • 80
  • 110
  • Hey @Ohgodwhy. I just updated the question explaining why the fired event won't work. Maybe I'm missing something though. Thx for your help. – crabbly May 31 '17 at 19:31
  • @crabbly hmm. I see. this is a more difficult case than originally presumed given that there is no event to be fired after the mail is sent. This is because of the way that mail transport works inherently. I think you may need to customize a solution for this. – Ohgodwhy May 31 '17 at 20:21
  • @crabbly Actually, I think the best thing to do is store the email send event in the database, with an `expiry` period of 24 hours after sending. Then scheduled a task to run hourly, loop the table where the event was stored, and after 24 hours, delete it (unless, the do_not_delete flag i set to 1 in the column). Something like that should do for you. – Ohgodwhy May 31 '17 at 20:24
  • Yea, I decided to store these "temporary" files into a specific folder, and have a daily schedule task which will clean this folder deleting the "expired" files. Thx for the feedback. – crabbly May 31 '17 at 22:37
  • actually, in my case was easier to just create a queue job, which will then send the mail (no longer queue). Inside that job. Since the mail is no longer queue, I could then wait for the mail to be sent and delete the file after. – crabbly May 31 '17 at 23:45
  • @crabbly Sure, that's another option! – Ohgodwhy Jun 01 '17 at 05:51