Advanced usage for PHP devs
On this page:
- Throttling sends
-
Handling events
- Spatie\Mailcoach\Domain\Audience\Events\SubscribedEvent
- Spatie\Mailcoach\Domain\Audience\Events\UnconfirmedSubscriberCreatedEvent
- Spatie\Mailcoach\Domain\Audience\Events\UnsubscribedEvent
- Spatie\Mailcoach\Domain\Campaign\Events\CampaignSentEvent
- Spatie\Mailcoach\Domain\Campaign\Events\CampaignMailSentEvent
- Spatie\Mailcoach\Domain\Campaign\Events\CampaignOpenedEvent
- Spatie\Mailcoach\Domain\Campaign\Events\CampaignLinkClickedEvent
- Spatie\Mailcoach\Domain\Campaign\Events\CampaignStatisticsCalculatedEvent
- Spatie\Mailcoach\Domain\Campaign\Events\BounceRegisteredEvent
- Spatie\Mailcoach\Domain\Audience\Events\ComplaintRegisteredEvent
- Spatie\Mailcoach\Domain\Audience\Events\TagAddedEvent
- Spatie\Mailcoach\Domain\Audience\Events\TagRemovedEvent
- Spatie\Mailcoach\Domain\Automation\Events\AutomationMailLinkClickedEvent
- Spatie\Mailcoach\Domain\Automation\Events\AutomationMailOpenedEvent
- Spatie\Mailcoach\Domain\Automation\Events\AutomationMailSentEvent
- Spatie\Mailcoach\Domain\Automation\Events\AutomationMailStatisticsCalculatedEvent
- Spatie\Mailcoach\Domain\Campaign\Events\WebhookCallProcessedEvent
- Spatie\Mailcoach\Domain\TransactionalMail\Events\TransactionalMailLinkClickedEvent
- Spatie\Mailcoach\Domain\TransactionalMail\Events\TransactionalMailOpenedEvent
- Spatie\Mailcoach\Domain\TransactionalMail\Events\TransactionalMailStored
- Custom authorization policies
- Manually handling feedback
- Bring your own editor
Throttling sends
Most email providers have a limit on how many emails you can send within a given amount of time. By default, five mails per second will be sent. You can add throttling config to your mailer:
// config/mail.php 'mailers' => [ 'ses' => [ 'transport' => 'ses', // Throttling for 10 mails / second 'timespan_in_seconds' => 1, 'mails_per_timespan' => 10, ], ]
Handling events
This package fires several events. You can listen for them firing to perform extra logic.
Spatie\Mailcoach\Domain\Audience\Events\SubscribedEvent
This event will be fired as soon as someone subscribes. If double opt-in is enabled on the email list someone is in the process of subscribing to, this event will be fired when the subscription is confirmed.
The event has one public property: $subscriber
which is an instance of Spatie\Mailcoach\Models\Subscriber
.
You can get the email address of the subscriber like this:
$email = $event->subscriber->email;
This is how to get the name of the email list:
$nameOfEmailList = $event->subscriber->emailList->name;
Spatie\Mailcoach\Domain\Audience\Events\UnconfirmedSubscriberCreatedEvent
This event will fire after a new email address is added to an email list that requires confirmation.
It has one public property: subscriber
.
Spatie\Mailcoach\Domain\Audience\Events\UnsubscribedEvent
This event will be fired as soon as someone unsubscribes. When somebody unsubscribes, the subscription won’t be deleted, but its status
attribute will be set to unsubscribed
.
The event has two public properties:
-
$subscriber
which is an instance ofSpatie\Mailcoach\Models\Subscriber
. -
$send
an instance ofSpatie\Mailcoach\Models\Send
. You can use this to determine in which campaign the unsubscribe occurred:$send->campaign
.
You can get the email address of the subscriber like this:
$email = $event->subscriber->email;
This is how to get the name of the email list:
$nameOfEmailList = $event->send->campaign->emailList->name;
Spatie\Mailcoach\Domain\Campaign\Events\CampaignSentEvent
This event will be fired after you’ve sent a campaign, and all mails are queued to be sent. Keep in mind that not all your subscribers will have gotten your mail when this event is fired.
The event has one public property: $campaign
, which is an instance of the \Spatie\Mailcoach\Models\Campaign
model.
Spatie\Mailcoach\Domain\Campaign\Events\CampaignMailSentEvent
This event will be fired when a mail has actually been sent to a single subscriber.
The event has one public property: $send
which is an instance of the Spatie\Mailcoach\Models\Send
model.
You can get the email the mail was sent to like this:
$email = $event->send->subscription->subscriber->email;
You can also retrieve the name of the campaign that this mail was part of:
$campaignName = $event->send->campaign->name;
Spatie\Mailcoach\Domain\Campaign\Events\CampaignOpenedEvent
This event will be fired when somebody opens an email. Be aware that this event could be fired many times after sending a campaign to a email list with a large number of subscribers. This event will only be fired for campaigns that have open tracking enabled.
It has one public property: $campaignOpen
, which is an instance of the Spatie\Mailcoach\Models\CampaignOpen
model.
You can get the email address that opened your email like this:
$email = $event->campaignOpen->subscriber->email;
This is how you can get to the name of the campaign:
$name = $event->campaignOpen->campaign->name;
Spatie\Mailcoach\Domain\Campaign\Events\CampaignLinkClickedEvent
This event will be fired when somebody clicks a link in a mail. This event will only be fired for campaigns that have click tracking enabled.
It has one public property $campaignClick
, which is an instance of the Spatie\Mailcoach\Models\CampaignClick
model.
You can get to the url of the link clicked like this:
$url = $event->campaignClick->link->original_link;
The email address of the subscriber who clicked the link can be retrieved like this:
$email = $event->campaignClick->subscriber->email;
Spatie\Mailcoach\Domain\Campaign\Events\CampaignStatisticsCalculatedEvent
After a campaign has been sent, statistics will be calculated according to a schedule.
Each time the statistics are calculated this event will be fired. It has one public property $campaign
, which is an instance of the Spatie\Mailcoach\Models\Campaign
model.
Spatie\Mailcoach\Domain\Campaign\Events\BounceRegisteredEvent
This event will fire when a complaint has bounced hard.
The event has one public property: $send
which is an instance of the Spatie\Mailcoach\Models\Send
model.
You can get the email the mail was sent to like this:
$email = $event->send->subscriber->email;
You can also retrieve the name of the campaign that this mail was part of:
$campaignName = $event->send->campaign->name;
Spatie\Mailcoach\Domain\Audience\Events\ComplaintRegisteredEvent
This event will fire when a complaint has been received about a sent mail. In many cases this means that the receiver marked it as spam.
The event has one public property: $send
which is an instance of the Spatie\Mailcoach\Models\Send
model.
You can get the email the mail was sent to like this:
$email = $event->send->subscription->subscriber->email;
You can also retrieve the name of the campaign that this mail was part of:
$campaignName = $event->send->campaign->name;
Spatie\Mailcoach\Domain\Audience\Events\TagAddedEvent
Spatie\Mailcoach\Domain\Audience\Events\TagRemovedEvent
Spatie\Mailcoach\Domain\Automation\Events\AutomationMailLinkClickedEvent
Spatie\Mailcoach\Domain\Automation\Events\AutomationMailOpenedEvent
Spatie\Mailcoach\Domain\Automation\Events\AutomationMailSentEvent
Spatie\Mailcoach\Domain\Automation\Events\AutomationMailStatisticsCalculatedEvent
Spatie\Mailcoach\Domain\Campaign\Events\WebhookCallProcessedEvent
Spatie\Mailcoach\Domain\TransactionalMail\Events\TransactionalMailLinkClickedEvent
Spatie\Mailcoach\Domain\TransactionalMail\Events\TransactionalMailOpenedEvent
Spatie\Mailcoach\Domain\TransactionalMail\Events\TransactionalMailStored
Custom authorization policies
By default, all Mailcoach backend and API actions are protected by the “viewMailcoach” gate. If this is
sufficient for your use case, then no further action is required. However, you may need more fine-grained
authorization logic to govern access to different Mailcoach features. In that case, you can create custom
authorization policies.
Policies are resolved via the Laravel service container, so swapping out a default policy for
one of your own is as simple as binding it in a service provider:
use Spatie\Mailcoach\Domain\Audience\Policies\EmailListPolicy; ... public function register() { app()->bind(EmailListPolicy::class, MyFancyCustomListPolicy::class); } ...
Policies are currently supported for the following model/action combinations:
- EmailList
- “viewAny”
- “create”
- “view”
- “update”
- “delete”
- Campaign
- “viewAny”
- “create”
- “view”
- “update”
- “delete”
- Template
- “viewAny”
- “create”
- “view”
- “update”
- “delete”
Manually handling feedback
After a mail is sent, most email providers send feedback on the result.
You can also manually handle feedback.
First you must add a transport id to a Send
model. Here’s an example listener:
class StoreTransportMessageId { public function handle(MessageSent $event) { if (! isset($event->data['send'])) { return; } /** @var \Spatie\Mailcoach\Models\Send $send */ $send = $event->data['send']; $transportMessageId = $event->message->getHeaders()->get('header-name-used-by-your-email-provider')->bodyAsString(); $send->storeTransportMessageId($transportMessageId); } }
You must register that listener. A typical place would be in a service provider.
Event::listen(Illuminate\Mail\Events\MessageSent::class, StoreTransportMessageId::class);
Next, in the code that handles feedback you can get to the MailSend
like this:
$send = Send::findByTransportMessageId($messageId);
You can mark a send as bounced.
$send->markAsBounced(SendBounceSeverity::PERMANENT);
When a Send
is marked as permanently bounced, the subscriber will get unsubscribed from the email list.
Bring your own editor
If you’ve installed Mailcoach in an existing Laravel app, you can add support for any editor you’d like.
An Editor
is a simple PHP class that implements the \Spatie\Mailcoach\Support\Editor\Editor
interface.
It requires that you implement a render()
function that accepts a \Spatie\Mailcoach\Models\Concerns\HasHtmlContent
object, this is a model that has 2 methods on it.
You can use the default \Spatie\Mailcoach\Support\Editor\TextEditor
implementation as a reference
public function render(HasHtmlContent $model): string { return view('mailcoach::app.campaigns.draft.textEditor', [ 'html' => $model->getHtml(), ])->render(); }
This renders the textEditor.blade.php
view of Mailcoach that makes heavy use of Blade Components.
This view will be rendered inside the forms of Campaigns and Templates, the only thing we require is that the Editor
passes valid html through an input with the name html
.
Mailcoach provides a secondary structured_html
field in which you can pass anything your Editor
needs to rebuild its view (our Unlayer editor uses this field to store the Unlayer specific JSON format).