erwane / whep-client
Webhooks handler for emailing providers.
Requires
- php: ^8.1
- ext-json: *
- ext-mbstring: *
- mlocati/ip-lib: ^1.0
Requires (Dev)
- cakephp/cakephp-codesniffer: ^5.0
- phpunit/phpunit: ^10.5
- symfony/phpunit-bridge: ^7.0
- symfony/var-dumper: ^v6.0
README
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.
Available providers handlers
Provider | Package |
---|---|
Brevo | erwane/whep-brevo |
Mailgun | erwane/whep-mailgun |
Mailjet | erwane/whep-mailjet |
Postal | erwane/whep-postal |
Usage
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 ? }
Options
You can pass options to Factory::provider('<provider>', $options)
method.
All available options are:
client_ip
: The client IP who request your url. Defaultnull
allowed_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. Defaultnull
callbacks
: Youcallable
you want to be called, depends on event type.
Security
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.
IP validation
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]);
Signing key
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()
Callbacks
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']]]);
Event type & Callbacks
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_ERROR |
Provider error. |
Methods
ProviderInterface has the following methods:
- getName()
- getTime()
- getType()
- getRecipient()
- getDetails()
- getSmtpResponse()
- getUrl()
- getRaw()
- process()
- callback()
- securityChecked()
getName()
Return provider name.
echo $provider->getName();
getTime()
Get event time as \DateTimeInterface
. This represents when hook was received, not event time.
$time = $provider->getTime();
getType()
Return event type. See Event type & Callbacks for all types.
if ($provider->getType() === \WHEP\ProviderInterface::EVENT_UNSUB) { // Do something }
getRecipient()
Return event related e-mail recipient.
echo $provider->getRecipient();
getDetails()
Return provider event details (or reason).
echo $provider->getDetails();
getSmtpResponse()
Return recipient MX SMTP response.
echo $provider->getSmtpResponse();
getUrl()
Return url of clicked link. Available for \WHEP\ProviderInterface::EVENT_CLICK
only.
Some providers (mailgun) do not return this information.
echo $provider->getUrl();
getRaw()
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()
Process the webhook data. This method is chainable.
$provider = \WHEP\Factory::provider('mailgun') ->process($webhookData);
callback()
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();
securityChecked()
Return true if security was checked. Default to false
.
if (!$provider->securityChecked()) { // Your webhook url deserve security. }