Skip to content

bertoost/Craft-CMS-Mandrill-Service

Repository files navigation

Mandrill service plugin for Craft CMS (v2)

This plugin provides the ability to send emails via Mandrill API. It also can control all of the emails send by Craft's EmailService being captured for sending to Mandrill. Read below for more information.

Installation

From the root of your Craft installation, just run composer to install this plugin;

composer require bertoost/craft-mandrill-service-plugin

This will install the plugin inside your craft/plugins/ folder automatically.

Composer vendor files

It also brings some other vendor files inside the vendor/ directory in your project root. This can be ignored by your VCS or included when you aren't able to run composer install at your hosting-server.

Maybe your installation is configured to use another path structure. If the plugin can't find the Composer vendor/ folder, it will notify you in the admin panel. To solve it, you can tell us where to find the vendor/ folder. Just add this line to your websites' index.php file, just below the $craftPath definition.

define('COMPOSER_VENDOR_PATH', realpath('../vendor/'));

Enable the plugin in Craft

Navigate to Craft's settings > Plugins > Install Mandrill Service plugin.

Configuration settings

Settings

API Key

After installation you have to configure the plugin to work at all. Navigate to the plugin settings page and enter the API key you want to use.

Remember: Mandrill provides the ability to have a test-API-key. You can test it as many times you want without having a paid account already. Login to Mandrill and activate a "Test" API key.

Enable as a service

There are two ways of using this plugin. You can use the Mandrill service or let it take over control of sending any email, sent by Craft's EmailService. This is a setting in the plugin;

From settings

The from email and name settings are meant to configure the sender name for your site/application. This can be overwritten when using manual service, but this config settings are used by default.

Craft's general config to override

You can pass the following settings to the general.php configuration file of Craft, to override the settings in the settings page from the plugin.

return [
    // ...
    'mandrillEnabled'   => false,
    'mandrillApiKey'    => 'TheKeyFromMandrill',
    'mandrillFromEmail' => 'you@address.mail',
    'mandrillFromName'  => 'Your Sender Name',
];

Take over control of all outgoing emails

Downside (read carefully):

The plugin hooks on the email.onBeforeSendEmail event and disables any further process of Craft's EmailService (by setting $event->performAction = false;). It also will re-fire that event, to be sure all data from any plugin is captured before sending it.

So, why is this a bad thing? Because it can happen (actually: it will!) that your plugin already did it's work before this event reaches the Mandrill-take-over part. But when not, we fire the event again to be sure it will. This will cause a second roundtrip of the email.onBeforeSendEmail event. Depending on what happens on this event, it can slow down the process!

If you're building heavy stuff on this event, it can be good to check if you did your thing already. Like this;

craft()->on('email.onBeforeSendEmail', function (Event $event) {

    // check if we've been here before
    if (!isset($event->params['myplugin_beenHere'])) {

        // do your stuff here

        $event->params['myplugin_beenHere'] = true;
    }
});

It will not stop coming here twice, but the hard part (or load/performance taking part) of your code will be skipped.

Manually use the service

It's also possible to use the Mandrill service manually.

$variables = [
    // any template variables
];

$htmlBody = /* Some HTML content, parsed by Twig?! */;
$plainTextBody = /* Some plain text content, parsed by Twig?! */;

craft()->mandrill
    ->addTo('email@ddre.ss', 'Sender Name')
    ->setContent($htmlBody, $plainTextBody, $variables)
    ->send();

Using Craft's messages system

// get any UserModel anyhow, example:
$user = craft()->users->getUserByEmail('me@example.com');

$variables = [
    // any template variables
];

craft()->mandrill
    ->setUser($user)
    ->setByEmailKey('the_message_key', $variables)
    ->send();

Events

The Craft email events are still being used. They contain the same params as the event is getting from Craft's default EmailService.

[
    'user'       => /* an UserModel */,
    'emailModel' => /* an EmailModel */,
    'variables'  => /* an array of variables */,

    // and on error:
    'error'      => /* error message */,
]

Additional params are added by the Mandrill service

email.onBeforeSendEmail

[
    // ...
    '_mandrill'    => true,
    'emailMessage' => /* a Mandrill_MessageModel */,
]

email.onSendEmail

[
    // ...
    '_mandrill'    => true,
    'emailMessage' => /* a Mandrill_MessageModel */,
    'result'       => /* array of the Mandrill API result */,
]

email.onSendEmailError

[
    // ...
    '_mandrill'    => true,
    'emailMessage' => /* a Mandrill_MessageModel */,
]

Examples

Find some example usages below

Add-in tags

Your plugin can add tags to email messages easily since the emailMessage is passed by the events given by the Mandrill plugin. Example;

When using service manually;

// attachment as content
craft()->mandrill
    // ...
    ->addAttachment('my.pdf', $fileContents, 'application/pdf');

// or as a file path
craft()->mandrill
    // ...
    ->addAttachmentFile('path/to/my.pdf', 'alternate-name.pdf', 'application/pdf')

When the "Mandrill as service" is on;

craft()->on('email.onBeforeSendEmail', function (Event $event) {

    // to be sure it happens when Mandrill is here
    if (isset($event->params['_mandrill'])) {

        // single one
        $event->params['emailMessage']
            ->addTag('Tag name one')
            ->addTag('Tag name two');

        // or as array
        $event->params['emailMessage']
            ->addTag(['Tag name one', 'Tag name two']);

        // based on messages-system email-key
        switch ($event->params['variables']['emailKey']) {
            case 'forgot_password':
                $event->params['emailMessage']
                    ->addTag('Forgot password');
                break;
        }
    }
});

Using attachments

When using service manually;

// attachment as content
craft()->mandrill
    // ...
    ->addAttachment('my.pdf', $fileContents, 'application/pdf');

// or as a file path
craft()->mandrill
    // ...
    ->addAttachmentFile('path/to/my.pdf', 'alternate-name.pdf', 'application/pdf')

When the "Mandrill as service" is on;

craft()->on('email.onBeforeSendEmail', function (Event $event) {

    // to be sure it happens when Mandrill is here
    if (isset($event->params['_mandrill'])) {

        $event->params['emailMessage']
            ->addAttachment('my.pdf', $fileContents, 'application/pdf');
    }
});

Set a schedule date/time

When using service manually;

$dateTime = new DateTime();
$dateTime->modify('+2 hours');

craft()->mandrill
    // ...
    ->setSentAt($dateTime);

When the "Mandrill as service" is on;

craft()->on('email.onBeforeSendEmail', function (Event $event) {

    // to be sure it happens when Mandrill is here
    if (isset($event->params['_mandrill'])) {

        $dateTime = new DateTime();
        $dateTime->modify('+2 hours');

        $event->params['mandrillSentAt'] = $dateTime;
    }
});

Outbound view

The plugin comes with a very cool overview where you can see the outbound of Mandrill. It shows you if messages are sent correctly and also gives you an inside when it failes or bounces. All of this can be found in Mandrill too of course.

Outbound page

To enable this feature, you have to add a sync script to your cronjob system. This is the call you have to make (for example 1 to 4 times a day).

php craft/app/etc/console/yiic mandrill syncOutbound

You can also use this command to sync it manually.

Note: This command scans Mandrill till 4 days in the past. Since bounces are being tried a couple of times.