Search by

maatify / email-delivery

Maatify

Standalone email delivery module for rendering, queueing and sending emails.

Package info

github.com/Maatify/email-delivery

pkg:composer/maatify/email-delivery

Statistics

Installs: 70

Dependents: 1

Suggesters: 0

Stars: 2

Open Issues: 1

v1.2.0 2026-11-06 20:07 UTC

This package is auto-updated.

Last update: 2026-11-06 20:26:24 UTC


README

Maatify Email Delivery

Maatify.dev

Status Latest Version PHP License PHPStan CI

Packagist Monthly Downloads Total Downloads Maatify Ecosystem Install

Documentation Usage Guide Examples Package Reference Keyed API Reference Changelog Security Policy

A framework-independent PHP library for an encrypted email queue, Twig HTML rendering and SMTP transport through PHPMailer. Applications enqueue work; a separately run worker attempts delivery.

Release artifact target: 1.2.0. Publication state: published. Version 1.2.0 was published on 2026-11-06 UTC and verified as an exact Composer dist installation. Its immutable qualified source is 8e0fc1e2995fb52d1e0e5e299eea2203ccd56c2d.

The tagged artifact retains its historically valid pre-publication qualification snapshot. This live repository records later publication facts; it does not replace the tag or change the distributed artifact.

Start here

Choose the enqueue contract

Requirement API Result
Each call intentionally creates another job EmailQueueWriterInterface::enqueue() / PdoEmailQueueWriter void; no request deduplication
Retrying one identified request must not create another job IdempotentEmailQueueWriterInterface::enqueueOnce() / PdoIdempotentEmailQueue A committed receipt; different content on the same key conflicts
Record an inert request without any email job SyntheticEmailRecorderInterface::record() / PdoSyntheticEmailStore Distinct synthetic record; never a delivery receipt
Observe an accepted keyed request EmailEnqueueReceiptReaderInterface::find(namespace, key) Scoped receipt or null; no recipient/context returned

Keyed enqueue atomically stores a job and its durable receipt. Repeating the same namespace/key and logical content returns the same receipt/job identity. It does not guarantee exactly-once SMTP, mailbox arrival, or automatic recovery of a worker interrupted after claiming a job.

Public Runtime API

Capability Supported entry points
Per-call queue insertion EmailQueueWriterInterface, PdoEmailQueueWriter
Keyed acceptance and scoped observation IdempotentEmailQueueWriterInterface, EmailEnqueueReceiptReaderInterface, PdoIdempotentEmailQueue
Inert recording and trusted cleanup SyntheticEmailRecorderInterface, SyntheticEmailMaintenanceInterface, PdoSyntheticEmailStore
Rendering EmailRendererInterface, TwigEmailRenderer, payload/rendered DTOs
Explicit SMTP call EmailTransportInterface, SmtpEmailTransport, EmailTransportConfigDTO
One processing batch EmailQueueWorker

The Package Reference owns the complete supported inventory, DTO fields, enum values, exceptions and behavioral boundaries. Internal helpers are not consumer API.

Installation and dependencies

composer require maatify/email-delivery:1.2.0

This exact version is available through Packagist. To follow the current Stable line, use composer require maatify/email-delivery.

The package requires PHP 8.2+, JSON and PDO, plus maatify/crypto, Twig, PHPMailer and PSR-3 logging. The production keyed and synthetic storage paths use MySQL/MariaDB with pdo_mysql and the package-owned SQL files. SQLite is used by legacy tests, not supported as keyed production storage. Supply your application PDO, crypto provider/context provider, renderer, transport and logger through DI. Monolog is not a package dependency.

Apply the schema installation/upgrade before adopting the keyed API. Do not run all numbered SQL files on a fresh installation: the binding upgrade is for an existing legacy table.

Synthetic recording uses an optional independent table and separate crypto domains. Its retention is explicitly configured by the consumer; cleanup is scheduled externally. It provides no constant-time or HTTP security guarantee. See the full contract.

Quick Usage

This function defines application wiring; including it does not connect or send mail. Its dependencies must already be configured. See the complete examples for construction, explicit scheduling, receipt lookup and worker composition.

use Maatify\EmailDelivery\Queue\DTO\EmailEnqueueReceiptDTO;
use Maatify\EmailDelivery\Queue\DTO\EmailEnqueueRequestDTO;
use Maatify\EmailDelivery\Queue\DTO\EmailQueuePayloadDTO;
use Maatify\EmailDelivery\Queue\IdempotentEmailQueueWriterInterface;

function queueWelcome(
    IdempotentEmailQueueWriterInterface $queue,
    string $authenticatedNamespace,
    string $stableRequestKey,
    string $recipient,
    string $name,
): EmailEnqueueReceiptDTO {
    return $queue->enqueueOnce(new EmailEnqueueRequestDTO(
        consumerNamespace: $authenticatedNamespace,
        requestKey: $stableRequestKey,
        entityType: 'user',
        entityId: null,
        recipientEmail: $recipient,
        payload: new EmailQueuePayloadDTO(['name' => $name], 'welcome', 'en'),
        senderType: 1,
    ));
}

Persist the key and intended content in the caller; do not generate a new key on every retry. Namespace is a scope, not authentication. Derive it from the authenticated caller and keep PII/secrets out of keys. The reference defines canonical content, validation, transaction errors, indefinite receipt/key retention and recovery with the same key on a fresh connection.

Worker and delivery boundaries

EmailQueueWorker::processBatch() claims a bounded pending batch under row locks, commits the claim, then decrypts/renders and calls the transport outside that transaction. Run it from your application's supervised process using the worker guide.

Keyed jobs use database UTC for due/retry selection, retry deadlines and sent_at. NULL-token legacy jobs retain local database NOW() and PHP-local retry calculation. The worker supports pre-binding legacy tables and does not mutate the session timezone. Clock and failure details.

Queue acceptance and delivery architecture

Development verification

composer validate --strict
composer test
composer analyse -- --memory-limit=512M
composer check:docs
composer check:examples
composer check:artifact

Without DB configuration, real-DB tests skip. CI is configured for PHP 8.2/8.3/8.4/8.5 with required MySQL integration tests and an additional no-DB skip check. For a disposable dedicated database ending in _test, set EMAIL_DELIVERY_IT_DSN, EMAIL_DELIVERY_IT_USER, EMAIL_DELIVERY_IT_PASS and EMAIL_DELIVERY_IT_REQUIRED=1. Tests own/drop their queue tables; never target an application database. See the release checklist for evidence and documentation checks.

License

This library is licensed under the MIT License. Vulnerability reports follow SECURITY.md.

Author

Engineered by Mohamed Abdulalim (@megyptm)
Backend Lead & Technical Architect
https://www.maatify.dev

Built with ❤️ by Maatify.dev — Unified Ecosystem for Modern PHP Libraries