-
Notifications
You must be signed in to change notification settings - Fork 11.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[9.x] Improve file attachment for mail and notifications #42563
Conversation
Looks like there are some tests failing on |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like a great addition to the mail component 👍
I think the Attachment class can definitely live in the Mail namespace.
@timacdonald I think this looks good so far! Feel free to continue with embeds. Marking back to draft for now while that is being worked on. |
This one is now ready to roll with embeds for all mail types. |
@timacdonald how does this embed stuff actually work? Normally I think of embeds as being in the message itself? For instance, where is this actually "embedding" the attachment in the message? |
@taylorotwell got that addressed. I misunderstood how the embed worked under the hood - the implementation was incorrect. Got it sorted now. This email view... <strong>BEFORE</strong>
<img src="{{
$message->embed(
Attachment::fromData(
fn () => file_get_contents('https://pbs.twimg.com/profile_images/1495883253445959681/xLo3tosq_400x400.jpg'),
'tim'
)->withMime('image/png')
)
}}" title="Expected title content" style="border-radius: 999px;">
<strong>AFTER</strong> Renders inline as expected... In an actual app, this would of course be written more like.... <img src="{{ $message->embed($user) }}"> assuming that |
Purpose
This PR aims to bring the concept of an "Attachable" for re-use of attaching files to a mail or other notification-like resources. It also standardises the attachable features across:
Illuminate/Mail/Mailable
Illuminate/Mail/Message
Illuminate/Notifications/Messages/MailMessage
which is currently inconsistent, with
Mailable
supporting attaching from storage, while the others do not.Why this feature is useful
Often in applications you have a model or POPO that represents a "file" that you attach to a notification. The best of example of this is the ever classic example of an
Invoice
. You may have in invoice model in your system that has an associated PDF that you attach to notifications.There may be several emails that you want the invoice attached to, and what's more is you might have some extra logic involved in retrieving the invoice before attaching to an email.
Currently we can attach files to an email in the following ways...
When you then implement another email that sends this same file, you may then find yourself duplicating this code or reaching for the docs to remember how the APIs work, etc.
This PR aims to improve experience of attaching files to an email or other notification system.
Usage
There is now an new contract called
Illumiante\Contracts\Mail\Attachable
that is meant for your model and a newIlluminate\Mail\Attachment
class that you return from the contract method.You can specify how you want the attachment to be attached to you mail / notification...
Then to attach the invoice to a built in mailable resource the following API is used...
It is also possible to set the filename or mine from within the mailable itself, if that is wanted...
Mutiple attachments
Sometimes your model may several attachments. No troubles...
it is also possible to just use the attachment class right inline while attaching to a
Mail\Mailable
,Mail\Message
, andNotification\Messages\MailMessage
, with the latter two now being able to utilise the storage machanism.General API for 3rd parties
This new class has two ways of attaching data. By referencing a path or by supplying a Cloure that resolves a string of data. All APIs are just wrappers around these two features.
Third party packages that want to integrate with this class may specify how they want to handle an attachment. They must specify both a handler for a path based resource and a data based resource.
You can see that the
$data
is not eagerly resolved, allowing the integration to decide when they want to resolve the data - which is useful for delaying the resolution from storage etc, which is how the current mail system works.Extending the dev facing API
The attachment class is also Macroable, so it is possible to create nice named constructors from 3rd party libraries...
Or even just a more generic way of retrieving from a public API...
Notes
Mail
namespace, but as shown above it is kinda just generic "Notification". I'm happy to move it to theNotifications
namespace if we feel that is a better fit.fromPath
andfromData
APIs so that everything at the end of the day results in afromData
. This would simplify the integration as well, as you no longer have to handle both the "Path" and "Data" based attachments. The reason I didn't opt for a simplefile_get_contents
is that the Symfony mailer is doing a heap under the hood that I didn't want to have to replicate, so we continue to have two APIs - just like we currently do.Mailable
andNotifications/Messages/MailMessage
which do not currently support inline embeds as a first class feature.