philsown/maileable

Maileable, a library for adding filters to Laravel Mailable messages

dev-develop 2020-05-26 12:26 UTC

README

This code is in active development with no releases. Please do not use this library yet. This is mainly on github so Paul can read it. Hi Paul!

About Maileable

Maileable is a library for adding filters to Laravel Mailable messages that can you modify Mailable or Swift_Message objects before they are sent. Think of it as response middleware for email.

The name "Maileable" is a play on on the word "malleable," which, in English, among other things, means "easily influenced; pliable." The goal of this library is to make it easy to change messages before they are sent.

Why

The examples directory has a couple of few cases, such as making sure the from address has a name and is tidy, prepending branding to the mail subject, or adding or modifying content in the mail body. This last one is better handled with Blade templates, but the concept is demonstrated here. You can modify the email headers. Logging. There's probably more ideas, I'm sure.

Why not just use the Illuminate\Mail\Events\MessageSending event? Uh, yeah, you could do that, too, I suppose. This is basically gives you the possibility of grouping your Mailable namespaces, such as Mail\Orders or Mail\Newsletter and applying filters based on the Namespaces, too.

How

Installation

Install with Composer.

Add the repository to your composer.json file.

{
    "repositories": [
        {
            "type": "git",
            "url": "https://github.com/philsown/maileable"
        }
    ]
}

Set your minimum-stability to dev.

{
    "minimum-stability": "dev",
}

Install with the require command.

$ composer require philsown/mailable

Add the service provider to your config/app.php provider's array.

<?php

return [
    // ...
    'providers' => [
        // ...

        /*
         * Application Service Providers...
         */
        App\Providers\AppServiceProvider::class,
        App\Providers\AuthServiceProvider::class,
        // App\Providers\BroadcastServiceProvider::class,
        App\Providers\EventServiceProvider::class,
        App\Providers\RouteServiceProvider::class,

        // add Maileable anywhere in here, really
        Maileable\Providers\MailFilterServiceProvider::class,
    ],
    // ...
];

Publish the vendor config.

$ php artisan vendor:publish --provider=Maileable\Providers\MailFilterServiceProvider --tag=config

This will create config/maileable.php. Edit this file to wire filters to your Mailables. This is explained below.

Use

The short version:

  1. Update the Mailable use statement to use Maileable's class, sorry :(
  2. Make a mail filter using the make:mailfilter generator.
  3. Flesh out the filter method.
  4. Wire the filter in the config/maileable.php file you published above.

The longer version:

Step 1: Update the Mailable use statement in your existing Mailable class

Sorry about this. If anyone knows a way around this, I'd love to hear it.

<?php
# app/Mail/YourEmail.php

namespace App\Mail;

// Change this line in your Mailable class
use Maileable\Mail\Mailable;

// everything else is the same
class YourEmail extends Mailable
{
    public function build()
    {
        // the rest of this class is unchanged
    }
}

Step 2: Use the generator to make a mail Filter

There is a generator for this using this artisan command:

$ php artisan make:mailfilter YourFilterName

This command has no other arguments besides name. This will create a mail filter from a stub in the app\Mail\Filters directory, and create that directory if it doesn't already exist.

Step 3: Flesh out your Filter class' filter method

Choose if you want to filter the \Swift_Message class or Illuminate\Mail\Mailable class.

If you would like to filter the \Swift_Message class, set $modifies to 'swift' (or take it out and let it default from the FilterAbstract). This is the default and let's you easily tinker with the nuts and bolts of the email message. This filtering happens when the mailer calls Illuminate\Mail\Mailable::runCallbacks, basically at the very last possible point.

If you want to filter Illuminate\Mail\Mailable, set $modifies to 'mailable'. This is useful if you want to use any information contained in the Mailable class, like grabbing the Mailable's class name or the name of the view. This filtering happens when the when the Mailable::send method is called. It's only a slightly different way of doing things, but I think it's nice to have a choice.

Use the @param phpdoc to let your IDE know what the message variable is.

For \Swift_Message, use:

<?php
    /**
     * Filter
     *
     * @param Swift_Message $message
     *
     * @return void
     */
    public function filter($message)

For Illuminate\Mail\Mailable, use:

<?php
    /**
     * Filter
     *
     * @param Mailable $message
     *
     * @return void
     */
    public function filter($message)

Then simply flesh out the filter method with some code that does what you want.

<?php

    // ...

    /**
     * Filter
     *
     * @param Mailable $message
     *
     * @return void
     */
    public function filter($message)
    {
        $froms = $message->from;

        foreach ($froms as &$from) {
            if ('contact@mycompany.com' != $from['address'] || !empty($from['name'])) {
                continue;
            }

            $from['name'] = 'My Company';
        }

        $message->from = $froms;
    }

    // ...

Step. 4 Wire the filter in the config/maileable.php file you published above

Wire the filters to various Mailable classes in the config/maileable.php config file. This works by using patterns to select classes, then assigning one or more filters to Mailables that match the pattern.

<?php

return [
    'filters' => [
        'App\Mail\*' => [
            \App\Mail\Filters\ThinkBeforeYouPrint::class,
            \App\Mail\Filters\AddSubjectBranding::class,
        ],
        'App\Mail\Orders\*' => [
            \App\Mail\Filters\ShippingDisclaimer::class,
        ],
        'App\Mail\Newsletter\*' => [
            \App\Mail\Filters\AddUnsubscribeHeaders::class,
        ],
    ],
];

Support and Issues

There's probably tons of problems with this and I've never used it on a Queued message, so... YMMV. But hey, give it a whirl and let me know how it goes or if you need help with anything!

Contributing

Thank you for your interest! To contribute, please fork this repository and submit a pull request.

License

Maileable is open-sourced software licensed under the MIT license.