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

Mailer Bundle Laravel Package

happyr/mailer-bundle

Happyr MailerBundle is a Symfony bundle that provides mailer services and helpers for composing and sending email messages. It centralizes email configuration and offers a simple API for integrating mail delivery into Symfony applications.

View on GitHub
Deep Wiki
Context7

Getting Started

1. Confirm you can actually install it. This bundle targets Symfony 2.x/3.x and Swiftmailer. Check composer.json in the repo before anything else — the 2.x line and the new autowire support in 2.1.6 mean the Symfony YAML service loader must understand the autowire key, which only exists from Symfony 3.3. On Symfony 2.8 the loader rejects unknown keys in a service definition, so you may now get an Unrecognized option "autowire" failure at container compile that did not exist in 1.x. On Symfony 4+ you're still fighting services.yml vs services.yaml and deprecated container passes. On a modern app, stop here and plan a migration instead (see Gotchas).

2. Install and register.

composer require happyr/mailer-bundle:^2.1
// AppKernel.php (Symfony 3.3+)
new Happyr\MailerBundle\HappyrMailerBundle(),

Swiftmailer must already be configured (swiftmailer:) — this bundle wraps a real mailer, it doesn't ship a transport.

3. Look here first, in this order:

Path Why
README.md The only documentation that exists; 7 stars means no blog posts, no Stack Overflow
DependencyInjection/Configuration.php The authoritative list of config keys — trust this over the README
Resources/config/services.yml Service IDs, aliases, and (from 2.1.6) the autowire flags you can now rely on
Mailer/Mailer.php The actual behaviour; read it top to bottom, it's short

4. First use case — send a message through the bundle's mailer service instead of \Swift_Mailer directly. Since 2.1.6 the bundle's services are declared with autowire: true, so on Symfony 3.3+ a constructor type-hint on the bundle's mailer interface resolves without you registering a service definition by hand:

use Happyr\MailerBundle\Mailer\MailerInterface;

final class WelcomeMailer
{
    private $mailer;
    private $twig;

    public function __construct(MailerInterface $mailer, \Twig_Environment $twig)
    {
        $this->mailer = $mailer;
        $this->twig = $twig;
    }

    public function send(string $to): void
    {
        $message = (new \Swift_Message('Welcome'))
            ->setFrom('[email protected]')
            ->setTo($to)
            ->setBody($this->twig->render('emails/welcome.html.twig'), 'text/html');

        $this->mailer->send($message);
    }
}

Autowiring only works if the interface alias is registered and unambiguous. Run bin/console debug:container | grep -i mailer to see the exact service ID and alias in your pinned version — the interface name has changed across releases, and a bare \Swift_Mailer alias sitting alongside it will make autowiring ambiguous.


Implementation Patterns

Wrap it, don't sprinkle it. Create one App\Mailer\AppMailer that composes the messages (Twig rendering, setTo, headers, locale) and delegates to the bundle mailer. Every controller/listener calls AppMailer. This gives you a single seam to swap in Symfony Mailer + Messenger later, which you will almost certainly need to do.

Let autowire do the wiring, but be explicit where it matters. 2.1.6 makes the common case (type-hint MailerInterface) work with zero config, which is a genuine ergonomics win. Do not extend that to the mailer's internals — if you ever need the underlying transport or spool, inject those by explicit service ID so a future bundle change to the alias list doesn't silently rewire you.

Message construction stays outside the mailer. Build a Swift_Message in your domain service, then hand it over. Don't pass entities or arrays into the mailer service — it will make background sending impossible, since anything queued must be serialisable.

Async / background sending. The bundle's main value-add over raw Swiftmailer is queueing work (send-in-background / delayed send). The pattern:

// web request: enqueue only, never touch SMTP
$mailer->sendLater($message, $delayInSeconds);

// worker process (supervisor or cron):
// bin/console <bundle's consume/worker command> --limit=100

Keep queued messages self-contained: inline images and attachments bloat the payload and break across deploys if the serialised format changes. Prefer storing a path/URL and rehydrating in the worker.

Use the event hook for cross-cutting concerns. The bundle dispatches an event when a message is about to go out. Register a subscriber for:

  • rewriting all recipients to a catch-all address when kernel.environment !== 'prod' (the single most valuable use),
  • stamping X-Request-Id / tenant headers,
  • BCC-ing an archive mailbox,
  • aborting sends for suppressed addresses.

