Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Postmark Bundle Laravel Package

mlpz/postmark-bundle

mlpz/postmark-bundle provides Symfony integration for Postmark transactional email. It offers bundle configuration and services for sending messages through Postmark's API, making it straightforward to add reliable email delivery to Symfony applications.

View on GitHub
Deep Wiki
Context7

Getting Started

First, the reality check: mlpz/postmark-bundle is a Symfony 2 bundle, not a Laravel package. It is archived, its last release was September 2013, and it has zero dependents. There is no ServiceProvider, no facade, no publishable config — Laravel's container cannot register a Symfony bundle, so you cannot "install and use" this in a Laravel app in any conventional sense.

What you can do day-to-day is treat it as a reference implementation and build the actual integration with supported tooling.

Minimal steps if you are evaluating it anyway:

  1. Read the source, not the README. Look at DependencyInjection/ (the config tree and service wiring), Resources/config/services.*, and whatever sits under a Transport/ or Mailer/ directory. That is the entire surface area of the package.
  2. Note the config keys it expects (historically a postmark: block in config.yml with an API/server token and optional public key). These map one-to-one onto what you would put in config/services.php and .env.
  3. Run composer why-not mlpz/postmark-bundle against your project before doing anything else. On PHP 8 / Symfony 6+ you will get a hard constraint failure because the package pins PHP 5.3-era and Symfony 2.x requirements.

First use case: sending a single transactional email through Postmark's /email endpoint. In Laravel today that is:

composer require symfony/postmark-mailer
MAIL_MAILER=postmark
POSTMARK_TOKEN=your-server-token

and then a normal Mailable. Nothing in this bundle improves on that path.

Implementation Patterns

1. Port, don't install. The useful artifact here is the shape of the Postmark payload the bundle builds: From, To, Cc, Bcc, Subject, HtmlBody, TextBody, Tag, TrackOpens, ReplyTo, Headers, Attachments. Copy that field list into a Laravel Mailable or a small DTO and you have reproduced the bundle's value in an hour.

2. Use Laravel's mailer, not a hand-rolled client. Laravel 9+ ships a first-party Postmark transport via symfony/postmark-mailer. Configure config/mail.php, keep credentials in config/services.php, and send through Mail::to(...)->send(...). This gives you queueing, events, Mail::fake() in tests, and local log/array drivers for free — none of which the bundle offers.

3. Reach for the SDK when you need more than mail. For inbound webhooks, templates, message streams, or batch sends, use wildbit/postmark-php (the official SDK) or plain Http::withHeaders(['X-Postmark-Server-Token' => ...])->post('https://api.postmarkapp.com/email', $payload). Wrap either behind an interface:

interface TransactionalMailer {
    public function send(TransactionalMessage $message): string; // returns MessageID
}

Bind a Postmark implementation in a service provider and a FakeMailer in tests. This is the pattern the bundle was trying to provide for Symfony's container; you get a better version of it with Laravel's container for free.

4. Migrating off the bundle. If you are porting a legacy Symfony 2 app to Laravel, map $this->get('postmark.message')-style calls to an injected TransactionalMailer service, and convert Swiftmailer \Swift_Message construction into Mailable classes. Do the translation at the boundary (one adapter class) rather than rewriting every call site.

5. Keep the raw-API escape hatch. Some Postmark features (message streams, metadata, TrackLinks) are easier to hit directly than to thread through a mailer abstraction. A thin PostmarkClient wrapper around Http is the pragmatic middle ground.

Gotchas and Tips

  • It will not install. PHP 5.3-era require constraints, Symfony 2.x bundle structure, no composer.json compatibility with PHP 8. Do not spend time trying to force it; the failure is structural, not a version-pin tweak.
  • The API moved on since 2013. Postmark now requires a message stream (X-Postmark-Message-Stream header or MessageStream field) and uses server tokens rather than the older account-level keys. Any payload copied verbatim from this bundle will get a 422 with an ErrorCode explaining exactly what is missing.
  • Error handling is opaque. Postmark returns structured errors as {"ErrorCode": 300, "Message": "..."} with a 422. Whatever exception handling this bundle had is almost certainly a generic \Exception; reimplement with a typed exception that carries ErrorCode so you can distinguish "inactive recipient" (406) from "invalid API token" (401) in logs.
  • Debugging: the send response includes a MessageID header — log it. That ID is what Postmark's Activity feed and webhook payloads key on, and it is the fastest way to trace a "user says they didn't get the email" ticket.
  • Queue everything. Postmark's API is fast but not free of latency or rate limits; a synchronous send inside a request cycle is a self-inflicted wound. Mail::queue() or a queued job wrapping your TransactionalMailer.
  • No extension points to speak of. The bundle is not maintained, so "extend it" means fork it — at which point you own a Symfony 2 bundle in a Laravel codebase. Prefer the official SDK or the first-party transport.
  • Supply chain risk. An archived, zero-dependent, decade-old package with no security process should not be a production dependency. If it is already in a composer.json you inherited, run composer audit and plan removal.
  • Where to actually look first if you are curious about intent: the bundle's DI extension and its message-building code. That is the whole package; everything else is Symfony 2 boilerplate.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings