PHPackages                             erwane/whep-client - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. erwane/whep-client

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

erwane/whep-client
==================

Webhooks handler for emailing providers.

2.3.0(8mo ago)02194MITPHPPHP ^8.1CI passing

Since Aug 3Pushed 8mo agoCompare

[ Source](https://github.com/Erwane/whep-client)[ Packagist](https://packagist.org/packages/erwane/whep-client)[ Docs](https://github.com/Erwane/whep-client)[ RSS](/packages/erwane-whep-client/feed)WikiDiscussions 2.x Synced 1mo ago

READMEChangelogDependencies (6)Versions (19)Used By (4)

Webhooks Handler for Emailing providers
=======================================

[](#webhooks-handler-for-emailing-providers)

[![Software License](https://camo.githubusercontent.com/55c0218c8f8009f06ad4ddae837ddd05301481fcf0dff8e0ed9dadda8780713e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d627269676874677265656e2e7376673f7374796c653d666c61742d737175617265)](LICENSE)[![codecov](https://camo.githubusercontent.com/4802f8763a63d9603104e79976be619ebaaa3565c7964b905ae58ccff3ae7190/68747470733a2f2f636f6465636f762e696f2f67682f457277616e652f776865702d636c69656e742f67726170682f62616467652e7376673f746f6b656e3d4c3938495a5a46425932)](https://codecov.io/gh/Erwane/whep-client)[![CI](https://github.com/Erwane/whep-client/actions/workflows/ci.yml/badge.svg)](https://github.com/Erwane/whep-client/actions)[![Packagist Downloads](https://camo.githubusercontent.com/7cc6cd7d845d4f5e9b67a10102227424f019e87e93624b1b222e40ae238d3d08/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f457277616e652f776865702d636c69656e74)](https://packagist.org/packages/Erwane/whep-client)[![Packagist Version](https://camo.githubusercontent.com/446bc79fc4a967fe85ca27cc70c18603f5f4aacbc81ca1a64ec967b9d083a5b6/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f457277616e652f776865702d636c69656e74)](https://packagist.org/packages/Erwane/whep-client)

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
----------------------------

[](#available-providers-handlers)

ProviderPackage[Brevo](https://www.brevo.com/)[erwane/whep-brevo](https://github.com/Erwane/whep-brevo)[Mailgun](https://www.mailgun.com/)[erwane/whep-mailgun](https://github.com/Erwane/whep-mailgun)[Mailjet](https://www.mailjet.com/)[erwane/whep-mailjet](https://github.com/Erwane/whep-mailjet)[Postal](https://docs.postalserver.io/)[erwane/whep-postal](https://github.com/Erwane/whep-postal)Usage
-----

[](#usage)

```
composer require erwane/whep-
```

```
use WHEP\Factory;
use WHEP\Exception\SecurityException;
use WHEP\Exception\WHEPException;
use WHEP\ProviderInterface;

try {
    $provider = Factory::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
-------

[](#options)

You can pass options to `Factory::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 `callable` you want to be called, depends on event type.

### Security

[](#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

[](#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](https://docs.postalserver.io/), 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

[](#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

[](#callbacks)

Your callback method are cast when `$provider->callback()` is called (you decide when). See [Event type &amp; Callbacks](#event-type--callbacks) section for details.

```
Factory::provider('', ['callbacks' => [ProviderInterface::EVENT_UNSUB => [$this, 'callbackUnsub']]]);
```

#### Event type &amp; Callbacks

[](#event-type--callbacks)

You can configure one callback by event type. Available callbacks are:

EventWhy 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
-------

[](#methods)

ProviderInterface has the following methods:

- [getName()](#getname)
- [getTime()](#gettime)
- [getType()](#gettype)
- [getRecipient()](#getrecipient)
- [getDetails()](#getdetails)
- [getSmtpResponse()](#getsmtpresponse)
- [getUrl()](#geturl)
- [getRaw()](#getraw)
- [process()](#process)
- [callback()](#callback)
- [securityChecked()](#securitychecked)

### getName()

[](#getname)

Return provider name.

```
echo $provider->getName();
```

### getTime()

[](#gettime)

Get event time as `\DateTimeInterface`. This represents when hook was received, not event time.

```
$time = $provider->getTime();
```

### getType()

[](#gettype)

Return event type. See [Event type &amp; Callbacks](#event-type--callbacks) for all types.

```
if ($provider->getType() === \WHEP\ProviderInterface::EVENT_UNSUB) {
    // Do something
}
```

### getRecipient()

[](#getrecipient)

Return event related e-mail recipient.

```
echo $provider->getRecipient();
```

### getDetails()

[](#getdetails)

Return provider event details (or reason).

```
echo $provider->getDetails();
```

### getSmtpResponse()

[](#getsmtpresponse)

Return recipient MX SMTP response.

```
echo $provider->getSmtpResponse();
```

### getUrl()

[](#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()

[](#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)

Process the webhook data. This method is chainable.

```
$provider = \WHEP\Factory::provider('mailgun')
    ->process($webhookData);
```

### callback()

[](#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()

[](#securitychecked)

Return true if security was checked. Default to `false`.

```
if (!$provider->securityChecked()) {
    // Your webhook url deserve security.
}
```

###  Health Score

36

—

LowBetter than 82% of packages

Maintenance59

Moderate activity, may be stable

Popularity11

Limited adoption so far

Community11

Small or concentrated contributor base

Maturity53

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~1 days

Total

19

Last Release

261d ago

Major Versions

1.1.0 → 2.1.02025-08-11

1.2.0 → 2.0.22025-08-13

1.2.1 → 2.2.22025-08-23

1.2.2 → 2.3.02025-08-30

1.3.0 → 2.x-dev2025-08-30

PHP version history (3 changes)1.0.0PHP ^7.2

2.1.0PHP ^8.1

2.0.0PHP 8.0.\*

### Community

Maintainers

![](https://www.gravatar.com/avatar/91732d78336582954080932d4350d08420a053dbba6728f1727b5500ab931c65?d=identicon)[Erwane](/maintainers/Erwane)

---

Top Contributors

[![Erwane](https://avatars.githubusercontent.com/u/712604?v=4)](https://github.com/Erwane "Erwane (33 commits)")

---

Tags

webhookemailing

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/erwane-whep-client/health.svg)

```
[![Health](https://phpackages.com/badges/erwane-whep-client/health.svg)](https://phpackages.com/packages/erwane-whep-client)
```

###  Alternatives

[dintel/php-github-webhook

Simple class for handling GitHub webhook calls

5115.5k](/packages/dintel-php-github-webhook)[ankurk91/laravel-ses-webhooks

Handle AWS SES webhooks in Laravel php framework

2534.2k](/packages/ankurk91-laravel-ses-webhooks)[atakde/discord-webhook-php

discord webhook php

186.5k](/packages/atakde-discord-webhook-php)[degordian/yii2-webhooks

Yii2 extension for webhooks

117.1k](/packages/degordian-yii2-webhooks)[shipsaas/laravel-inbox-process

Inbox pattern process implementation for your Laravel Applications

132.1k](/packages/shipsaas-laravel-inbox-process)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
