maatify / channel-delivery
Maatify Channel Delivery — Standalone async email delivery service with atomic acceptance and isolated synthetic recording; additional channels planned.
Requires
- php: ^8.4
- ext-curl: *
- ext-json: *
- ext-openssl: *
- ext-pdo: *
- ext-pdo_mysql: *
- ext-redis: *
- ext-sodium: *
- ext-zlib: *
- maatify/crypto: ^1.0
- maatify/email-delivery: ^1.2
- maatify/psr-logger: ^1.0
- maatify/shared-common: ^1.0
- php-di/php-di: ^7.1
- php-di/slim-bridge: ^3.0
- phpmailer/phpmailer: ^6.9
- psr/http-message: ^2.0
- psr/http-server-handler: ^1.0
- psr/http-server-middleware: ^1.0
- psr/log: ^3.0
- slim/psr7: ^1.8
- slim/slim: ^4.15
- twig/twig: ^3.0
- vlucas/phpdotenv: ^5.6
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.94
- phpstan/phpstan: ^1.12
- phpunit/phpunit: ^11.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
Maatify Channel Delivery
Usage Guide · Examples · HTTP Reference · Changelog · Security · Contributing
Standalone asynchronous email delivery service with encrypted queues, atomic acceptance and isolated no-send recording. Other delivery channels are planned.
Artifact target: 2.0.0 — project release identity; HTTP API versioning is separate.
Current publication (2026-11-07): 2.0.0 is published
and available through Composer. Its immutable source is commit
c5714f8d1b3fc13e4d42e88501c668af3f1595ac.
Exact-version Composer installation and all 88 distributed source files were verified.
Security support covers both 1.x and 2.x; see SECURITY.md.
Publication snapshot at preparation (2026-11-07): 2.0.0 was unpublished;
1.1.0 was the verified published release. The badges above report live repository/registry state,
not the identity or qualification of this artifact. See the 2.0.0 release guide
and upgrade guide. This historical preparation snapshot does not describe current availability; the publication record above does.
Overview
Maatify Channel Delivery is a standalone asynchronous email delivery microservice, designed to accommodate additional channels in future releases.
It offloads delivery processing from your core applications, providing:
- Independent ingestion and worker operation
- Background delivery processing
- Retry mechanisms
- Secure payload encryption
- Controlled API ingestion
The Email channel is implemented. Acceptance confirms queue persistence; delivery is processed separately by the worker. Additional channels such as SMS, Telegram, and Push notifications are planned for future releases.
Atomic keyed acceptance and receipt lookup are available through the additive v2 HTTP API, using email-delivery 1.2.0. Follow the schema/binding rollout before enabling v2. v1 keeps its existing behavior.
The optional synthetic no-send HTTP endpoint records encrypted inert data in separate storage. It requires explicit retention and bounded cleanup; no timing-equality promise is made.
Features
-
Async Email Queue Process notifications asynchronously using background workers.
-
Encrypted Payloads Built-in
AES-256-GCMencryption for recipients and message contexts viamaatify/crypto. -
Template Rendering Uses Twig to render dynamic email templates safely.
-
Reply-To Support Optional
reply_tofield for admin notification emails — email goes to the admin, replies go to the customer. -
Robust Delivery Bounded retry/backoff handling for delivery failures.
-
API Key & IP Whitelisting Secure ingestion endpoints allowing only trusted origin servers.
-
Rate Limiting Redis-backed fixed-window request counter per API key. The existing Redis-unavailable behavior is fail-open.
-
Containerized Dependency Injection Built on Slim 4 + PHP-DI for modular and testable architecture.
Architecture
The system operates as an API ingestion layer combined with background workers.
Applications enqueue notification jobs via HTTP. Workers then process the queue and deliver messages asynchronously.
The email delivery pipeline is powered internally by the
maatify/email-delivery
library, which provides the rendering, transport abstraction,
and delivery engine.
Email Delivery Pipeline
Client Application
↓
Channel Delivery API
↓
Encrypted Queue (Database)
↓
Worker
↓
SMTP Transport
↓
Recipient
Detailed processing steps:
-
Enqueue In this legacy pipeline example, the client calls
/api/v1/email/enqueue. The additive v2 paths are described below. -
Encryption The handler delegates recipient and payload encryption/persistence to
maatify/email-delivery, usingMaatify\Crypto. -
Persistence Job stored securely in
cd_email_queue. -
Worker Polling
EmailQueueWorkerpolls pending jobs. -
Template Rendering Context is decrypted and injected into Twig templates.
-
SMTP Delivery Email is sent via
SmtpEmailTransport. IfreplyTowas set, aReply-Toheader is added so replies go to the specified address.
Requirements
- PHP 8.4+ for this 2.0.0 artifact (CI: 8.4 and 8.5); see upgrade compatibility
- MySQL with InnoDB and the PDO MySQL driver; service CI currently exercises MySQL 9.2. MariaDB deployment compatibility needs its own qualification.
- Redis
- SMTP server
- Composer
Public Runtime API
| Entry point | Contract |
|---|---|
GET /health |
Service/database health; no SMTP-delivery probe |
POST /api/v1/email/enqueue |
Legacy per-call insert; 202 queued |
POST /api/v2/email/enqueue |
Atomic acceptance with stable consumer/key identity; 202 accepted |
GET /api/v2/email/receipt |
Same-key receipt recovery; 200 or point-in-time 404 |
POST /api/v2/email/synthetic |
Isolated encrypted no-send recording; 202 recorded |
| API-key / email-worker / synthetic-purge CLI | Operator commands and configuration |
The HTTP reference links the complete contracts and template fields. Application classes and vendor internals are implementation details, not a PHP library API. See v2 examples for same-key recovery and no-send usage.
Related Projects
maatify/email-delivery– email delivery enginemaatify/crypto– encryption layer
Installation
The published Stable channel is available through the registry.
A generic composer create-project maatify/channel-delivery follows that channel and does not select an unpublished target.
Install the published 2.0.0 project with:
composer create-project --prefer-dist --no-dev maatify/channel-delivery channel-delivery 2.0.0
cd channel-delivery
For source review or contribution, use a reviewed checkout:
git clone https://github.com/Maatify/channel-delivery.git cd channel-delivery git checkout <reviewed-commit-or-published-tag> composer install --no-dev --prefer-dist --no-interaction
Do not run the placeholder checkout literally. Use the committed project lock.
First setup includes the required .env, schema,
API key and worker steps. The HTTP document root is public/, never the repository root.
Configuration
Create the environment configuration file:
cp .env.example .env
Edit .env and configure the following variables.
Application
| Variable | Description |
|---|---|
APP_ENV |
Application environment (development / production) |
APP_NAME |
Name of the service instance |
SUPPORT_EMAIL |
Support contact email |
Database
| Variable | Description |
|---|---|
DB_HOST |
Database host |
DB_PORT |
Database port |
DB_DATABASE |
Database name |
DB_USERNAME |
Database username |
DB_PASSWORD |
Database password |
Example:
DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=channel_delivery DB_USERNAME=root DB_PASSWORD=secret
Encryption (Crypto)
Queue payloads and sensitive data are encrypted using AES-256-GCM through maatify/crypto.
| Variable | Description |
|---|---|
CRYPTO_ACTIVE_KEY_ID |
Identifier of the active encryption key |
CRYPTO_KEYS |
JSON array containing encryption keys |
Configuration shape only — the placeholder below is deliberately not a usable key. Replace it with a new private value generated for this installation:
CRYPTO_ACTIVE_KEY_ID=v1 CRYPTO_KEYS='[{"id":"v1","key":"<YOUR_UNIQUE_32_BYTE_SECRET>"}]'
Key requirements:
- Key must be exactly 32 bytes
- Keys support rotation
- Old keys remain for decryption only
The following existing format produces 32 ASCII key-material bytes from 16 random bytes (128 bits of randomness); it is not 32 random bytes and is not automatically hex-decoded:
php -r "echo bin2hex(random_bytes(16));"
Use the locally generated 32-character ASCII string in place of the placeholder above. Generate a fresh private value for each installation; never copy a published example key or commit/paste the generated key into source, logs or public messages. Keep historical keys privately when rotating keys for retained data.
Key requirements:
- Must be exactly 32 raw bytes (32 ASCII characters in this example)
- Used as the symmetric encryption key for AES-256-GCM
- Keys support rotation
SMTP
SMTP configuration used by the email delivery worker.
| Variable | Description |
|---|---|
MAIL_HOST |
SMTP server host |
MAIL_PORT |
SMTP server port |
MAIL_USERNAME |
SMTP username |
MAIL_PASSWORD |
SMTP password |
MAIL_FROM_ADDRESS |
Default sender email |
MAIL_FROM_NAME |
Sender display name |
MAIL_ENCRYPTION |
Encryption type (tls / ssl) |
MAIL_TIMEOUT |
SMTP timeout (seconds) |
MAIL_DEBUG_LEVEL |
SMTP debug level (0 = disabled) |
Redis
Redis is used for rate limiting.
| Variable | Description |
|---|---|
REDIS_HOST |
Redis host |
REDIS_PORT |
Redis port |
REDIS_PASSWORD |
Redis password (optional) |
REDIS_DB |
Redis database index |
RATE_LIMIT_MAX_REQUESTS |
Maximum requests allowed |
RATE_LIMIT_WINDOW_SECONDS |
Rate limit window duration |
TRUSTED_PROXIES |
Trusted proxy IPs (for X-Forwarded-For) |
Example:
REDIS_HOST=127.0.0.1 REDIS_PORT=6379 RATE_LIMIT_MAX_REQUESTS=100 RATE_LIMIT_WINDOW_SECONDS=60
Quick Examples
Customer-facing email
Enqueue a transactional email (e.g., welcome, OTP, verification) sent to the customer:
curl -X POST http://localhost:8080/api/v1/email/enqueue \ -H "Content-Type: application/json" \ -H "X-Api-Key: your_generated_api_key" \ -d '{ "entity_type": "user", "recipient": "user@example.com", "template_key": "welcome", "language": "en", "sender_type": 1, "context": { "user_name": "Ahmed", "activation_link": "https://example.com/activate?token=abc" } }'
Admin notification with Reply-To (v1.1.0+)
Enqueue an admin notification where the email goes to the admin, and replies go to the customer:
curl -X POST http://localhost:8080/api/v1/email/enqueue \ -H "Content-Type: application/json" \ -H "X-Api-Key: your_generated_api_key" \ -d '{ "entity_type": "contact_form", "recipient": "admin@example.com", "reply_to": "customer@example.com", "template_key": "admin_notification", "language": "en", "sender_type": 1, "context": { "customer_name": "Ahmed", "customer_email": "customer@example.com", "customer_message": "I need help with my account." } }'
Worker Usage
Run the email worker:
php scripts/email_worker.php --batch=50 --loop --sleep=5
This worker should normally run under a process manager like Supervisor or systemd.
See the worker setup guide:
Documentation
- Documentation Index
- Usage Guide
- 2.0.0 Upgrade Guide
- Configuration / CLI Reference
- Atomic v2 Contract
- Synthetic Contract
- Release Qualification Checklist
- Run Worker Guide
- Send Email Guide
- API Documentation: Email Enqueue
- Basic Usage Example
License
This project is open-sourced software licensed under the MIT License.
See the LICENSE file for details.
Contributing
Use a source clone and the contribution guide. Release archives omit test infrastructure. Please follow the Code of Conduct and report vulnerabilities privately through 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