Testing. Don't mock the bundle's mailer in unit tests — swap the whole service for a spy in config_test.yml. Because the bundle is now autowired, an explicit service definition still wins over the autowired alias, so this override keeps working:

services:
    app.mailer_spy:
        class: App\Test\MailerSpy       # collects Swift_Message objects
    Happyr\MailerBundle\Mailer\MailerInterface: '@app.mailer_spy'

Then assert on getTo(), getSubject(), getBody() — cheap, fast, and it survives the migration to Symfony Mailer with only the message class changed. If your spy is not being used, that is a signal autowiring resolved the interface elsewhere; check debug:container --show-arguments.

Integration tip: if you already have a swiftmailer.spool configured, be explicit about which mechanism owns async delivery. Having both a spool and the bundle's queue means two workers and confusing double-delivery bugs.


Gotchas and Tips

Still effectively unmaintained. 2.1.6 is a single patch release arriving years after the 2018-11-06 release, from a package with 7 stars and 0 dependents. Swiftmailer reached EOL in November 2021 and Symfony 2/3 are long EOL. One commit does not change the risk profile — treat it as "read the source and vendor it" territory, not "composer require and forget."

2.1.6 can break older Symfony installs. autowire: true in a bundle's services.yml is only understood by Symfony 3.3+. If you pinned the bundle on a Symfony 2.8 or early 3.x app, this patch release may fail at container compile with an unrecognized-key error. Test the upgrade on a branch; if it breaks, pin ^2.0 <2.1.6 and record why.

Autowire ambiguity. Adding autowire support means the bundle's aliases now compete with every other mailer-ish service in your container (notably swiftmailer.mailer). Symptom: Cannot autowire service ... argument $mailer ... references interface ... but no such service exists or, worse, the wrong mailer injected silently. Fix with an explicit alias in your app config rather than by removing the bundle's declaration.

The migration target is small. Symfony Mailer + Messenger covers everything this bundle does: MailerInterface::send(Email $email) for sync, $bus->dispatch(new SendEmailMessage($email)) for async, MessageEvent for the pre-send hook, and InMemoryTransport for tests. If you're starting fresh, write the ~40 lines yourself rather than adding this dependency.

Config key drift. Configuration.php is the truth. Older READMEs and blog snippets reference keys that were renamed or removed; a bad key silently does nothing because the bundle doesn't enable strict config validation in every version.

Remaining container compilation failures on newer Symfony. Autowire support removed one cause, not all of them. Still expect: %kernel.root_dir% (removed in SF4) in the bundle's service definitions, compiler passes using APIs deprecated since 3.4, and services.yml naming clashes. Fix by overriding Resources/config/services.yml in your app, not by patching vendor/ (use composer patches if you must, since vendor/ is disposable).

Serialised Swift_Message is fragile. If you queue messages, any change to the bundle or Swiftmailer version can make in-flight jobs unserialisable — the worker throws and the job retries forever. This is doubly true when upgrading to 2.1.6: drain the queue before deploying, and add a failed transport/message handler.

Debugging checklist:

bin/console debug:container Happyr          # what's actually registered
bin/console debug:container --show-arguments Happyr\\MailerBundle\\Mailer\\MailerInterface
                                            # confirm autowire resolved the service you expect
bin/console debug:event-dispatcher          # confirm your listener is wired
bin/console swiftmailer:spool:send          # if a spool is in play

For "did it even try to send", temporarily enable Swift_Plugins_LoggerPlugin or set the transport to null in dev — a null transport proves message construction without touching the network, and isolates whether the bug is in your message or in the sending layer.

Extension points, ranked by usefulness:

  1. Decorating the mailer interface — safest; no bundle internals touched, trivially removable, and 2.1.6's autowiring makes the decoration registration the only thing you write.
  2. Event subscriber — the sanctioned hook; use it for dev-redirects and headers.
  3. Overriding Resources/config/services.yml in your app — works but every bundle upgrade is a merge conflict, and 2.1.6 just changed that file.
  4. Patching the bundle's classes — avoid; it's the thing that makes removal expensive.

Pin everything. composer require happyr/mailer-bundle:^2.1 plus a composer.lock committed, and add the repo to your tech-debt register with a named owner and an exit date. A bundle with 7 stars has no maintainer to answer your issue — budget for reading ~500 lines of PHP yourself when something breaks.

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.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings