Audience

On this page:

In this section you’ll learn how to programmatically work with email lists & subscribers.

Creating a list

An email list is used to group a collection of subscribers.

You can create a new email list by newing up an EmailList. The only required field is name.

$emailList = EmailList::create(['name' => 'my email list name']);

Setting a default sender and reply to

You can set a default email address and from name.

$emailList->update([
    'default_from_email' => 'john@example.com',
    'default_from_name' => 'John Doe',
]);
$emailList->update([
    'default_reply_to_email' => 'jane@example.com',
    'default_reply_to_name' => 'Jane Doe',
]);

When sending a campaign to this email list these defaults will be used if you send a campaign that doesn’t have a from or reply to of its own.

Specifying the mailers to be used

By default, Mailcoach sends all mails using the default mailer of your Laravel app. In the mailcoach.php config file, you can override this.

At the time of creating your EmailList, the transactional_mailer, automation_mailer, and campaign_mailer attributes will be set based on your configuration settings. Any future change in your configuration settings will not automatically apply to the EmailList.

You can also override the mailer to be used on the list level by updating the campaign_mailer attribute with the mailer to be used. Confirmation and welcome mails will be sent using the mailer specified in transactional_mailer.

$emailList->update([
    'campaign_mailer' => $nameOfMailer,
    'automation_mailer' => $nameOfMailer,
    'transactional_mailer' => $nameOfAnotherMailer,
]);

Subscribing to a list

This is the easiest way to subscribe to a list:

$emailList->subscribe('john@example.com');

Alternatively you can create a subscriber via the Subscriber model.

Subscriber::createWithEmail('john@example.com')->subscribeTo($emailList);

Specifying first name and last name

There are attributes named first_name and last_name on the Subscriber model itself. When subscribing you can fill them by passing a second argument to subscribe.

$subscriber = $emailList->subscribe('john@example.com', [
    'first_name' => 'John', 
    'last_name' => 'Doe'
]);

Alternatively you can create a subscriber with attributes via the Subscriber model.

Subscriber::createWithEmail('john@example.com')
   ->withAttributes([
       'first_name' => 'John', 
       'last_name' => 'Doe'
   ])
   ->subscribeTo($emailList);

Adding regular attributes

If you need more attributes on a subscriber you can create a migration that adds a field.

Schema::table('mailcoach_subscribers', function (Blueprint $table) {
    $table->string('job_title')->nullable();
});

To fill the field just add a key to the second array passed to subscribe.

$subscriber = $emailList->subscribe('john@example.com', ['job_title' => 'Developer']);

$subscriber->job_title; // returns 'Developer'

Adding extra attributes

The email_list_subscribers table has an json field called extra_attributes. You can use this field to add unstructured data to a subscriber.

When subscribing pass unstructured data as the value of the extra_attributes key . This data will be saved in extra_attributes.

$subscriber = $emailList->subscribe('john@example.com', [
    'extra_attributes' => [
        'key 1' => 'value 1',
        'key 2' => 'value 2',
    ],
]);

$subscriber->extra_attributes->get('key 1'); // returns 'value 1';
$subscriber->extra_attributes->get('key 2'); // returns 'value 2';

You can read more on extra attributes in this section of the docs.

Checking if someone is subscribed

You can check if a given email is subscribed to an email list.

$emailList->isSubscribed('john@example.com'); // returns a boolean

You can use a subscriber to check to if it is subscribed.

$subscriber->isSubscribed() // returns a boolean;

Getting the status of a subscriber

To get the status of a subscriber

$subscriber->status;

This property can contain three possible values:

  • unconfirmed: when the list uses double opt-in and the confirmation link wasn’t clicked yet
  • subscribed: when the subscriber is subscribed.
  • unsubscribed: when the subscriber was unsubscribed.

Getting all list subscribers

To get all subscribers of an email list you can use the emailList you can call subscribers on an email list.

$subscribers = $emailList->subscribers; // returns all subscribers

To get the email address of a subscriber call email on a subscriber.

$email = $subscribers->first()->email;

Calling subscribers on an email list will only return subscribers that have a subscription with a subscribed status. Subscribers that have unsubscribed or are still unconfirmed (when using double opt-in) will not be returned.

