Oh Dear is the all-in-one monitoring tool for your entire website. We monitor uptime, SSL certificates, broken links, scheduled tasks and more. You'll get a notifications for us when something's wrong. All that paired with a developer friendly API and kick-ass documentation. O, and you'll also be able to create a public status page under a minute. Start monitoring using our free trial now.

Mailcoach v2 has been released with support for custom HTML editors and multiple mailers

Original – by Freek Van der Herten – 9 minute read

A couple of months ago, my team released Mailcoach, a self-hosted solution to send out newsletters. It sends out mail via services like Amazon SES, Mailgun, Sendgrid, and Postmark. It can optionally track opens and clicks. When your email list grows, this is a much more cost-effective solution when compared to a service like Mailchimp.

Mailcoach can be used as a premium Laravel package or as a stand-alone app. When installed into a Laravel app, it can be greatly customized. The Mailcoach stand alone app can be used without knowing how to program.

Today we're releasing v2 of Mailcoach. It offers support for Laravel 7, html editors, and multiple mailers, together with a bunch of quality of life improvements. In this blog post, I'd like to walk you through these features and show some technical details.

If you already bought Mailcoach, you'll be happy to know that this is a free upgrade.

Introducing Mailcoach

If you're not familiar with Mailcoach yet, you can watch this video to see the core features in action.

Mailcoach intro from Spatie on Vimeo.

Support for custom HTML editors

By default, Mailcoach uses a plain text area field to edit campaigns and tables. One of the most requested features after launching Mailcoach v1, was support for an HTML editor.

Unlayer, an easy to use HTML editor

In Mailcoach v2 we've added the ability to install editors via add on packages, so you can bring any editor you like. We've created two add-on packages ourselves. The first one brings the free version of Unlayer, a powerful WYSIWYG HTML editor to Mailcoach.

image of unlayer

When using this editor, you don't need any knowledge of HTML to compose your campaign. It also can handle image uploads. Any uploads will be handled by our laravel-medialibrary package, but users don't need to care about that, it all happens behind the scenes.

Installing the Unlayer editor in Mailcoach is easy. You just have to require the add on package.

composer require spatie/laravel-mailcoach-unlayer

Next, you'll have to run the migration provided by the package, add the route macro, and set the editor key in the mailcoach.app config file to \Spatie\MailcoachUnlayer\UnlayerEditor::class. If you're familiar with adding packages to a Laravel app, this shouldn't take you long.

Monaco, a powerful code editor

Monaco is a powerful code editor created by Microsoft. It provides code highlighting, auto-completion, and much more.

image of monaco editor

Installing this package is dead simple too. Just require the package...

composer require spatie/laravel-mailcoach-monaco

Install the assets...

php artisan vendor:publish --tag mailcoach-monaco-assets --force

Set the editor in the mailcoach.app config file...

'editor' => \Spatie\MailcoachMonaco\MonacoEditor::class,

And you're good to go!

Optionally, you can customize the looks of Monaco by specifying some options in the monaco key of the mailcoach.php config file.

'monaco' => [
    'theme' => 'vs-light', // vs-light or vs-dark
    'fontFamily' => 'Jetbrains Mono',
    'fontLigatures' => true,
    'fontWeight' => 400,
    'fontSize' => '16', // No units
    'lineHeight' => '24' // No units
],

When using Mailcoach as a stand-alone app, you can configure these options on the editor screen.

image of monaco editor settings

How editors are implemented in Mailcoach

By default, Mailcoach displays a plain text area field to edit campaigns and templates. Let's take a look at how that is implemented.

image of textarea

In Mailcoach, you must specify the class name of an editor in the editor config key of the mailcoach.app config file. By default, Spatie\Mailcoach\Support\Editor\TextEditor::class is used. Let's take a look at that class.

namespace Spatie\Mailcoach\Support\Editor;

use Spatie\Mailcoach\Models\Concerns\HasHtmlContent;

class TextEditor implements Editor
{
    public function render(HasHtmlContent $model): string
    {
        return view('mailcoach::app.campaigns.draft.textEditor', [
            'html' => $model->getHtml(),
        ])->render();
    }
}

As you can see, it's quite simple. We just call getHtml on the $model (which can be a campaign or a template)`, give that to a view and return the rendered view.

Here's the context of that textEditor view.

<div>
    <x-html-field label="Body (HTML)" name="html" :value="old('html', $html)"></x-html-field>
</div>

<div class="form-buttons">
    <button id="save" type="submit" class="button">
        <x-icon-label icon="fa-code" text="Save content"/>
    </button>

    <button type="button" class="link-icon" data-modal-trigger="preview">
        <x-icon-label icon="fa-eye" text="Preview"/>
    </button>
    <x-modal title="Preview" name="preview" large>
        <iframe class="absolute" width="100%" height="100%" data-html-preview-target></iframe>
    </x-modal>
</div>

<x-replacer-help-texts />

