erwane / whep-client
Webhooks handler for emailing providers.
Installs: 215
Dependents: 4
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/erwane/whep-client
Requires
- php: ^8.1
- ext-json: *
- ext-mbstring: *
- mlocati/ip-lib: ^1.0
Requires (Dev)
- cakephp/cakephp-codesniffer: ^5.0
- php-parallel-lint/php-parallel-lint: ^1.0
- phpro/grumphp: ^v2.0
- phpunit/phpunit: ^10.5
- 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. Default- null
- 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 is- false.
- signing_key: Your provider private key to validate request came from trusted provider. Default- null
- callbacks: You- callableyou 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_BLOCKLIST | You provider IP is in MX recipient blocklist (spam/dnsbl). | 
| 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. }