stackinstance/mailer-bundle
A Laravel/PHP mailer bundle that packages mail transport, configuration, and sending utilities into a reusable service, helping developers integrate email delivery into applications with a simpler, bundle-style setup.
stackinstance/mailer-bundle is a low-signal package (no stars, no dependents, no description beyond "Stack Instance Mailer"), so treat the README and composer.json in the repository as the primary source of truth before writing any code against it. The bundle naming convention strongly suggests a Symfony bundle wrapping a "Stack Instance" transactional mail API, but confirm the framework target, supported PHP version, and Symfony version constraints before adopting it.
Minimal steps:
Install and inspect.
composer require stackinstance/mailer-bundle
Immediately open vendor/stackinstance/mailer-bundle/composer.json and the bundle class (usually StackInstance\MailerBundle\StackInstanceMailerBundle or similar). Check:
config/bundles.php auto-registration) or requires manual registration.Register the bundle if it wasn't auto-registered:
// config/bundles.php
return [
// ...
StackInstance\MailerBundle\StackInstanceMailerBundle::class => ['all' => true],
];
Configure credentials via environment variables, never hard-coded. Look for the bundle's configuration tree (DependencyInjection/Configuration.php) to see the exact keys — typical shape:
# config/packages/stack_instance_mailer.yaml
stack_instance_mailer:
api_key: '%env(STACK_INSTANCE_API_KEY)%'
base_uri: '%env(STACK_INSTANCE_BASE_URI)%'
from_address: '%env(MAIL_FROM_ADDRESS)%'
from_name: '%env(MAIL_FROM_NAME)%'
Add the corresponding entries to .env and .env.local, and ensure the real values live only in your secret manager / deployment environment.
First use case: a single transactional email. The most likely entry point is an injected mailer service. Find the service ID with:
php bin/console debug:container --tag=mailer # or grep the bundle's services.yaml
Then send one real message from a console command or bin/console shell before wiring it into application flows. Prove the credential path, the from address, and the response handling end-to-end with the smallest possible surface area.
Look at the bundle's own tests (vendor/stackinstance/mailer-bundle/tests/). For an undocumented package this is often more accurate than the README and will show you the expected message payload shape and how the HTTP client is stubbed.
Wrap the bundle behind your own interface. Given the package's maturity signals, do not let its concrete classes leak into controllers or domain services. Define a small application-level port and adapt the bundle to it:
interface TransactionalMailer
{
public function send(EmailMessage $message): void;
}
final class StackInstanceMailerAdapter implements TransactionalMailer
{
public function __construct(private readonly StackInstanceMailer $inner) {}
public function send(EmailMessage $message): void
{
// map your value object onto the bundle's payload/message class
}
}
This costs an hour and buys you the ability to swap providers without touching call sites.
Send asynchronously by default. Transactional sends should not block a web request. Wrap the adapter in a Symfony Messenger handler so the mail is dispatched to a queue:
final class SendEmailHandler
{
public function __construct(private readonly TransactionalMailer $mailer) {}
public function __invoke(SendEmail $command): void
{
$this->mailer->send($command->message);
}
}
The bundle's synchronous API maps naturally onto a message handler; retries and failure transport then come from Messenger rather than from the package.
Prefer the bundle's templating hook over string concatenation. If the package supports template IDs or server-side templates (common for hosted mail APIs), use those instead of building HTML in PHP. It keeps content editable by non-developers and avoids escaping bugs. If it only accepts raw HTML, render with Twig in your own layer and pass the result in.
Centralize the from identity. Configure a single default sender and only override per-message when there is a real product reason (e.g. per-tenant branding). Scattered from addresses are the most common cause of deliverability problems and confusing support tickets.
Testing pattern. If the bundle exposes a transport or mailer interface, bind a no-op or in-memory implementation in config/services_test.yaml so the test suite never makes network calls. If it doesn't, wrap it (see the adapter above) precisely so this is possible:
# config/services_test.yaml
services:
App\Mail\TransactionalMailer:
class: App\Mail\InMemoryMailer
Assert on the captured messages rather than on HTTP mocks — it survives provider changes.
composer why-not symfony/framework-bundle <version> after installing to see whether this package is the blocker.php bin/console cache:clear — parameter resolution and env var inlining behave differently between dev and a warmed prod cache. A misconfigured env() reference often surfaces only after cache:warmup.%env()% correctly you're fine; if it reads getenv() directly in a constructor, the service will fail when the var is absent even in commands that never send mail. Check how the API key is consumed.base_uri, and observe: does it throw a typed exception, return false, or silently swallow the error? Wrap all calls in your adapter and normalize to a single exception type so upstream code is not coupled to the package's error style. Log the provider's response body — hosted mail APIs return actionable diagnostics in the body, not in the status code.framework.rate_limiter) rather than discovering the limit in production.services.yaml. If the bundle defines one, you can inject a decorated client for logging, metrics, or local capture without forking. If it defines none, treat the package as a leaf dependency and keep all customization in your adapter.How can I help you explore Laravel packages today?