Photo by Kelly Sikkema on Unsplash
Global Tags and Metadata on Laravel Mailables
Adding site specific tags or meta-data to all mailables
Laravel mailables have a nice interface for consistently structuring an email for any of their supported drivers.
As I'm often working with Mailgun I like Laravels support for tags and metadata which lets you add additional metadata to a message for easier filtering inside mailgun:
//Inside your mailable class
public function envelope(): Envelope
{
return new Envelope(
subject: 'Testing Tags',
tags: ['mail-1', 'mail-2'],
metadata: [
'type' => 'from-envelope',
],
);
}
That's great for mail-specific tags, but if you are sharing one sending address between multiple apps and have a lot of mail and notifications it can be handy to tag all messages out of a specific site with a globally added metadata to separate the sending application.
There's no obvious way to do this, but after a bit of source diving into the base Laravel and Symfony classes I've found a reasonable solution:
//In AppServiceProvider boot(), or in a custom service provider
Event::listen(MessageSending::class, function (MessageSending $event) {
if ($tag = config('mail.tag')) {
$event->message->getHeaders()->add(new TagHeader($tag));
}
if ($metadata = config('mail.metadata')) {
foreach ($metadata as $key => $value) {
if ($value) {
$event->message->getHeaders()->add(new MetadataHeader($key, $value));
}
}
}
});
This hooks into all messages as they are being sent and adds any tags or metadata added inside config/mail.php as a tag string and an array of metadata key/values:
//config.mail.php
'tag' => 'global-1',
'metadata' => [
'site' => env('APP_NAME'),
'environment' => env('APP_ENV'),
],
This will merge with the tags and metadata from the envelope so the finished result gives you this in the final mail headers:
X-Metadata-Environment | local |
X-Metadata-Site | (Site Name) |
X-Metadata-Type | from-envelope |
X-Tag | mail-1 |
mail-2 | |
global-1 |
Notes:
With Mailgun a single message can only have up to 3 tags, so avoid adding more than two tags in any template if you use this system
This same technique can be used to add global SES tags to Laravel mails, but you need to use the metadata method for SES tags.
Test before use! Causing an error in the sending event will mean no mails will be able to send!