spatie / mailcoach-support

Questions and support for Mailcoach
https://mailcoach.app
31 stars 2 forks source link

Sendgrid feedback: The signature is invalid #280

Closed aprendible closed 3 years ago

aprendible commented 3 years ago

Apparently Sendgrid webhook configuration has changed and does not match the Mailcoach documentation. I have tried with Signed Event Webhook Requests enabled and disabled and I keep getting the same error that I detail below.

This is the confusing part for me in the Mailcoach documentation.

At the webhooks settings screen at sendgrid you must add the Bounced, Opened, Clicked and Mark as Spam webhooks and point them to the route your configured. In the screenshot below we configured the webhooks using a ngrok.io domain with a ?secret=yolo-no-real-signature appended to the webhook url.

At no point do I get that referenced 'secret', I don't know what to put in the environment variable SENDGRID_SIGNING_SECRET

Thanks for your help.

Spatie\WebhookClient\Exceptions\WebhookFailed The signature is invalid. 
    vendor/spatie/laravel-webhook-client/src/Exceptions/WebhookFailed.php:11 Spatie\WebhookClient\Exceptions\WebhookFailed::invalidSignature
    vendor/spatie/laravel-webhook-client/src/WebhookProcessor.php:44 Spatie\WebhookClient\WebhookProcessor::ensureValidSignature
    vendor/spatie/laravel-webhook-client/src/WebhookProcessor.php:26 Spatie\WebhookClient\WebhookProcessor::process
    vendor/spatie/laravel-mailcoach-sendgrid-feedback/src/SendgridWebhookController.php:13 Spatie\MailcoachSendgridFeedback\SendgridWebhookController::__invoke
    vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php:48 Illuminate\Routing\ControllerDispatcher::dispatch
    vendor/laravel/framework/src/Illuminate/Routing/Route.php:255 Illuminate\Routing\Route::runController
    vendor/laravel/framework/src/Illuminate/Routing/Route.php:197 Illuminate\Routing\Route::run
    vendor/laravel/framework/src/Illuminate/Routing/Router.php:691 Illuminate\Routing\Router::Illuminate\Routing\{closure}
    vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:128 Illuminate\Pipeline\Pipeline::Illuminate\Pipeline\{closure}
    vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:103 Illuminate\Pipeline\Pipeline::then
    vendor/laravel/framework/src/Illuminate/Routing/Router.php:693 Illuminate\Routing\Router::runRouteWithinStack
    vendor/laravel/framework/src/Illuminate/Routing/Router.php:668 Illuminate\Routing\Router::runRoute
    vendor/laravel/framework/src/Illuminate/Routing/Router.php:634 Illuminate\Routing\Router::dispatchToRoute
    vendor/laravel/framework/src/Illuminate/Routing/Router.php:623 Illuminate\Routing\Router::dispatch
    vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php:166 Illuminate\Foundation\Http\Kernel::Illuminate\Foundation\Http\{closure}
    vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:128 Illuminate\Pipeline\Pipeline::Illuminate\Pipeline\{closure}
    vendor/kabbouchi/nova-impersonate/src/Http/Middleware/Impersonate.php:23 KABBOUCHI\NovaImpersonate\Http\Middleware\Impersonate::handle
    vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:167 Illuminate\Pipeline\Pipeline::Illuminate\Pipeline\{closure}
    vendor/laravel/nova/src/Http/Middleware/ServeNova.php:26 Laravel\Nova\Http\Middleware\ServeNova::handle
    vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:167 Illuminate\Pipeline\Pipeline::Illuminate\Pipeline\{closure}
    vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php:21 Illuminate\Foundation\Http\Middleware\TransformsRequest::handle
    vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:167 Illuminate\Pipeline\Pipeline::Illuminate\Pipeline\{closure}
    vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php:21 Illuminate\Foundation\Http\Middleware\TransformsRequest::handle
    vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:167 Illuminate\Pipeline\Pipeline::Illuminate\Pipeline\{closure}
    vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ValidatePostSize.php:27 Illuminate\Foundation\Http\Middleware\ValidatePostSize::handle
    vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:167 Illuminate\Pipeline\Pipeline::Illuminate\Pipeline\{closure}
    vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php:87 Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance::handle
    vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:167 Illuminate\Pipeline\Pipeline::Illuminate\Pipeline\{closure}
    vendor/fruitcake/laravel-cors/src/HandleCors.php:37 Fruitcake\Cors\HandleCors::handle
    vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:167 Illuminate\Pipeline\Pipeline::Illuminate\Pipeline\{closure}
    vendor/fideloper/proxy/src/TrustProxies.php:57 Fideloper\Proxy\TrustProxies::handle
    vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:167 Illuminate\Pipeline\Pipeline::Illuminate\Pipeline\{closure}
    vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:103 Illuminate\Pipeline\Pipeline::then
    vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php:141 Illuminate\Foundation\Http\Kernel::sendRequestThroughRouter
    vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php:110 Illuminate\Foundation\Http\Kernel::handle
    public/index.php:53 [main]

Health check:

Environment: production Debug: OFF Horizon: Active Queue connection: OK Webhooks: 0 unprocessed webhooks Schedule: ran 0 minute(s) ago Default mailer: sendgrid Mailcoach mailer: null Campaign mailer: null Transactional mailer: null

Technical details

App directory: /home/forge/aprendible.com User agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36 PHP version: 7.4.8 MySQL version: 10.2.30-MariaDB-10.2.30+maria~xenial-log Laravel version: 8.15.0 Horizon version: v5.4.0@d08d10ee12f53b7ba2cbb938eb23857e93fe51d3 laravel-mailcoach version: 3.3.0

aprendible commented 3 years ago

I just added a custom validator that just returns true (while you guys work out the actual validation of the signature), and I no longer get the exception, however, it still doesn't show me the clicks and opens of a campaign I sent a few hours ago.

// config/mailcoach.php
'sendgrid_feedback' => [
  'signing_secret' => env('SENDGRID_SIGNING_SECRET'),
  'signature_validator' => SendgridSignatureValidator::class
]
class SendgridSignatureValidator implements SignatureValidator
{
    public function isValid(Request $request, WebhookConfig $config): bool
    {
        return true;
    }
}

Checking the webhook_calls table in the database, I see that in all the records, the payload is an empty array.

id    external_id    name            payload    exception    processed_at            created_at            updated_at
7792    NULL    sendgrid-feedback   []  NULL    2020-11-22 22:00:15 2020-11-22 22:00:15 2020-11-22 22:00:15
7791    NULL    sendgrid-feedback   []  NULL    2020-11-22 21:59:17 2020-11-22 21:59:17 2020-11-22 21:59:17
7790    NULL    sendgrid-feedback   []  NULL    2020-11-22 21:59:08 2020-11-22 21:59:08 2020-11-22 21:59:08
7789    NULL    sendgrid-feedback   []  NULL    2020-11-22 21:59:06 2020-11-22 21:59:06 2020-11-22 21:59:06
7788    NULL    sendgrid-feedback   []  NULL    2020-11-22 21:58:52 2020-11-22 21:58:52 2020-11-22 21:58:52

The tables mailcoach_campaign_clicks, mailcoach_campaign_links and mailcoach_campaign_opens are empty.

riasvdv commented 3 years ago

The secret is something you append to your URL yourself, since Sendgrid doesn't support signing secrets

image

I suggest using a random string of >8 characters

aprendible commented 3 years ago

It seems like the Signed Event Webhook Requests option exists, that's what got me confused about the secret.

Screen Shot 2020-11-23 at 09 35 30 Screen Shot 2020-11-23 at 09 35 45
riasvdv commented 3 years ago

Ah that looks like something new, we haven't added support for that yet

aprendible commented 3 years ago

That's what I thought. So in the meantime, what can I do about webhooks that aren't being stored correctly? clicks and opens are not tracked.

The webhook_calls table in the database, I see that in all the records, the payload is an empty array.

id    external_id    name            payload    exception    processed_at            created_at            updated_at
7792    NULL    sendgrid-feedback   []  NULL    2020-11-22 22:00:15 2020-11-22 22:00:15 2020-11-22 22:00:15
7791    NULL    sendgrid-feedback   []  NULL    2020-11-22 21:59:17 2020-11-22 21:59:17 2020-11-22 21:59:17
7790    NULL    sendgrid-feedback   []  NULL    2020-11-22 21:59:08 2020-11-22 21:59:08 2020-11-22 21:59:08
7789    NULL    sendgrid-feedback   []  NULL    2020-11-22 21:59:06 2020-11-22 21:59:06 2020-11-22 21:59:06
7788    NULL    sendgrid-feedback   []  NULL    2020-11-22 21:58:52 2020-11-22 21:58:52 2020-11-22 21:58:52

The tables mailcoach_campaign_clicks, mailcoach_campaign_links and mailcoach_campaign_opens are empty.

aprendible commented 3 years ago

Now i get this error

TypeError : Argument 1 passed to Spatie\MailcoachSendgridFeedback\ProcessSendgridWebhookJob::handleRawEvent() 
must be of the type array, string given, called in 
/Users/jgarciac/Sites/api.aprendible/vendor/spatie/laravel-mailcoach-sendgrid-feedback/src/ProcessSendgridWebhookJob.php 
on line 28
riasvdv commented 3 years ago

Is there a way for you to log exactly what Sendgrid is sending to you? Maybe add a log somewhere, it could help a lot with debugging

freekmurze commented 3 years ago

Closing due to inactivity.