23

Laravel 5.3 introduces a new service called notifications, allowing the construct of emails (among other notifications) via a simple fluent syntax:

    return (new MailMessage)
            ->greeting('Hello!')
            ->line('One of your invoices has been paid!')
            ->action('View Invoice', $url)
            ->line('Thank you for using our application!');

What is an eloquent approach to adding images to the email notifications? I have already published the vendor files to modify the base template.

My thoughts currently stand at:

  • Extend Illuminate\Notifications\Messages\SimpleMessage as a new local class, along the lines of SimpleMediaMessage with a few additional methods (example: ->image(src, url, alt))
  • Modify the base template (or create one specific to SimpleMediaMessage that loops over the media array built up via ->image
  • Finally, register a custom channel to allow notifications to deliver notifications with images.

This seems quite heavy handed for something as simple as images in email. Am I missing something? Is there a better approach?

Edited for clarity

When I refer to images, I mean banner and trail images that are visible in the message itself (not as a seperate attachment).

The attached image shows a) in red what can be currently achieved, and b) in purple what I am looking for.

enter image description here

Second edit

Re-reading the answers posted so far, especially @Erics, I see that with a very simple modification to the template, you can in fact do the following:

->line("<img src='foo.example/bar.jpg' />")

The template needs to be modified to allow unsafe markup:

// Note this is in two spots - intro + outro
{{ $line }} --> becomes --> {!! $line !!} 

Disadvantages to this method:

  1. Possibly opening up a security issue, the whole reason of using {{}} over {!!!!}
  2. The image can't take advantage of the inline styles, unless you do it outside the email template, for example:

    ->line(" < img style='max-width:570px;/* all the other junk to make images look ok in email */' src='foo.example.bar.jpg' /> ")

Chris
  • 54,599
  • 30
  • 149
  • 186

3 Answers3

12

How are you wanting to attach? In emails you can reference the full path and just add it to the view in typical HTML format:

<img src="http://yoursite.com/path/to/image.png">

If you want to make it a real file attachment there is both an ->attach() and attachData method on the MailMessage. These are typically used for things like PDF's or document attachments.

If you want to attach and reference the attachment in the source then I'm guessing you will need to extend the class like you mentioned or fallback to Laravel's Mail::send method.

Since the notification system was designed to be simple and opinionated I imagine they wanted to cover the common use cases and it's much simpler to use full paths to images versus referencing the cid: style.

Community
  • 1
  • 1
Eric
  • 1,197
  • 9
  • 18
  • Good pick up - I have editted in an example image to the original question. Full path is the intention - my understanding is that gives the best coverage for the various mail clients. Agree with the opinionated, and thats fine, but most transactional email I receive (and intend on sending) relies on imagery to convey part of the message - largely because email client functionality is soooo limited. – Chris Oct 20 '16 at 00:51
  • 1
    Thanks @Eric. Just want to note, that although this works, you need to slightly modify the template to be `{!! !!}` instead of `{{ }}`. Whether this is a risk or not is up to you and your project – Chris Oct 29 '16 at 08:41
  • @Eric, It seems you master laravel. I need you help. Look here : http://stackoverflow.com/questions/41887504/how-to-solve-missing-argument-1-for-app-repositories-favoriterepositorydelete/41887543 – moses toh Jan 27 '17 at 06:43
0

As you can see in Mail/resources/html/layout.blade.php, Laravel uses the Markdown notation:

{{ Illuminate\Mail\Markdown::parse($slot) }}

So you can format insert an image using line() method with a code like this:

->line('![your_text](https://image_address);

lluisma
  • 101
  • 1
  • 6
0

If you don't want to modify the template, but want to include an image (or other arbitrary HTML), you can use the HtmlString helper:

use Illuminate\Support\HtmlString;

[...]

return (new MailMessage)
   ->line(new HtmlString('<img src="https://example.com/image.webp">'));
Ari Cooper-Davis
  • 3,374
  • 3
  • 26
  • 43