Coder Social home page Coder Social logo

laravel-postmark-webhooks's Introduction

Postmark Inbound

Handle Postmark webhooks in a Laravel application

Latest Version on Packagist Software License Tests StyleCI Total Downloads

Postmark can send out several webhooks to your application when an event occurs.
This way Postmark is able to immediately notify you when something new occurs.

This package can help you handle those webhooks.

Installation

You can install the package via composer:

composer require mvdnbrk/laravel-postmark-webhooks

This package will log all incoming webhooks to the database by default.
Run the migrations to create a postmark_webhook_logs table in the database:

php artisan migrate

If you want to disable database logging you can set POSTMARK_WEBHOOKS_LOG_ENABLED=false in your .env file.

Setup webhooks with Postmark

Visit the servers page on your Postmark account. Choose the server you want to setup webhooks for.
Go to settings > webhooks > add webbook.

This package will register a route where Postmark can post their webhooks to: /api/webhooks/postmark.

Fill in your webhook URL: https://<your-domain.com>/api/webhooks/postmark
Pick the events Postmark should send to you and save the webhook.
You are ready to receive webhook notifications from Postmark!

You may change the /api/webhooks/postmark endpoint to anything you like.
You can do this by changing the path key in the config/postmark-webooks.php file.

Protection of your webhook

This package protects your webhook automatically by only allowing requests from the IP range that Postmark uses.

Usage

Postmark can send out several event types by posting a webhook.
You can find the full list of webhooks in the Postmark documentation.

All webhook requests will be logged in the postmark_webhook_logs table.
The table has a payload column where the entire payload of the incoming webhook is saved.
The ID Postmark assigned to the original message will be saved in the message_id column,
the event type will be stored in the record_type column and the email address as well in the email column.

Note that event types will be converted to snake_case.
For example SpamComplaint will be saved as spam_complaint.

Events

Whenever a webhook call comes in, this package will fire a PostmarkWebhookCalled event.
You may register an event listener in the EventServiceProvider:

/**
 * The event listener mappings for the application.
 *
 * @var array
 */
protected $listen = [
    PostmarkWebhookCalled::class => [
        YourListener::class,
    ],
];

Example of a listener:

<?php

namespace App\Listeners;

use Mvdnbrk\PostmarkWebhooks\Events\PostmarkWebhookCalled;

class YourListener
{
    /**
     * Handle the event.
     *
     * @param  \Mvdnbrk\PostmarkWebhooks\Events\PostmarkWebhookCalled  $event
     * @return void
     */
    public function handle(PostmarkWebhookCalled $event)
    {
        // Do your work here.

        // You can access the payload here with: $event->payload.
        // The email address, message ID and record type are also available:
        // $event->email
        // $event->messageId
        // $event->recordType
    }
}

You may also register an event listener for a specific type of event:

/**
 * The event listener mappings for the application.
 *
 * @var array
 */
protected $listen = [
    'webhook.postmark: spam_complaint' => [
        YourSpamComplaintListener::class,
    ],
];

Available events: open, bounce, click, delivery, spam_complaint.

Advanced configuration

You may optionally publish the config file with:

php artisan vendor:publish --provider="Mvdnbrk\PostmarkWebhooks\PostmarkWebhooksServiceProvider" --tag="config"

Within the configuration file you may change the table name being used or the Eloquent model being used to save log records to the database.

If you want to use your own model to save the logs to the database you should extend the Mvdnbrk\PostmarkWebhooks\PostmarkWebhook class.

You can also exclude one or more event types from being logged to the database.
Place the events you want to exclude under the except key:

'log' => [
    ...
    'except' => [
        'open',
        ...
    ],
],

You can map the events fired by this package to your own event classes:

'events' => [
    'spam_complaint' => App\Events\SpamComplaint,
    ...
],

Change log

Please see CHANGELOG for more information on what has changed recently.

Testing

$ composer test

Contributing

Please see CONTRIBUTING for details.

Security Vulnerabilities

Please review our security policy on how to report security vulnerabilities.

Credits

Inspired by Laravel Stripe Webooks from Spatie.

License

The MIT License (MIT). Please see License File for more information.

laravel-postmark-webhooks's People

Contributors

flatcapco avatar mikebronner avatar mvdnbrk avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

laravel-postmark-webhooks's Issues

PHP 8 support

Hello Mark, congrats on the package!

I tried to install, but I've got this error, does the package support PHP 8+ ? Thank you in advance.

`Your requirements could not be resolved to an installable set of packages.

Problem 1
- mvdnbrk/laravel-postmark-webhooks[v0.1.0, ..., v0.2.1, v1.0.0, ..., v1.5.1] require php ^7.1 -> your php version (8.2.6) does not satisfy that requirement.
- mvdnbrk/laravel-postmark-webhooks v1.6.0 requires illuminate/support ^6.0 || ^7.0 || ^8.0 -> found illuminate/support[v6.0.0, ..., v6.20.44, v7.0.0, ..., v7.30.6, v8.0.0, ..., v8.83.27] but these were not loaded, likely because it conflicts with another require.
- mvdnbrk/laravel-postmark-webhooks v1.7.0 requires illuminate/support ^6.0 || ^7.0 || ^8.0 || ^9.0 -> found illuminate/support[v6.0.0, ..., v6.20.44, v7.0.0, ..., v7.30.6, v8.0.0, ..., v8.83.27, v9.0.0, ..., v9.52.15] but these were not loaded, likely because it conflicts with another require.
- Root composer.json requires mvdnbrk/laravel-postmark-webhooks * -> satisfiable by mvdnbrk/laravel-postmark-webhooks[v0.1.0, v0.2.0, v0.2.1, v1.0.0, ..., v1.7.0].`

Upgrading to L9 - Illuminate\Support

Hey - thanks for this package I've been using it flawlessly for sometime now.
I've just come to upgrade to L9 from L8 and I have a conflict issue in composer:

laravel/framework replaces illuminate/support and thus cannot coexist with it.

Are there any plans to support L9 with this package? or are you open to PR's or should I migrate away from this package if its no longer maintained?

Thanks a mil
Alex

Got 401 Unauthorized response code

Hi, thank you for the package!

I'm testing the package with a ngrok host directly from the Postmark Webhook interface and i receive the 401 error code.

Maybe it will be a good idea to have the IP addresses from your PostmarkIpsWhitelist in the config file, to have the possiblity to override this adresses.

Thank you! :)

Undefined Array Key 1

Whatever I try to do, I always get this error:

Ps. I'm using the Postmarkapp webhook test function.

