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

Stampie Laravel Package

henrikbjorn/stampie

Stampie is a PHP library for sending email through API-based providers such as Mailgun, Mandrill, Postmark, and SendGrid. It provides a consistent mailer and message API, making it easy to switch transactional email services without rewriting your sending code.

View on GitHub
Deep Wiki
Context7

Getting Started

  • Install from the repository/Packagist source. The package name and namespace may not match modern stampie/stampie conventions, so first verify composer.json (name, autoload, PHP/Guzzle constraints) before running:
composer require henrikbjorn/stampie
  • Look first at:
    • README.md for the supported providers and minimal examples.
    • src/Stampie/Mailer/ for concrete provider mailers (Mailgun, SendGrid, Postmark, Mandrill, etc.).
    • src/Stampie/Message/ for the message object and attachment handling.
    • src/Stampie/Adapter/ for the HTTP transport (historically Guzzle/Buzz).
    • tests/ for exact constructor signatures and expected request payloads.
  • First use case: send one transactional email through a provider from a Laravel command or queued job. Start with a single provider rather than building a provider-agnostic abstraction.
use Stampie\Adapter\Guzzle;
use Stampie\Mailer\Mailgun;
use Stampie\Message\Message;

$mailer = new Mailgun(
    new Guzzle(new \GuzzleHttp\Client()),
    config('services.mailgun.domain'),
    config('services.mailgun.secret')
);

$message = (new Message())
    ->setSender('[email protected]', 'My App')
    ->setTo('[email protected]')
    ->setSubject('Welcome')
    ->setText('Welcome!')
    ->setHtml('<h1>Welcome!</h1>');

$mailer->send($message);
  • In Laravel, bind the configured mailer once in a service provider so jobs/controllers do not construct adapters repeatedly:
// AppServiceProvider::register()
$this->app->singleton(\Stampie\Mailer::class, function () {
    return new \Stampie\Mailer\Mailgun(
        new \Stampie\Adapter\Guzzle(new \GuzzleHttp\Client()),
        config('services.mailgun.domain'),
        config('services.mailgun.secret')
    );
});

Implementation Patterns

  • Keep provider configuration in config/services.php and .env, never inline secrets:
// config/services.php
'mailgun' => [
    'domain' => env('MAILGUN_DOMAIN'),
    'secret' => env('MAILGUN_SECRET'),
],
  • Wrap Stampie behind your own small service instead of injecting provider mailers directly into controllers. This keeps provider-specific payload details out of application code:
final class TransactionalMailer
{
    public function __construct(private \Stampie\Mailer $mailer) {}

    public function sendWelcome(User $user): void
    {
        $message = (new \Stampie\Message\Message())
            ->setSender(config('mail.from.address'), config('mail.from.name'))
            ->setTo($user->email, $user->name)
            ->setSubject('Welcome')
            ->setText(view('mail.welcome-text', compact('user'))->render())
            ->setHtml(view('mail.welcome', compact('user'))->render());

        $this->mailer->send($message);
    }
}
  • Use a dedicated message factory/builder for repeated fields (From, Reply-To, common headers, provider tags). Laravel Mailables are a good model, but do not try to reproduce the whole Laravel mail stack unless needed.
  • Send through queued jobs. Provider HTTP calls are I/O-bound; retries and timeouts belong on the job/queue, not inside the mailer:
final class SendWelcomeEmail implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public int $tries = 3;

    public function __construct(public User $user) {}

    public function handle(TransactionalMailer $mailer): void
    {
        $mailer->sendWelcome($this->user);
    }
}
  • Use provider-specific features deliberately:

    • Mailgun: domain, tags, delivery-time options.
    • SendGrid: categories, templates, substitutions.
    • Postmark: message streams, templates, tag metadata.
    • Mandrill: templates and merge variables. If you only need plain transactional email, a generic Message is enough. Add provider-specific payloads only when a feature requires it.
  • For testing, inject a fake adapter rather than hitting the provider. If the adapter is Guzzle-based, use Guzzle’s MockHandler; otherwise implement the package’s adapter interface and return a canned response. Assert on the captured request body, not just “send was called.”

  • Log the provider response/message ID after a successful send. That ID is usually what provider support needs when debugging delivery.

  • If migrating from Laravel’s native mailer, put Stampie behind an interface and keep call sites unchanged. This makes it possible to revert to Laravel mail or Symfony Mailer later without rewriting application code.

Gotchas and Tips

  • Maintenance risk is real. This is an older, low-star package. Check the repository’s last commit, open issues, PHP version support, and especially the Guzzle major version. Pin the package and its HTTP client dependency in composer.json.
  • Confirm the actual package name and namespace. Historical Stampie releases used different package/namespace layouts (henrikbjorn/stampie vs stampie/stampie); do not assume class names from an old blog post.
  • Adapters usually return a response object even for provider errors. Do not assume send() throws on a 4xx/5xx. Inspect the response status and body, and throw your own exception so queue retries work correctly.
  • Provider prerequisites are the most common source of “it sends from my machine but not production” bugs:
    • Mailgun requires a verified domain or authorized recipients.
    • Postmark requires a verified sender signature and the correct server token.
    • SendGrid requires a verified sender/domain and may enforce categories/templates.
  • Always set both text and html parts. Some providers reject messages without a text fallback; some spam filters score HTML-only mail poorly.
  • Attachments can be memory-heavy. Prefer file paths/streams when the adapter supports them, and enforce size limits before sending. Do not base64-encode large PDFs in PHP if the provider supports multipart uploads.
  • Respect provider rate limits and recipient limits. Batch APIs are not the same as adding many To addresses; misuse can get an account throttled.
  • Configure HTTP timeouts and retries explicitly. A default Guzzle client with no timeout can hang a queue worker.
  • Laravel config caching will hide runtime env() calls. Keep all provider credentials in config files, and clear/rebuild config after changes.
  • Be careful with Bcc and provider-specific headers. Some providers strip or rewrite headers; verify in the provider dashboard.
  • Debugging tips:
    • Add Guzzle middleware or a logging adapter to capture method, URL, and request body.
    • Never log full message bodies or API keys in production.
    • Compare the raw request against the provider’s API docs; field names and nesting differ significantly between providers.
    • Use the provider’s activity/event log to distinguish “request rejected” from “accepted but not delivered.”
  • Extension points:
    • Implement the package’s adapter interface to swap HTTP clients or add tracing.
    • Subclass a provider mailer to change endpoint/region or add provider-specific fields.
    • Create a custom message class if you need reusable headers/tags, but keep it implementing the package’s message interface.
  • If all you need is SMTP/API transactional mail with Laravel-native drivers, prefer Laravel’s built-in mailer or Symfony Mailer. Use Stampie when you specifically need its provider payload abstractions or are maintaining an existing integration.
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.
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log