Transactional mails

On this page:

In this section you’ll learn how to programmatically work with transactional emails.

Logging transactional mails

Mailcoach can store transactional mails, record any opens and clicks, and even resend them.

Getting started

To work with transactional mails in Mailcoach, you should use
Spatie\Mailcoach\Domain\TransactionalMail\Mails\Concerns\StoresMail trait on your Mailable class.

Storing mails

In the
content function of your mailable, you should call the store method provided by the trait.

use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Spatie\Mailcoach\Domain\TransactionalMail\Mails\Concerns\StoresMail;

class YourMailable extends Mailable
{
    use StoresMail;

    public function envelope(): Envelope
    {
        return new Envelope(
            subject: 'Your order has been shipped!'
        );
    }
    
    public function content(): Content
    {
        $this->store();
    
        return new Content(
            markdown: 'mails.orderShipped'
        );
    }
}

If you’re using build in your mailable, you can also the store method provided by the trait like this.

class YourMailable extends Mailable
{
    use StoresMail;

    public function build()
    {
        $this
            ->store()
            ->view('mails.your-mailable')
    }
}

Whenever this mailable is sent, Mailcoach will store and display it in the UI.

Tracking opens and clicks

When enabled with your email provider, transactional mails will track opens & clicks as well.

Tracking opens and/or clicks requires Mailcoach to store the mail, so you have to call store separately.

class YourMailable extends Mailable
{
    public function content(): Content
    {
        $this->store();
    
        return new Content(
            markdown: 'mails.orderShipped'
        );
    }
}

Resending stored mails

You can resend stored transactional mails via the UI or by calling resend on the Spatie\Mailcoach\Domain\TransactionalMail\Models\TransactionalMail model

TransactionalMail::find($id)->resend();

Using templates

By defining a transactional mail template, you can let non-technical users specify the content of a transactional mail.

Getting started

To get started you should create a Spatie\Mailcoach\Domain\TransactionalMail\Models\TransactionalMailTemplate model.

Spatie\Mailcoach\Domain\TransactionalMail\Models\TransactionalMail::create([
    'name' => 'name-of-your-template',
    'type' => 'html', // this can be html, markdown or blade
    'subject' => 'The subject of your mail',
    'body' => '<html>Content of your mail</html>'
]);

After you have created this model, it will become visible in the UI of Mailcoach. Users of Mailcoach will be able to change the properties of the mail.

Next, you should create a mailable and let it use the Spatie\Mailcoach\Domain\TransactionalMail\Mails\Concerns\UsesMailcoachTemplate trait. In the content or build method of your mailable you should call the template method.

use Spatie\Mailcoach\Domain\TransactionalMail\Mails\Concerns\UsesMailcoachTemplate
use Illuminate\Mail\Mailable
use Illuminate\Mail\Mailables\Content;

class YourMailable extends Mailable
{
    use UsesMailcoachTemplate;

    public function content(): Content
    {
        $this->template('test-template');
        
        // return content;
    }

When the mailable is sent, it will use the subject and content of the TransactionalMailTemplate.

Using template types

You can use of one these types as the value of type in a TransactionalMailTemplate instance

  • html: the content of the body column will be used as is
  • markdown: you can use mark down in body column
  • blade: you can use Blade syntax in the body column. Only select this option if you trust all users of the Mailcoach UI, as arbitrary PHP in the template will be executed.

Storing and tracking open & clicks

By default, mails using templates will not be stored or tracked.

If you want to log any mail that use the template, you should set this attribute on TransactionalMailTemplate to true:

  • store_mail

Open & click tracking are configured in your email provider.

Using replacers

You can define replacers to dynamically replace content in the template. A replacer is any class that implements the Spatie\Mailcoach\Domain\TransactionalMail\Support\Replacers\TransactionalMailReplacer interface. This interface requires you to implements two methods:

  • helpText: returns the help text to be displayed in the UI
  • replace: the function that makes the replacement.

Here’s an example implementation where we will replace ::subject:: in the content of the template with the subject used on the mailable.

namespace App\Support\Replacers;

use Illuminate\Mail\Mailable;
use Spatie\Mailcoach\Domain\TransactionalMail\Models\TransactionalMail;
use Spatie\Mailcoach\Domain\TransactionalMail\Support\Replacers\TransactionalMailReplacer;

class SubjectReplacer implements TransactionalMailReplacer
{
    public function helpText(): array
    {
        return [
            'subject' => 'The subject used on the template',
        ];
    }

    public function replace(string $templateText, Mailable $mailable, TransactionalMail $template): string
    {
        return str_replace('::subject::', $mailable->subject, $templateText);
    }
}

You should register replacers in the transactional.replacers config key of the mailcoach config file. You should use array syntax: the key is the name of your replacer, the value should be the full qualified class name

// in mailcoach.php
return [
    // ...

    'transactional' => [
        /*
         * The default mailer used by Mailcoach for transactional mails.
         */
        'mailer' => null,

        /*
         * Replacers are classes that can make replacements in the body of transactional mails.
         *
         * You can use replacers to create placeholders.
         */
        'replacers' => [
            'subject' => \App\Support\Replacers\SubjectReplacer::class,
        ],
        
        // ...
    ],
];

To enable a registered replacer for a TransactionalMailTemplate, you should set the name of the replacer in the replacers column of the TransactionalMailTemplate. Use array notation to be able to specify multiple replacers.

$transactionalMailTemplate->update(['replacers' => ['subject', 'another_replacer']])
Audience