Search code examples
laravelnotificationsschedulemailmessage

Notification Images cannot be found when triggered by an command/schedule


When I trigger a notification via a controller the MailMessage sends with no issue, all imaged contained.

However when the same notification is triggered via a schedule item that calls a console command the images cannot be found.


Solution

  • You haven't shown any code, but I have been bitten by something similar also so I think I know what you are talking about.

    If your APP_URL includes a directory (eg http://localhost/myproject), and you use asset() to reference images in your views, the generated references will work fine when the view is generated from a browser request, but not from a queue, a scheduled job, or from CLI in general. From the CLI, the directory part of your APP_URL is lost in the generated references, and your images will be broken.

    This is a known problem in Laravel that comes from Symfony. It looks like it has just been fixed, a month ago: https://github.com/laravel/framework/issues/14139

    UPDATE

    Here's a concrete example of the issue. I'm using Laravel 5.2 (though according to the issue above it was fixed in 5.4 at the end of August, so appears right up to recent versions) and sending a transactional email when a user does something on the site. I updated my email view to dump out some values.

    Browser request, real-time mail, with Mail::send(), and QUEUE_DRIVER=sync:

    env('APP_URL')           http://localhost/myproject                 // OK
    config('app.url')        http://localhost/myproject                 // OK
    asset('/images/foo.png') http://localhost/myproject/images/foo.png  // OK 
    

    These values are all correct, and the URLs generated by asset() shows my email images correctly.

    CLI request, queued mail, with Mail::queue(), and QUEUE_DRIVER=database:

    env('APP_URL')           http://localhost/myproject                 // OK
    config('app.url')        http://localhost/myproject                 // OK
    asset('/images/foo.png') http://localhost/images/foo.png            // xxxx
    

    Note myproject/ is missing from the URL generated by asset(). All images references in my email are broken, images don't show up.

    Short of upgrading to a version of Laravel where this is fixed, all you can do is not use asset() in any view that will be generated from CLI, and instead manually specify asset paths:

    config('app.url') . '/images/' . $product->image
    

    Side note - as @Desh901 pointed out in the comments, env() should never be used outside of config files:

    If you execute the config:cache command during your deployment process, you should be sure that you are only calling the env function from within your configuration files.