This project is not covered by Drupal’s security advisory policy.
Postmark Webhooks receives bounce, spam complaint, delivery and subscription-change notifications and applies suppression before Drupal mail transport. Pair it with the Postmark module or another sending backend.
Features
- HTTP Basic Auth with timing-safe comparison, settings-only credentials and bounded-overlap secret rotation. Optional named source profiles bind independently rotated credentials to server and stream pairs.
- Event-aware identity and atomic retry handling preserve distinct events and recipients.
- Durable suppression survives event-history retention. Provider event times and source context keep delayed events from overwriting newer evidence.
- Checks every To, Cc and Bcc recipient before core mail transport. An optional Mailer Plus adapter covers native and compatibility mail pipelines.
- Consent-aware SubscriptionChange processing and audited, source-specific hard-bounce recovery.
- Protected inspection, no-send policy previews, structured Drush diagnostics, health evaluation and intake counters.
- Permission-controlled recipient export, confirmed bounded history erasure, and an optional MessageID timeline. Minimal suppression and audit evidence remain. When audit_chain is installed, operator export, erasure and hard-bounce recovery are also appended to that chain (hashed subject, uid and optional target only). Webhook intake is not written to the chain.
- Optional read-only Postmark reconciliation: review differences, then apply local imports in resumable batches. No provider writes or automatic reactivation.
Installation and configuration
Install with composer require 'drupal/postmark_webhooks:^1.2' and enable Postmark Webhooks. Store the password in settings.php:
$settings['postmark_webhooks.webhook_secret'] = getenv('POSTMARK_WEBHOOK_SECRET') ?: '';Visit /admin/config/services/postmark-webhook for the routed endpoint, suppression settings and diagnostics. Configure Postmark to send webhooks to that HTTPS endpoint with HTTP Basic Auth, username postmark and the configured password. Preserve the Authorization header through proxies. The endpoint returns 503 without a configured password and 401 for missing or incorrect credentials. Secrets never appear in exported configuration or the settings page.
HardBounce, BadEmailAddress, ManuallyDeactivated and Unsubscribe suppress without a time window. Transient and soft-bounce types use a configurable window, defaulting to 30 days. Complaints have no time limit by default. History retention defaults to 90 days and no longer removes durable suppression. Source policies are optional; existing sites retain the site-wide default.
Requirements and optional integrations
PHP 8.3 or later and Drupal 10.3 or 11. PostgreSQL 16 is the default CI database; MySQL 8.4, MariaDB 10.11 and SQLite are also verified. The optional Postmark Webhooks Mailer adapter is tested with Mailer Plus 1.6.2 and 2.0.2. The receiver needs no API token; the optional reconciliation module reads server tokens from settings. Optional audit_chain dual-write of operator audits is a Composer suggest; there is no hard dependency on Key or Encrypt.
Upgrading
From 1.0.1, run composer require 'drupal/postmark_webhooks:^1.2' and drush cache:rebuild. There is no new update hook. Enable audit_chain separately if you want the optional operator-audit dual-write.
From 1.0.0, back up the database, run composer require 'drupal/postmark_webhooks:^1.2', then drush updatedb -y and drush cache:rebuild. Drupal 11 sites that failed update 10007 on 1.0.0 can complete that update on 1.0.1 or later.
From 1.0.0-alpha2, back up the database, require ^1.0, then run drush updatedb -y and drush cache:rebuild. Update 10007 creates the empty integration outbox table. Optional health, source profiles, integration events, scheduled reconciliation, MessageID timeline and extra retention draining stay off until configured.
From 1.0.0-alpha1, run every update through 10007, including restartable 250-row batches. Updates preserve retained events, backfill suppression state and remove legacy provider free text. Previously discarded history cannot be recovered locally. Review suppression policy before resuming mail; optional submodules must be enabled separately. There is no supported downgrade.
Limits
- Direct Symfony transports and custom recipient changes after the supported adapter boundary are outside its coverage.
- Erasing event history retains minimal suppression and audit evidence. Backups, provider records and downloaded exports require their own handling. Optional audit_chain dual-write is fail-open and never receives a mailbox.
- Reconciliation reads bounded, date-filtered suppression dumps; oversized dumps require a separately reviewed migration. It does not import complete delivery history or clear consent because a record is absent.
- This module does not send mail or parse inbound email. Named source profiles are optional; the shared webhook secret remains the default.
Optional MCP tools
The optional postmark_webhooks_mcp submodule exposes Tool API plugins so a governed agent can read health, diagnostics, delivery preview, message timeline, outbox status and drift reports. The base module does not depend on MCP. Enable the submodule only with MCP Sentinel. Pair the site with the Drupal MCP Connector (source) so those tools appear in an MCP client. Restricted permissions ship granted to no role.
Support
Maintained by Jeremy Michael Cerda. Development sponsored by Wilkes & Liberty, LLC. Licensed under GPL-2.0-or-later. Listed in the Chronicle package group on Extend.
Project information
- Project categories: Integrations
- Ecosystem: Postmark, Mail System
10 sites report using this module
- Created by jmcerda on , updated
This project is not covered by the security advisory policy.
Use at your own risk! It may have publicly disclosed vulnerabilities.