[2023-08-14 06:44:15] staging.ERROR: Undefined array key 1 {"exception":"[object] (ErrorException(code: 0): Undefined array key 1 at /home/ploi//vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php:436)
[stacktrace]
#0 /home/ploi//vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php(436): Illuminate\Foundation\Bootstrap\HandleExceptions->handleError()
#1 /home/ploi//vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php(422): Illuminate\Events\Dispatcher->createClassCallable()
#2 /home/ploi//vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php(249): Illuminate\Events\Dispatcher->Illuminate\Events\{closure}()
#3 /home/ploi//vendor/laravel/framework/src/Illuminate/Foundation/helpers.php(450): Illuminate\Events\Dispatcher->dispatch()
#4 /home/ploi//vendor/mvdnbrk/laravel-postmark-webhooks/src/Http/Controllers/StorePostmarkWebhookController.php(24): event()
#5 /home/ploi//vendor/laravel/framework/src/Illuminate/Support/helpers.php(263): Mvdnbrk\PostmarkWebhooks\Http\Controllers\StorePostmarkWebhookController->Mvdnbrk\PostmarkWebhooks\Http\Controllers\{closure}()
#6 /home/ploi//vendor/mvdnbrk/laravel-postmark-webhooks/src/Http/Controllers/StorePostmarkWebhookController.php(18): tap()
#7 /home/ploi//vendor/laravel/framework/src/Illuminate/Routing/Controller.php(54): Mvdnbrk\PostmarkWebhooks\Http\Controllers\StorePostmarkWebhookController->__invoke()
#8 /home/ploi//vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php(45): Illuminate\Routing\Controller->callAction()
#9 /home/ploi//vendor/laravel/framework/src/Illuminate/Routing/Route.php(261): Illuminate\Routing\ControllerDispatcher->dispatch()
#10 /home/ploi//vendor/laravel/framework/src/Illuminate/Routing/Route.php(205): Illuminate\Routing\Route->runController()
#11 /home/ploi//vendor/laravel/framework/src/Illuminate/Routing/Router.php(721): Illuminate\Routing\Route->run()
#12 /home/ploi//vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(128): Illuminate\Routing\Router->Illuminate\Routing\{closure}()
#13 /home/ploi//vendor/mvdnbrk/laravel-postmark-webhooks/src/Http/Middleware/PostmarkIpsWhitelist.php(34): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()
#14 /home/ploi//vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Mvdnbrk\PostmarkWebhooks\Http\Middleware\PostmarkIpsWhitelist->handle()
#15 /home/ploi//vendor/laravel/framework/src/Illuminate/Routing/Middleware/SubstituteBindings.php(50): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()
#16 /home/ploi//vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\Routing\Middleware\SubstituteBindings->handle()
#17 /home/ploi//vendor/laravel/framework/src/Illuminate/Routing/Middleware/ThrottleRequests.php(127): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()
#18 /home/ploi//vendor/laravel/framework/src/Illuminate/Routing/Middleware/ThrottleRequests.php(93): Illuminate\Routing\Middleware\ThrottleRequests->handleRequest()
#19 /home/ploi//vendor/laravel/framework/src/Illuminate/Routing/Middleware/ThrottleRequests.php(55): Illuminate\Routing\Middleware\ThrottleRequests->handleRequestUsingNamedLimiter()
#20 /home/ploi//vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\Routing\Middleware\ThrottleRequests->handle()
#21 /home/ploi//vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(103): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()
#22 /home/ploi//vendor/laravel/framework/src/Illuminate/Routing/Router.php(719): Illuminate\Pipeline\Pipeline->then()
#23 /home/ploi//vendor/laravel/framework/src/Illuminate/Routing/Router.php(698): Illuminate\Routing\Router->runRouteWithinStack()
#24 /home/ploi//vendor/laravel/framework/src/Illuminate/Routing/Router.php(662): Illuminate\Routing\Router->runRoute()
#25 /home/ploi//vendor/laravel/framework/src/Illuminate/Routing/Router.php(651): Illuminate\Routing\Router->dispatchToRoute()
#26 /home/ploi//vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(167): Illuminate\Routing\Router->dispatch()
#27 /home/ploi//vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(128): Illuminate\Foundation\Http\Kernel->Illuminate\Foundation\Http\{closure}()
#28 /home/ploi//vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()
#29 /home/ploi//vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ConvertEmptyStringsToNull.php(31): Illuminate\Foundation\Http\Middleware\TransformsRequest->handle()
#30 /home/ploi//vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull->handle()
#31 /home/ploi//vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()
#32 /home/ploi//vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TrimStrings.php(40): Illuminate\Foundation\Http\Middleware\TransformsRequest->handle()
#33 /home/ploi//vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\Foundation\Http\Middleware\TrimStrings->handle()
#34 /home/ploi//vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ValidatePostSize.php(27): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()
#35 /home/ploi//vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\Foundation\Http\Middleware\ValidatePostSize->handle()
#36 /home/ploi//vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php(86): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()
#37 /home/ploi//vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance->handle()
#38 /home/ploi//vendor/fruitcake/laravel-cors/src/HandleCors.php(38): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()
#39 /home/ploi//vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Fruitcake\Cors\HandleCors->handle()
#40 /home/ploi//vendor/laravel/framework/src/Illuminate/Http/Middleware/TrustProxies.php(39): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()
#41 /home/ploi//vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\Http\Middleware\TrustProxies->handle()
#42 /home/ploi//vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(103): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()
#43 /home/ploi//vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(142): Illuminate\Pipeline\Pipeline->then()
#44 /home/ploi//vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(111): Illuminate\Foundation\Http\Kernel->sendRequestThroughRouter()
#45 /home/ploi//public/index.php(51): Illuminate\Foundation\Http\Kernel->handle()
#46 {main}
"}

Configurable Middleware Group

Hi, I have the need to put the webhook route in a different middleware group than api. Do you have a recommended way of doing this, other than me having to write my own service provider?

Thanks!
~Mike

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.