To return all subscribers, including all unconfirmed and unsubscribed ones, use allSubscribers.

$allSubscribers = $emailList->allSubscribers;

Skipping opt in when subscribing

If double opt-in is enabled on a list, then subscribeTo won’t result in an immediate subscription. Instead, the user must first confirm, by clicking a link in a mail, before their subscription to the new list is completed.

To immediately confirm someone, and skipping sending the confirmation mail, use subscribeSkippingConfirmation:

$emailList->subscribeskippingConfirmation('john@example.com');

Alternatively you can use this syntax:

Subscriber::createWithEmail('john@example.com')
   ->skipConfirmation()
   ->subscribeTo($emailList);

Using subscription forms

You can accept email list subscriptions coming from external sites by adding a subscription form to that site.

In order to accept incoming form subscriptions you must set allow_form_subscriptions to true.

$emailList->update(['allow_form_subscriptions' => true]);

Here’s an example form you can embed on an external site to accept subscriptions.

<form method="POST" action="https://domain-where-mailcoach-runs/mailcoach/subscribe/<uuid-of-emaillist>">
    <div>
        <label for="email">Email</label>
        <input name="email">
    </div>
   <!-- optionally you can include the first_name and last_name field
    <div>
        <label for="first_name">First name</label>
        <input name="first_name">
    </div>
    <div>
        <label for="last_name">Last name</label>
        <input name="last_name">
    </div>
    -->
    <input type="hidden" name="redirect_after_subscribed" value="https://your-site/subscribed"  />
    <input type="hidden" name="redirect_after_already_subscribed" value="https://your-site/already-subscribed"  />
   <!-- only required if your list has double opt-in enabled
    <input type="hidden" name="redirect_after_subscription_pending" value="https://your-site/redirect-after-pending"  />
    -->
    <div>
       <button type="submit">Subscribe</button>    
    </div>
</form>

Attaching tags

You can specify one or more tags in an input field named tags that should be attached to the subscriber when it gets created.

<!-- somewhere in your form -->
<input type="hidden" name="tags" value="tagA;tagB">

Only tags that were added on the allowedFormSubscriptionTags relation of the email list you’re subscribing someone to will be attached. Here’s you can attach tags to that relation.

$tagA = $emailList->tags()->where('name', 'tagA')->first();
$tagB = $emailList->tags()->where('name', 'tagB')->first();

$emailList->allowedFormSubscriptionTags([$tagA->id, $tagB->id]);

A word to the wise

We highly recommend that you turn on confirmation for email lists that allow form subscriptions. This will keep your list healthy. Also consider adding a honeypot to the form to avoid bots from trying to subscribe. When using Laravel, you could opt to use the spatie/laravel-honeypot package.

Validating subscribers

When integrating this package into your app you will likely build a UI where people can subscribe to your list. This package provides a validation rule that verifies that given email address isn’t already on the given email list. You can use it like this:

// in a form request

public function rules() {
   $emailList = EmailList::first();

   return [
      'email' => ['email', new Spatie\Mailcoach\Rules\EmailListSubscriptionRule($emailList)]
   ];
}

You can customize the validation error message publishing the lang files.

php artisan vendor:publish --provider="Spatie\Mailcoach\MailcoachServiceProvider" --tag="mailcoach-translations"

You’ll find the translation files in lang/vendor/mailcoach. If you need to change the English messages, you can copy the keys from one of the other translation files.

Unsubscribing from a list

You can add an unsubscribe link by adding an {{ unsubscribeUrl }} placeholder to the HTML of your campaign.

When a subscriber visits the actual unsubscribe URL, a simple message will be displayed to confirming that they have successfully unsubscribed.

To customize this confirmation message, publish the views.

php artisan vendor:publish --provider="Spatie\Mailcoach\MailcoachServiceProvider" --tag="mailcoach-views"

Now we modify the following views in the /resources/views/vendor/mailcoach/landingPages/ directory:

  • unsubscribed.blade.php
  • couldNotFindSubscription.blade.php

Unsubscribing manually

You can also unsubscribe someone manually like this.

$emailList->unsubscribe('john@example.com');

Alternatively, you can call unsubscribe on a subscriber

