PHPackages                             andrewdyer/mailer - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Templating &amp; Views](/categories/templating)
4. /
5. andrewdyer/mailer

ActiveLibrary[Templating &amp; Views](/categories/templating)

andrewdyer/mailer
=================

A framework-agnostic library for sending emails from Twig templates, with support for a swappable transport interface.

0.1.1(1mo ago)00[1 issues](https://github.com/andrewdyer/mailer/issues)MITPHPPHP ^8.3CI passing

Since May 28Pushed 1mo agoCompare

[ Source](https://github.com/andrewdyer/mailer)[ Packagist](https://packagist.org/packages/andrewdyer/mailer)[ Docs](https://github.com/andrewdyer/mailer)[ RSS](/packages/andrewdyer-mailer/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (2)Dependencies (8)Versions (4)Used By (0)

Mailer
======

[](#mailer)

A framework-agnostic library for sending emails from Twig templates, with support for a swappable transport interface.

[![Latest Stable Version](https://camo.githubusercontent.com/f40565157076100627ce77aff7b5a32a5632602e78040ca90c3448c4d9245d21/687474703a2f2f706f7365722e707567782e6f72672f616e64726577647965722f6d61696c65722f763f7374796c653d666c61742d737175617265)](https://packagist.org/packages/andrewdyer/mailer)[![Total Downloads](https://camo.githubusercontent.com/62dc2267f635d42688ea86934faeb714baeff93f31cf54b8b59a21d1c34206b7/687474703a2f2f706f7365722e707567782e6f72672f616e64726577647965722f6d61696c65722f646f776e6c6f6164733f7374796c653d666c61742d737175617265)](https://packagist.org/packages/andrewdyer/mailer)[![License](https://camo.githubusercontent.com/0395c021d733fdae300a24d837d27a2a352530685d1e62b488c597fc4fa615a7/687474703a2f2f706f7365722e707567782e6f72672f616e64726577647965722f6d61696c65722f6c6963656e73653f7374796c653d666c61742d737175617265)](https://packagist.org/packages/andrewdyer/mailer)[![PHP Version Require](https://camo.githubusercontent.com/3e830e0b47914d4054be89b2327d8a565944af816eebed8106ef37ba97c31f5c/687474703a2f2f706f7365722e707567782e6f72672f616e64726577647965722f6d61696c65722f726571756972652f7068703f7374796c653d666c61742d737175617265)](https://packagist.org/packages/andrewdyer/mailer)

Introduction
------------

[](#introduction)

This library renders Twig templates to HTML and dispatches them through an extensible, swappable transport interface, with a Symfony Mailer transport included out of the box. Custom transports can be introduced by implementing a simple contract, making it straightforward to adapt the delivery pipeline to different mailing backends or infrastructure requirements.

Prerequisites
-------------

[](#prerequisites)

- **[PHP](https://www.php.net/)**: Version 8.3 or higher is required.
- **[Composer](https://getcomposer.org/)**: Dependency management tool for PHP.
- **[Twig](https://twig.symfony.com/)**: Version ^3.27 is required.

Installation
------------

[](#installation)

```
composer require andrewdyer/mailer
```

Getting Started
---------------

[](#getting-started)

### 1. Create a Twig template

[](#1-create-a-twig-template)

Create an HTML template in the application's templates directory:

```
>

      body {
        font-family: Arial, sans-serif;
        font-size: 14px;
        color: #333;
        padding: 40px;
      }
      h1 {
        font-size: 24px;
        color: #1a1a2e;
      }

    Welcome, {{ user.name }}
    Thanks for signing up.

```

### 2. Create a mailable

[](#2-create-a-mailable)

Extend `Mailable` and implement `envelope()` to configure the routing and `content()` to define the template and data:

```
use AndrewDyer\Mailer\Mailable;
use AndrewDyer\Mailer\Values\Address;
use AndrewDyer\Mailer\Values\Content;
use AndrewDyer\Mailer\Values\Envelope;

class WelcomeMail extends Mailable
{
    public function __construct(private readonly User $user) {}

    public function envelope(): Envelope
    {
        return new Envelope(
            to:      new Address($this->user->email, $this->user->name),
            subject: 'Welcome to the platform!',
        );
    }

    public function content(): Content
    {
        return new Content(
            view: 'emails/welcome.html.twig',
            data: ['user' => $this->user],
        );
    }
}
```

### 3. Set up the mailer

[](#3-set-up-the-mailer)

Instantiate `Mailer` with a `Twig\Environment`, a transport, and an optional default from address:

```
use AndrewDyer\Mailer\Mailer;
use AndrewDyer\Mailer\Drivers\SymfonyTransport;
use AndrewDyer\Mailer\Values\Address;
use Twig\Environment;
use Twig\Loader\FilesystemLoader;

$twig = new Environment(new FilesystemLoader('/path/to/templates'));

$mailer = new Mailer(
    twig:        $twig,
    transport:   new SymfonyTransport('smtp://user:pass@smtp.example.com:587'),
    defaultFrom: new Address('hello@example.com', 'My App'),
);
```

Usage
-----

[](#usage)

### Sending a mailable

[](#sending-a-mailable)

Dispatch any `Mailable` instance via the `send()` method:

```
$mailer->send(new WelcomeMail($user));
```

### Attaching files

[](#attaching-files)

Implement `AttachableInterface` on the mailable and return an array of absolute file paths:

```
use AndrewDyer\Mailer\Contracts\AttachableInterface;
use AndrewDyer\Mailer\Mailable;

class InvoiceMail extends Mailable implements AttachableInterface
{
    public function __construct(private readonly Order $order) {}

    public function envelope(): Envelope { /* ... */ }

    public function content(): Content { /* ... */ }

    public function attachments(): array
    {
        return [
            '/storage/invoices/invoice-' . $this->order->id . '.pdf',
        ];
    }
}
```

Envelope
--------

[](#envelope)

A value object defining the routing and metadata for a message. Only `to` and `subject` are required — all other properties are optional and can be passed in any order using named arguments:

```
use AndrewDyer\Mailer\Values\Envelope;
use AndrewDyer\Mailer\Values\Address;
use AndrewDyer\Mailer\Enums\Priority;

new Envelope(
    to:       new Address('recipient@example.com', 'Recipient'),
    subject:  'Hello!',
    from:     new Address('sender@example.com', 'Sender'),
    cc:       [new Address('cc@example.com')],
    bcc:      [new Address('bcc@example.com')],
    replyTo:  new Address('reply@example.com'),
    priority: Priority::Normal,
);
```

### Setting a from address

[](#setting-a-from-address)

The `defaultFrom` address set on `Mailer` is used when `from` is omitted. Set it explicitly on the `Envelope` to override it for a specific mailable:

```
public function envelope(): Envelope
{
    return new Envelope(
        to:      new Address($this->user->email, $this->user->name),
        subject: 'Welcome to the platform!',
        from:    new Address('support@example.com', 'Support Team'),
    );
}
```

### Adding CC and BCC recipients

[](#adding-cc-and-bcc-recipients)

Pass arrays of `Address` instances to `cc` and `bcc` on the `Envelope`:

```
public function envelope(): Envelope
{
    return new Envelope(
        to:      new Address($this->user->email, $this->user->name),
        subject: 'Welcome to the platform!',
        cc:      [new Address('manager@example.com', 'Manager')],
        bcc:     [new Address('archive@example.com')],
    );
}
```

### Setting priority

[](#setting-priority)

Pass a `Priority` enum value to `priority` on the `Envelope`:

```
use AndrewDyer\Mailer\Enums\Priority;

public function envelope(): Envelope
{
    return new Envelope(
        to:       new Address($this->user->email),
        subject:  'Urgent: action required',
        priority: Priority::High,
    );
}
```

Transports
----------

[](#transports)

### Symfony Mailer

[](#symfony-mailer)

A transport backed by [Symfony Mailer](https://symfony.com/doc/current/mailer.html), supporting SMTP and a wide range of third-party providers via DSN strings.

```
composer require symfony/mailer
```

Then instantiate the transport with a DSN string:

```
use AndrewDyer\Mailer\Drivers\SymfonyTransport;

$transport = new SymfonyTransport('smtp://user:pass@smtp.example.com:587');
```

Common DSN formats:

```
smtp://user:pass@smtp.example.com:587
sendmail://default
null://null

```

### Custom transports

[](#custom-transports)

Any class implementing `TransportInterface` can be used as a transport, accepting a `PreparedMessage` and dispatching it:

```
use AndrewDyer\Mailer\Contracts\TransportInterface;
use AndrewDyer\Mailer\PreparedMessage;

class CustomTransport implements TransportInterface
{
    public function send(PreparedMessage $message): void
    {
        // Dispatch the message...
    }
}
```

License
-------

[](#license)

Licensed under the [MIT licence](https://opensource.org/licenses/MIT) and is free for private or commercial projects.

###  Health Score

36

—

LowBetter than 79% of packages

Maintenance92

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity41

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~18 days

Total

2

Last Release

38d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/666597ea6e46748a89fe8764d1a45b4d0da97daf1bb1e9770ea34ae41f706d08?d=identicon)[andrewdyer](/maintainers/andrewdyer)

---

Top Contributors

[![andrewdyer](https://avatars.githubusercontent.com/u/8114523?v=4)](https://github.com/andrewdyer "andrewdyer (10 commits)")

---

Tags

emailframework-agnosticmailerphpsmtptwigphptwigemailmailersmtpframework agnostic

###  Code Quality

TestsPHPUnit

Code StylePHP CS Fixer

### Embed Badge

![Health badge](/badges/andrewdyer-mailer/health.svg)

```
[![Health](https://phpackages.com/badges/andrewdyer-mailer/health.svg)](https://phpackages.com/packages/andrewdyer-mailer)
```

###  Alternatives

[symfony/ux-twig-component

Twig components for Symfony

22018.6M379](/packages/symfony-ux-twig-component)[twig/inky-extra

A Twig extension for the inky email templating engine

16613.6M81](/packages/twig-inky-extra)[symfony/ux-live-component

Live components for Symfony

1647.0M136](/packages/symfony-ux-live-component)[symfony/ux-toolkit

A tool to easily create a design system in your Symfony app with customizable, well-crafted Twig components

16126.1k1](/packages/symfony-ux-toolkit)[mati365/ckeditor5-symfony

CKEditor 5 integration for Symfony

262.6k](/packages/mati365-ckeditor5-symfony)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
