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

Ecomail Laravel Package

ecomailcz/ecomail

Laravel integration for the Ecomail.cz email marketing API. Manage mailing lists, subscribers, tags, custom fields, campaigns, and events with a fluent client, facades, and config-based authentication for newsletter and transactional workflows.

View on GitHub
Deep Wiki
Context7

Getting Started

ecomailcz/ecomail is the official PHP wrapper for the Ecomail.cz transactional/marketing API — not a Laravel package. There is no auto-discovery, no facade, no config file. You get a PSR-4 autoloaded set of classes under Ecomail\ and a Guzzle client underneath. Your first job as a Laravel dev is to wrap it.

composer require ecomailcz/ecomail

Where to look first: the repo README for the resource list (lists, subscribers, and the campaign/webhook resources as they exist in your pinned version), then Ecomail's API docs at https://api2.ecomailapp.cz/. Method names drift between releases — trust the README shipped with the version you install, not blog posts.

Bind it as a singleton so the Guzzle client is reused:

// config/services.php
'ecomail' => ['key' => env('ECOMAIL_API_KEY')],

// App\Providers\AppServiceProvider::register()
$this->app->singleton(\Ecomail\Ecomail::class, fn () =>
    new \Ecomail\Ecomail(config('services.ecomail.key'))
);

First use case — the one that covers 80% of real work — is pushing a subscriber onto a list:

$ecomail = app(\Ecomail\Ecomail::class);
$ecomail->subscribers->create($listId, [
    'email' => $user->email,
    'name'  => $user->name,
    'subscriber_status' => 1, // 1 = subscribed
]);

Implementation Patterns

Wrap it in a domain service. Controllers and jobs should never touch Ecomail\Ecomail directly. A NewsletterService (or EcomailClient interface) with methods like subscribe(User $u, int $listId) keeps the SDK at the edge, makes it swappable, and lets you mock your own boundary instead of a concrete third-party class.

Queue everything. The SDK is synchronous Guzzle — every call blocks. Never call it inside a web request. Dispatch a job on a dedicated marketing or ecomail queue with tries = 3 and backoff = [10, 60, 300]. Rate limits are the usual reason to isolate this queue.

Event-driven subscription. UserRegistered → SubscribeToNewsletter listener that dispatches the queued job. This is the clean Laravel shape and keeps signup latency decoupled from Ecomail availability.

Bulk imports. For backfills, chunk by a few hundred, dispatch one job per chunk, and let the queue serialise them. Don't loop tens of thousands of subscribers in a single job — you'll hit the timeout and the rate limit at the same time.

Webhooks are your responsibility. Ecomail can push opens, clicks, bounces and unsubscribes back to you, but the SDK does not help — you write a plain route/controller, verify the payload, and reconcile against your own subscriber state. This is the pattern most teams need on day two.

Testing. Fake your wrapper service ($this->mock(NewsletterService::class)). If you must test the SDK layer itself, inject a Guzzle MockHandler — but don't hit the live API in CI, and don't try to Mockery::mock(\Ecomail\Ecomail::class) if it has final methods.

Gotchas and Tips

  • Package vs. repo name mismatch. The repo is ecomailcz/ecomail-php but the Composer package is ecomailcz/ecomail. Double-check what you actually installed before debugging "class not found".
  • API key only, no OAuth. Keys are per-account. Keep them in .env, never log them, and rotate via Ecomail's dashboard if leaked.
  • Guzzle exceptions are raw. Catch GuzzleHttp\Exception\ClientException (4xx, including 401 bad key and 422 validation) separately from ServerException (5xx). 429 means rate limited — retry with backoff, don't hammer.
  • subscriber_status is a footgun. Getting the integer wrong silently unsubscribes people or marks them unconfirmed. Treat it as a constant, not a magic number.
  • List IDs vs. list keys. Most methods want the numeric ID; some endpoints accept a slug. Mixing them up returns 404s that look like auth failures.
  • The wrapper lags the API. Newer Ecomail endpoints frequently aren't exposed yet. Fallback: reach for the underlying client, or just issue a raw Guzzle call to https://api2.ecomailapp.cz/... with the same key. Keep a thin raw() helper on your service for exactly this.
  • Cache static-ish reads. lists->all() and custom-field definitions change rarely — cache for a few minutes to stay well under rate limits and to avoid a cold API call on every page render.
  • Maintenance signal. 17 stars, zero dependents, low release cadence. Pin the exact version in composer.json and budget for occasionally dropping to raw HTTP when a method you need doesn't exist. Don't build your architecture assuming the SDK will grow with your needs — your NewsletterService wrapper is the abstraction that protects you.
  • GDPR / residency. Ecomail is a Czech provider with EU data residency, which is usually a feature for EU apps — but double opt-in and consent records still live on your side. Don't rely on the API call to prove consent.
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.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource