8000 feat(messaging): Adds Mailjet web hook event callbacks by mcharawi · Pull Request #33407 · PostHog/posthog · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

feat(messaging): Adds Mailjet web hook event callbacks #33407

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Jun 16, 2025

Conversation

mcharawi
Copy link
Contributor
@mcharawi mcharawi commented Jun 10, 2025

Problem

Part of #32436 (we shouldnt close it until its fully implemented tbh)

Changes

Adds a Mailjet CDP source to inject Mailjet web hook events

Did you write or update any docs for this change?

  • No docs needed for this change

How did you test this code?

-unit testing for callbacks

@mcharawi mcharawi marked this pull request as ready for review June 12, 2025 23:26
Copy link
Contributor
@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Summary

Implements Mailjet webhook integration for email event tracking, adding secure event handling and metric collection for email-related activities (sent, opened, clicked, etc.).

  • Added plugin-server/src/cdp/mailjet-metrics.ts for tracking email event metrics with Prometheus counters
  • Implemented HMAC SHA-256 signature validation for webhook security in /public/messaging/mailjet_webhook endpoint
  • Modified app metrics serializers to support Mailjet webhook events while removing 'composeWebhook' from request choices
  • Consider aligning TypeScript interface with serializer choices to maintain consistency

3 files reviewed, 5 comments
Edit PR Review Bot Settings | Greptile

}

const payload = `${timestamp}.${req.rawBody.toString()}`
const hmac = crypto.createHmac('sha256', this.hub.MAILJET_SECRET_KEY).update(payload).digest()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: MAILJET_SECRET_KEY might be undefined here. Add validation or provide a default value to prevent runtime errors.

@mcharawi mcharawi requested a review from benjackwhite June 13, 2025 00:29
@@ -79,6 +81,7 @@ export class CdpApi {
router.get('/api/projects/:team_id/hog_functions/:id/status', asyncHandler(this.getFunctionStatus()))
router.patch('/api/projects/:team_id/hog_functions/:id/status', asyncHandler(this.patchFunctionStatus()))
router.get('/api/hog_function_templates', this.getHogFunctionTemplates)
router.post('/public/messaging/mailjet_webhook', asyncHandler(this.postMailjetWebhook()))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you given any thought as to how this would work for the different regions? EU / US? Do we have different mailjet accounts or something?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah we have 3 subaccounts, one for each environment:
image

}

// Track Mailjet webhook metrics
// TODO: Zod validation
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should arguably validate the payload rather than a cast here. We can sort of trust it due to the signature validation but nonetheless

// Track Mailjet webhook metrics
// TODO: Zod validation
const event = req.body as MailjetEvent
const category = EVENT_TYPE_TO_CATEGORY[event.event as keyof typeof EVENT_TYPE_TO_CATEGORY]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the "as" cast isn't great. This could lead to an undefined category (the typing is incorrect)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typed the event field in the web hook body and added a type guard

const event = req.body as MailjetEvent
const category = EVENT_TYPE_TO_CATEGORY[event.event as keyof typeof EVENT_TYPE_TO_CATEGORY]

if (event) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

General comment - tests 😅 tests tests tests

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added some unit testing to mailjet-manager.service.test.ts, not sure if you want them in a separate file or if they are better as part of the CDP API tests in cdp-api.test.ts

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No here makes most sense. an e2e test at some point will be good but the bulk of testing should be localised to the service itself for sure

@github-project-automation github-project-automation bot moved this from Todo to In Review in Feature Flags Jun 13, 2025
@haacked haacked removed this from Feature Flags Jun 13, 2025
@mcharawi mcharawi requested a review from benjackwhite June 16, 2025 02:52
Copy link
Contributor
@benjackwhite benjackwhite left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing blocking but the clean up of the tests would be great so that we start as we mean to carry on

import { parseJSON } from '../../../utils/json-parse'
import { MessagingMailjetManagerService } from './mailjet-manager.service'

describe('MessagingMailjetManagerService', () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm picky about tests because tests are important but also a source of pain over time if they aren't well maintained. A few things that could be done way better here commented where they are

const event = req.body as MailjetEvent
const category = EVENT_TYPE_TO_CATEGORY[event.event as keyof typeof EVENT_TYPE_TO_CATEGORY]

if (event) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No here makes most sense. an e2e test at some point will be good but the bulk of testing should be localised to the service itself for sure

@mcharawi mcharawi merged commit f740274 into master Jun 16, 2025
99 checks passed
@mcharawi mcharawi deleted the feat/mailjet-webhooks branch June 16, 2025 19:32
adamleithp pushed a commit that referenced this pull request Jun 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants
0