Using the new Blade components introduced in Laravel 7, we render the x-HTML-field (which is a textarea), and some buttons to submit and preview the content.

Now we only have the rendered editor, let's see how it is rendered in a form. This is the content of the content.blade.view, which renders the entire view you see in the screenshot above.

@extends('mailcoach::app.campaigns.draft.layouts.edit', [
    'campaign' => $campaign,
    'titlePrefix' => 'HTML',
])

@section('breadcrumbs')
    <li>
        <a href="{{ route('mailcoach.campaigns.settings', $campaign) }}">
            <span class="breadcrumb">{{ $campaign->name }}</span>
        </a>
    </li>
    <li><span class="breadcrumb">Content</span></li>
@endsection

@section('campaign')
    <form
        class="form-grid"
        action="{{ route('mailcoach.campaigns.updateContent', $campaign) }}"
        method="POST"
        data-dirty-check
    >
        @csrf
        @method('PUT')
        {!! app(config('mailcoach.editor'))->render($campaign) !!}
    </form>
@endsection

The important line is the one with app(config('mailcoach.editor'))->render($campaign). As you can see, we simply get the class name of the configured editor, instantiate it, and render it.

This all makes creating support for another editor is rather straightforward. You should have to create a class, let it implement Spatie\Mailcoach\Models\Concerns\HasHtmlContent interface, and specify its fully qualified class name to the config. And that is exactly what our add on packages are doing. Here's the code of the MonacoEditor class in the laravel-mailcoach-monaco package.

namespace Spatie\MailcoachMonaco;

use Spatie\Mailcoach\Models\Concerns\HasHtmlContent;
use Spatie\Mailcoach\Support\Editor\Editor;

class MonacoEditor implements Editor
{
    public function render(HasHtmlContent $model): string
    {
        return view('mailcoach-monaco::editor', [
            'html' => $model->getHtml(),
        ])->render();
    }
}

The JavaScript side of the setup happens in the mailcoach-monaco::editor view. An interesting note is that we use the @push blade directive to add a script to the endHead stack of the Mailcoach layout view.

Using multiple mailers

Some email providers have very strict rules on sending mails. They require to keep a low bounce rate at all times. Confirmation emails have a higher chance of bouncing because they are sent to unverified email addresses.

Mailcoach v1 was built on Laravel v6. In that version of the framework, you could only define one mailer. In Laravel v7 support for multiple mailers was introduced. Mailcoach makes use of that feature to allow confirmation mails to be sent using a different mailer.

In the mailcoach.php config file, there are a couple of values that govern which mailer should be used.

return [

    /*
     * The mailer used by Mailcoach for password resets and summary emails.
     * Mailcoach will use the default Laravel mailer if this is not set.
     */
    'mailer' => null,

    /*
     * The default mailer used by Mailcoach for sending campaigns.
     */
    'campaign_mailer' => null,

    /*
     * The default mailer used by Mailcoach for confirmation and welcome mails.
     */
    'transactional_mailer' => null,
    
    // ...
];

On the settings screen of an email list, you can also specify which mailer should be used for that particular list.

Building Mailcoach

While building Mailcoach, I've recorded a video course on how to use Mailcoach, and how it was built. You can use these techniques to improve your projects as well. I've made a couple of videos available for free.

When creating a function, it's a good idea to keep the number of arguments as low as possible. In this video, you'll learn a technique on how to do this.

Most developers have probably have seen complex conditionals in legacy code. In this video, I show you how to refactor those.

Want to see more videos like this? Then head over to the video course page on Mailcoach.

Even if you don't require a self-hosted email solution, you could still benefit from purchasing it. Mailcoach is a labor of love, and our team polished it a lot. You can probably learn some nice things and pick up some tricks by reading the source code. The test suite of Mailcoach has been opensource, you can view it in this repo on GitHub.

In closing

Mailcoach v2 has a few smaller new features too, such as adding a delay for a welcome mail, some new customization options when sending mail, support for the latest version of laravel-medialibrary, support for Postmark ...

I'd like to thank my colleague Rias, who has done a lot getting v2 ready.

If you want to know more about Mailcoach, check out the extensive documentation. If you like what you see, consider getting your license.

Here are some more blog posts on Mailcoach

Mailcoach is probably the best package I've worked on. I use it myself to send my own newsletter. I hope you'll like it too!

Stay up to date with all things Laravel, PHP, and JavaScript.

You can follow me on these platforms:

On all these platforms, regularly share programming tips, and what I myself have learned in ongoing projects.

Every month I send out a newsletter containing lots of interesting stuff for the modern PHP developer.

Expect quick tips & tricks, interesting tutorials, opinions and packages. Because I work with Laravel every day there is an emphasis on that framework.

Rest assured that I will only use your email address to send you the newsletter and will not use it for any other purposes.

Comments

Minda Molina avatar

I appreciate the solutions you've come up with for Mailcoach space waves

Comments powered by Laravel Comments
Want to join the conversation? Log in or create an account to post a comment.