PHPackages                             phpdot/mail - 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. [Mail &amp; Notifications](/categories/mail)
4. /
5. phpdot/mail

Active[Mail &amp; Notifications](/categories/mail)

phpdot/mail
===========

00PHP

Pushed 1mo agoCompare

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

READMEChangelogDependencies (7)Versions (2)Used By (0)

phpdot/mail
===========

[](#phpdotmail)

Coroutine-safe transactional email for the PHPdot ecosystem. Compose a message with a fluent, immutable builder and send it through any transport — SMTP, sendmail, or any Symfony transport — from one injectable service. Delivery is delegated to the battle-tested [`symfony/mailer`](https://symfony.com/doc/current/mailer.html)

- `symfony/mime`, fenced entirely behind a single transport boundary; the rest of the package (the builder, the value objects, the receipt) is plain PHPdot code. A fresh transport is built per send, so concurrent coroutines never share a socket under Swoole.

Table of Contents
-----------------

[](#table-of-contents)

- [Requirements](#requirements)
- [Installation](#installation)
- [Usage](#usage)
- [Architecture](#architecture)
- [Testing](#testing)
- [License](#license)

Requirements
------------

[](#requirements)

RequirementConstraintPHP`>= 8.5``symfony/mailer``^8.0``symfony/mime``^8.0``phpdot/container`, `phpdot/config`, and `phpdot/package` are optional suggestions — install them to auto-wire the mailer and populate `MailConfig` from `config/mail.php`; the attributes are inert at runtime, so standalone consumers need none of them.

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

[](#installation)

```
composer require phpdot/mail
```

Usage
-----

[](#usage)

### Sending

[](#sending)

Inject `Mailer`, compose fluently, and send. Each builder step returns a new `Message`, so chaining off the shared mailer never mutates it:

```
use PHPdot\Mail\Contract\MailerInterface;

final class Welcome
{
    public function __construct(private readonly MailerInterface $mail) {}

    public function greet(string $email): string
    {
        $receipt = $this->mail
            ->to($email, 'Alice')
            ->subject('Welcome aboard')
            ->html('Hi Alice')
            ->text('Hi Alice')
            ->send();

        return $receipt->messageId; // ''
    }
}
```

Every message needs a sender: set `fromEmail` in `MailConfig` so chains can omit `->from()`, or call `->from('you@example.com', 'You')` explicitly. `cc()`, `bcc()`, `replyTo()`, `attach()`/`attachData()`, `priority()`, and `header()` round out the builder.

### Composing without sending

[](#composing-without-sending)

`$mail->message()` starts a bare `Message` you can build and pass around; its getters (`recipients()`, `htmlBody()`, `attachments()`, …) expose the composed state, and a configured base message is a safe reusable template because every step clones:

```
$base = $mail->message()->from('no-reply@example.com', 'Acme')->replyTo('support@example.com');
$base->to('alice@example.com')->subject('Hi')->send();
$base->to('bob@example.com')->subject('Hi')->send();   // $base is untouched
```

### Outcomes

[](#outcomes)

`send()` returns a `Receipt` (with the message id) when the transport **accepts** the message, and throws `TransportException` when it is rejected — every Symfony failure is translated into the package's own `MailException` hierarchy, so no Symfony type leaks into your code. Accepted is not the same as delivered: a `Receipt` means the transport took responsibility, not that the mailbox received it.

Architecture
------------

[](#architecture)

`Mailer` is the injected `#[Singleton]` façade; its builder methods start a fresh immutable `Message`. `send()` hands the message to `Transport`, which maps it onto a `symfony/mime` `Email` via `EmailFactory`, builds a one-shot transport from the `MailConfig` DSN, delivers, and returns a `Receipt`. Symfony lives only inside `Transport/`; `Mailbox` and `Attachment` are the immutable value objects.

 ```
graph TD
    MAILER["Mailer#[Singleton] — inject this"]
    MESSAGE["Messageimmutable fluent builder"]
    TRANSPORT["Transportper-send, one-shot socket"]
    FACTORY["EmailFactoryMessage → symfony/mime Email"]
    SYMFONY["symfony/mailer + symfony/mime"]
    RECEIPT["Receiptmessage id (accepted)"]

    MAILER --> MESSAGE
    MESSAGE --> TRANSPORT
    TRANSPORT --> FACTORY
    FACTORY --> SYMFONY
    TRANSPORT --> SYMFONY
    TRANSPORT --> RECEIPT
```

      Loading Testing
-------

[](#testing)

```
composer install
composer test        # PHPUnit
composer analyse     # PHPStan, level max + strict rules
composer cs-check    # PHP-CS-Fixer
composer check       # All three
```

License
-------

[](#license)

MIT — see [LICENSE](LICENSE).

This repository is a **read-only mirror**. The canonical source lives in [phpdot/monorepo](https://github.com/phpdot/monorepo); pull requests and issues are handled there: [pulls](https://github.com/phpdot/monorepo/pulls) · [issues](https://github.com/phpdot/monorepo/issues).

###  Health Score

20

—

LowBetter than 12% of packages

Maintenance60

Regular maintenance activity

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity13

Early-stage or recently created project

 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

Unknown

Total

1

Last Release

45d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/62e82421bda4b5d6ba9a47ba6d88caca060dcd0d1a2862f351f3a97657385db0?d=identicon)[phpdot](/maintainers/phpdot)

---

Top Contributors

[![phpdot](https://avatars.githubusercontent.com/u/252500?v=4)](https://github.com/phpdot "phpdot (1 commits)")

---

Tags

emailmailmailerphpsmtpswoole

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/phpdot-mail/health.svg)

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

###  Alternatives

[laravel/framework

The Laravel Framework.

34.8k543.8M20.6k](/packages/laravel-framework)[symfony/mailer

Helps sending emails

1.6k409.1M1.5k](/packages/symfony-mailer)[drupal/core

Drupal is an open source content management platform powering millions of websites and applications.

19566.0M1.8k](/packages/drupal-core)[kimai/kimai

Kimai - Time Tracking

4.8k9.0k1](/packages/kimai-kimai)[drupal/core-recommended

Locked core dependencies; require this project INSTEAD OF drupal/core.

6942.5M425](/packages/drupal-core-recommended)[shopware/core

Shopware platform is the core for all Shopware ecommerce products.

585.6M606](/packages/shopware-core)

PHPackages © 2026

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