maatify / channel-delivery
Maatify Channel Delivery — Standalone async multi-channel delivery microservice (Email, Telegram, SMS, Push...)
Requires
- php: ^8.2
- ext-curl: *
- ext-json: *
- ext-openssl: *
- ext-pdo: *
- ext-redis: *
- ext-sodium: *
- ext-zlib: *
- maatify/crypto: ^1.0
- maatify/email-delivery: ^1.0
- 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
README
Overview
Maatify Channel Delivery is a standalone async multi-channel delivery microservice for sending notifications across channels like Email, Telegram, SMS, and Push.
It offloads delivery processing from your core applications, ensuring:
- High availability
- Background delivery processing
- Retry mechanisms
- Secure payload encryption
- Controlled API ingestion
Currently, the Email channel is fully implemented and production-ready. Additional channels such as SMS, Telegram, and Push notifications are planned for future releases.
Features
-
Async Multi-Channel 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 Exponential retry strategy for transient delivery failures.
-
API Key & IP Whitelisting Secure ingestion endpoints allowing only trusted origin servers.
-
Rate Limiting Redis-backed sliding window rate limiter to prevent abuse.
-
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 Client calls
/api/v1/email/enqueue. -
Encryption
EnqueueEmailHandlerencrypts recipient and context viaMaatify\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.2+
- MySQL / MariaDB
- Redis
- SMTP server
- Composer
Related Projects
maatify/email-delivery– email delivery enginemaatify/crypto– encryption layer
Installation
Clone the repository or install via Composer:
composer create-project maatify/channel-delivery
cd channel-delivery
Install dependencies:
composer install --optimize-autoloader --no-dev
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 |
Example:
CRYPTO_ACTIVE_KEY_ID=v1 CRYPTO_KEYS='[{"id":"v1","key":"replace_with_32_byte_secret_here"}]'
Key requirements:
- Key must be exactly 32 bytes
- Keys support rotation
- Old keys remain for decryption only
Generate a secure 32-byte key:
php -r "echo bin2hex(random_bytes(16));"
This will generate a 32-character string, for example:
a3f9c2d1e4b5f6a7c8d9e0f1a2b3c4d5
Then place it inside the .env configuration:
CRYPTO_ACTIVE_KEY_ID=v1 CRYPTO_KEYS='[{"id":"v1","key":"a3f9c2d1e4b5f6a7c8d9e0f1a2b3c4d5"}]'
Key requirements:
- Must be exactly 32 characters
- 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 |
SMTP debug mode (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
License
This project is open-sourced software licensed under the MIT License.
See the LICENSE file for details.