Subscriber::findForEmail('john@example.com', $emailList)->unsubscribe();

Unsubscribing using an email client

Emails sent have the List-Unsubscribe header included. This allows for users to unsubscribe from their email client as per RFC2369.

Permanently deleting a subscriber

Behind the scenes, the subscriber won’t be deleted. Instead, the status of the subscription will be updated to unsubscribed.

If you want to delete the subscription/subscriber entirely, you can call delete on it.

Subscriber::findForEmail('john@example.com', $emailList)->delete();

The code above will also delete all related subscriptions.

Using double opt-in

To ensure that all subscribers of your email list really wanted to subscribe, you can enable the double opt-in requirement.

EmailList::create([
    'name' => 'My list'
    'requires_confirmation' => true,
]);

When calling subscribe on a list where requires_confirmation is enabled, a subscription will be created with a status set to unconfirmed. An email will be sent to the email address you’re subscribing. The email contains a link that, when clicked, will confirm the subscription. When a subscription is confirmed, its status will be set to subscribed.

When sending a campaign to an email list, only subscribers that have a subscription with status subscribed will receive the campaign.

To immediately subscribe someone, and skip sending a confirmation email, you can call subscribeNow on a list.

Customizing the subscription confirmation response

When a person clicks the email confirmation link, a simple message explaining the result of confirmation is displayed. You can customize that response by publishing the views.

php artisan vendor:publish --provider="Spatie\Mailcoach\MailcoachServiceProvider" --tag="mailcoach-views"

The responses of a confirmation can now be modified in the view inside the /resources/views/vendor/mailcoach/landingPages/ directory. It will contain these blade files:

  • subscribed.blade.php
  • couldNotFindSubscription.blade.php
  • alreadySubscribed.blade.php

Customizing the double opt in mail

You can customize the content of the double opt-in mail.

First, you must publish the views.

php artisan vendor:publish --provider="Spatie\Mailcoach\MailcoachServiceProvider" --tag="mailcoach-views"

After that, the content of the double opt-in mail can be modified in the /resources/views/vendor/mailcoach/mails/confirmSubscription.blade.php view.

Working with tags

A mailinglist can have one or more tags. These tags can be applied onto the subscribers of that list.

Creating and attaching tags

Here’s how you can create a tag.

$subscriber->addTag('tagA');

The tag named tagA will be created an associated with the email list of the subscriber and with the subscriber itself.

Tags can be created and associated in one go:

$subscriber->addTags(['tagB', 'tagC']);

Detaching tags

Tags can be detached.

$subscriber->removeTag('tagA');
$subscriber->removeTags(['tagA', 'tagB']);

Detaching a tags will only remove it from a subscriber. It will not be removed from the email list.

Deleting tags

To delete a certain tag from an email list, just call delete on it.

$emailList->tags()->where('name', 'tagA')->first()->delete();

Syncing tags

You can pass multiple tags names to syncTags. Tags that do not exist yet will be created. Tags that are already attached but not present in the array passed to syncTags will be detached from the subscriber.

$subscriber->syncTags(['tagA', 'tagC']);

Working with extra attributes

When subscribing you can add extra attributes. Here’s an example where first_name and last_name are added.

$subscription = $emailList->subscribe('john@example.com', [
    'first_name' => 'John',
    'last_name' => 'Doe'
]);

When you are adding subscribers from an external form, you can also add extra attributes by using a specific input name pattern attributes['name-of-your-new-attribute']. This is what that looks like for storing a user’s job.

<input type="text" name="attributes[job]" value="developer">

To make this work, you also have to make sure job is defined as an allowed extra field on your email list’s field allowed_form_extra_attributes.

Here are examples of methods to work with those extra attributes.

$subscriber = $subscription->subscriber;

// get all extra attributes
$subscriber->extra_attributes->all(); // return an array with all extra attributes;

// updating an extra attibute
$subscriber->extra_attributes->first_name = 'Other name';
$subscriber->save();

// replacing all extra attributes in one go
$subscriber->extra_attributes = ['first_name' => 'Jane', 'last_name' => 'Dane'];
$subscriber->save();

// returns all models with a first_name set to John
$subscriber->withExtraAttributes(['first_name' => 'John'])->get();
Automations