This bundle provides services to handle Mandrill's Webhooks:
- a
WebhookControllercontroller to handle Mandrill's webhook requests; - a
WebhookAuthenticationservice to verify the request to ensure that the data is coming from Mandrill and not a third-party pretending to be; - a
WebhookHandlerhandler to let you perform a custom action when a message event occurs, by making use of the Event Dispatcher component; - a
MessageEvents, the list of events to listen to suit the specific needs of your application; - a
MessageEvent, an object that represents a message event data sent by Mandrill.
Mandrill's webhooks offer many possibilities. Here are some examples:
- Reduce bounce rate: listen for bounces events, then remove invalid emails from your mailing lists.
- Avoid spam complaint rate: listen for spam events, then delete the email that flagged your message as spam from your mailing lists.
- Synchronize database in real-time: listen for send events, then mark your entity as sent in your database.
- Log events of email: listen for one or more events, then log them to your preferred location by using a logger.
Add your Mandrill Webhook key and URL inside the .env file:
# .env
MANDRILL_WEBHOOK_KEY=6LfoM_YUAAAAACd3tyP82gpjQRrjJar-AoHaCyVQ
MANDRILL_WEBHOOK_URL=https://acme.com/mandrill/hooks
The MANDRILL_WEBHOOK_KEY key is used to identify the webhook. You can retrieve or reset the key
from your Webhooks page in your account, in the Key column.
The MANDRILL_WEBHOOK_URL key is used to authenticate the Mandrill's request.
It's the URL that you used to configure the webhook in Mandrill.
By default, the authentication is enabled. Therefore, you need to specify the webhook key and webhook URL to verify the request signature:
# config/packages/mandrill.yaml
parameters:
mandrill_webhook_key: '%env(resolve:MANDRILL_WEBHOOK_KEY)%'
mandrill_webhook_url: '%env(resolve:MANDRILL_WEBHOOK_URL)%'
qferrer_mandrill:
webhooks:
key: "%mandrill_webhook_key%"
url: "%mandrill_webhook_key%"
This is not recommended but if you want to disable the authentication (e.g. in dev environment), set the authentication to false:
# config/packages/dev/mandrill.yaml
qferrer_mandrill:
webhooks:
auth: false
The WebhookController controller accepts Mandrill's webhook request and returns the response to Mandrill.
# config/routes.yaml
mandrill_hooks:
path: /mandrill/hooks
controller: Qferrer\Symfony\MandrillBundle\Controller\WebhookController::handle
methods: POST|GET|HEAD
The controller accepts only POST requests and supports the Mandrill check they do to verify that the
URL defined in the Mandrill app exists by using a HEAD request. Symfony silently transforms HEAD requests to GET.
Read more on the Mandrill documentation.
When a Mandrill's webhook is triggered, it's identified by a unique event name, which any number of listeners might be listening to.
All events can be found in the constants of the MessageEvents class:
MessageEvents.SEND: The message is sentMessageEvents.DELAYED: The message is delayedMessageEvents.SOFT_BOUNCE: The message is soft-bouncedMessageEvents.HARD_BOUNCE: The message is hard-bouncedMessageEvents.SPAM: The message is marked as spamMessageEvents.REJECTED: The message is rejectedMessageEvents.UNSUBSCRIBE: The message recipient unsubscribeMessageEvents.OPENED: The message is openedMessageEvents.CLICKED: The link in the message is clicked
The following example shows an event subscriber that defines a method that listens to Mandrill's events and logs the message.
<?php
namespace App\EventListener;
use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
use Qferrer\Symfony\MandrillBundle\Event\MessageEvent;
use Qferrer\Symfony\MandrillBundle\MessageEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Class LoggerListener
*/
class LoggerListener implements EventSubscriberInterface
{
/**
* @var LoggerInterface
*/
private $logger;
/**
* LoggerListener constructor.
*
* @param LoggerInterface $logger
*/
public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
}
/**
* @inheritDoc
*/
public static function getSubscribedEvents()
{
return [
MessageEvents::SEND => 'log',
MessageEvents::REJECTED => 'log',
MessageEvents::HARD_BOUNCE => 'log',
MessageEvents::SOFT_BOUNCE => 'log',
MessageEvents::SPAM => 'log',
];
}
/**
* Log the event of an email
*
* @param MessageEvent $event
*/
public function log(MessageEvent $event)
{
$message = $event->getMessage();
switch ($event->getName()) {
case MessageEvents::REJECTED:
case MessageEvents::HARD_BOUNCE:
$level = LogLevel::ERROR;
break;
case MessageEvents::SOFT_BOUNCE:
case MessageEvents::SPAM:
$level = LogLevel::WARNING;
break;
default:
$level = LogLevel::INFO;
}
$this->logger->log(
$level,
sprintf('Message "%s" has been handled.', $message['_id']),
$message
);
}
}
Mandrill has built-in testing tools to send test events to any webhook URL. To test a webhook using the Mandrill web application:
- Navigate to Settings in your Mandrill account.
- Click Webhooks from the top menu.
- Click the send test button to send a batch of events to your webhook URL.
Your webhook URL must be public to allow Mandrill to send you test events. You should use third-party tools such as ngrok to create a secure public URL to a local server on your machine.
First, you need to disable the authentication in dev environment:
# config/packages/dev/mandrill.yaml
qferrer_mandrill:
webhooks:
auth: false
Then, execute the following command example to send a test event to your webhook URL:
curl --location --request POST 'localhost/mandrill/hooks' \
--form 'mandrill_events=[{"event": "send", "msg": {"_id": "testSend", "to": "john@acme.com", "status": "sent"}, "_id": "testSend", "ts": 1384954004}]'