This is the base project to easily handle webhooks sent by different emailing providers and uniformizing in a comprehensive object.
This project is not made to be used alone, you need to pick your providers handlers corresponding to your project.
| Provider | Package |
|---|---|
| Brevo | erwane/whep-brevo |
| Mailgun | erwane/whep-mailgun |
| Mailjet | erwane/whep-mailjet |
| Postal | erwane/whep-postal |
composer require erwane/whep-<provider>use WHEP\Factory;
use WHEP\Exception\SecurityException;
use WHEP\Exception\WHEPException;
use WHEP\ProviderInterface;
try {
$provider = Factory::provider('<provider>', [
'client_ip' => $_SERVER['REMOTE_ADDR'] ?? null, // Use your framework correct method to get the client ip.
'callbacks' => [
ProviderInterface::EVENT_BLOCKED => [$this, 'callbackInvalidate'],
ProviderInterface::EVENT_BOUNCE_HARD => [$this, 'callbackInvalidate'],
ProviderInterface::EVENT_BOUNCE_QUOTA => [$this, 'callbackUnsub'],
],
]);
// process the data.
$provider->process($webhookData);
// Data available from provider getters.
$recipient = $provider->getRecipient();
// Launch callback
$provider->callback();
} catch (SecurityException $e) {
// log ?
} catch (WHEPException $e) {
// log ?
}You can pass options to Factory::provider('<provider>', $options) method.
All available options are:
client_ip: The client IP who request your url. Defaultnullallowed_ip: Array of IPv4/IPv6 network (range) and allowed IP. Default depends on provider.check_ip: Set to false to bypass security IP check. Default isfalse.signing_key: Your provider private key to validate request came from trusted provider. Defaultnullcallbacks: Youcallableyou want to be called, depends on event type.
Except if your webhook url has a security token, you can't ensure the webhook really came from trusted provider.
Some providers use a signing key to validate data or provide an IP addresses list.
When provider publish his IP addresses, you should pass the webhook client IP to the provider.
Factory::provider('mailjet', ['client_ip' => $_SERVER['REMOTE_ADDR'] ?? null]);When provider is self-hosted, like Postal, you can pass your postal server IP.
Factory::provider('postal', [
'client_ip' => $_SERVER['REMOTE_ADDR'] ?? null,
'allowed_ip' => [
'10.0.0.1',
'fe80::0023:1',
'192.168.0.1/24',
],
]);You can bypass IP check with check_ip sets to false.
Factory::provider('mailjet', ['check_ip' => false]);When provider support signing key, you can pass your private key with signing_key option.
Factory::provider('mailgun', ['signing_key' => 'my-private-signing-key']);The validation is done during ProviderInterface::process()
Your callback method are cast when $provider->callback() is called (you decide when).
See Event type & Callbacks section for details.
Factory::provider('<provider>', ['callbacks' => [ProviderInterface::EVENT_UNSUB => [$this, 'callbackUnsub']]]);You can configure one callback by event type. Available callbacks are:
| Event | Why event was emitted |
|---|---|
ProviderInterface::EVENT_REQUEST |
You send an e-mail to your provider. |
ProviderInterface::EVENT_DEFERRED |
The send was deferred by provider. |
ProviderInterface::EVENT_BLOCKED |
The recipient e-mail is in provider blocklist. |
ProviderInterface::EVENT_SENT |
E-mail was sent. |
ProviderInterface::EVENT_BOUNCE_SOFT |
E-mail receive a soft-bounce (4xx) with reason. |
ProviderInterface::EVENT_BOUNCE_QUOTA |
Like BOUNCE_SOFT but quota problem detected. |
ProviderInterface::EVENT_BOUNCE_HARD |
E-mail receive a hard-bounce (5xx) with reason. |
ProviderInterface::EVENT_OPENED |
E-mail was opened. |
ProviderInterface::EVENT_CLICK |
A link was clicked. |
ProviderInterface::EVENT_ABUSE |
Recipient report your e-mail as abuse. |
ProviderInterface::EVENT_UNSUB |
Recipient want to unsubscribed from you list. |
ProviderInterface::EVENT_BLOCKLIST |
You provider IP is in MX recipient blocklist (spam/dnsbl). |
ProviderInterface::EVENT_ERROR |
Provider error. |
ProviderInterface has the following methods:
- getName()
- getTime()
- getType()
- getRecipient()
- getDetails()
- getSmtpResponse()
- getUrl()
- getRaw()
- process()
- callback()
- securityChecked()
Return provider name.
echo $provider->getName();Get event time as \DateTimeInterface. This represents when hook was received, not event time.
$time = $provider->getTime();Return event type. See Event type & Callbacks for all types.
if ($provider->getType() === \WHEP\ProviderInterface::EVENT_UNSUB) {
// Do something
}Return event related e-mail recipient.
echo $provider->getRecipient();Return provider event details (or reason).
echo $provider->getDetails();Return recipient MX SMTP response.
echo $provider->getSmtpResponse();Return url of clicked link. Available for \WHEP\ProviderInterface::EVENT_CLICK only.
Some providers (mailgun) do not return this information.
echo $provider->getUrl();Return event raw data as array by default. Return as json if $asJson is true.
$raw = $provider->getRaw();
// raw data in json format.
echo $provider->getRaw(true);Process the webhook data. This method is chainable.
$provider = \WHEP\Factory::provider('mailgun')
->process($webhookData);Run you related event type callable if configured.
// This will process data and call self::callbackUnsub($provider) if event is unsub.
$provider = \WHEP\Factory::provider('mailgun', [
'callbacks' => [
\WHEP\ProviderInterface::EVENT_UNSUB => [$this, 'callbackUnsub'],
],
])
->process($webhookData)
->callback();Return true if security was checked. Default to false.
if (!$provider->securityChecked()) {
// Your webhook url deserve security.
}