A PHP email notification system with server/client architecture for sending emails from multiple systems without requiring SMTP configuration on each client.
The application runs standalone or as a Composer dependency. Server and client are bundled in one package so separate apps are not required.
Centralized email delivery: client systems send HTTP requests to a notifier server, which handles authentication, validation, and actual mail delivery. Clients do not need a local SMTP setup.
| Component | Responsibility |
|---|---|
Server (index.php → Server::handleRequest()) |
Validates API key, host/IP restrictions, and request parameters; sends the email |
Client (Client::sendMail()) |
Sends a POST request to the server with to, subject, message, and the configured from-address |
| Common | Shared utilities used by server and client |
- PHP 8.3 minimum
- SMTP via PHPMailer (no custom SMTP implementation)
- HTTP client cURL
- Autoloading PSR-4 via Composer
- Config format PHP arrays for server/client settings; JSON for per-client access records on the server
- Config merge Constructor arguments are merged recursively with the default config
- Config access Dot notation, CakePHP-style:
Config::read('foo.bar', 'default') - Timezone Europe/Berlin
- API keys, minimum 64 characters, generated as
hash('sha256', SERVER_DOMAIN . CLIENT_EMAIL . SALT . time()) - One JSON file per client in
data/notifier/clients/<API_KEY>.json(email, allowed hosts/IPs) - HTTPS only
- Rate limiting per client (configurable number of emails per 10-second window)
- Optional host/IP whitelist per client
- Server responds with JSON on errors: status codes and short messages, no sensitive details
.htaccessblocks direct web access to project files
- HTML emails only; no CC/BCC
- UTF-8 MIME: both SMTP (PHPMailer) and PHP
mail()send HTML ascharset=UTF-8with base64 transfer encoding so umlauts and other non-ASCII characters render correctly - Attachments planned for a later version
- Server: configurable primary method (
mail()or SMTP) with automatic fallback to the other method - Client: up to 3 retry attempts; failures are saved to
tmp/failures/
Besides server URL and API key, the client config includes:
- Client name — prepended to the subject, e.g.
[MySystem1] Original subject - From address — sent with each request; the server validates it against the client's restrictions
cli-create-client-access.php / cli-create-client-access.sh (CLI only):
- Client email address (allowed sender)
- Optional comma-separated list of allowed hosts or IPs
If a matching client already exists, the existing API key is printed. Otherwise a new key is generated and saved.
Requires PHP 8.3+. If the default php binary is older (e.g. 8.1), select the correct binary via env or flag:
PHP_BIN=php8.3 ./cli-create-client-access.sh
./cli-create-client-access.sh --php php8.3
./cli-create-client-access.sh -p /usr/bin/php8.3--php / -p override PHP_BIN. Default is php.
When debug => true in config:
- Server & client save outgoing/incoming emails to
tmp/debug/ - Client saves undeliverable emails to
tmp/failures/ - Filenames:
Y-m-d--H-i-s_<content-hash>.html
No statistics or metrics are collected beyond debug logging.
- Comments in English
- Opening brace on the same line as method definitions
- Two blank lines after each method
- Typed parameters and return types
- Server/Client Architecture: Centralized email sending with distributed clients
- API Key Authentication: Secure access with optional host/IP restrictions
- Dual Email Methods: Support for both PHP
mail()and SMTP with automatic fallback - Rate Limiting: Configurable per-client rate limiting (emails per 10 seconds)
- Retry Logic: Automatic retries on client side with failure logging
- Debug Mode: Save emails to files for debugging purposes
- Logging: Comprehensive logging with different levels
- HTTPS Only: Enforced secure connections
- PHP 8.3+
- cURL extension
- JSON extension
- Composer
-
Install via Composer:
composer install
-
Configure Server/Client:
- Edit
config/config_notifier.php - OR: setup client and server via constructor
- Set your domain, SMTP settings, and other preferences
- Set server URL and other client settings
- Edit
-
Create Client Access:
# interactive client setup (needs PHP 8.3+) PHP_BIN=php8.3 ./cli-create-client-access.sh # OR ./cli-create-client-access.sh --php php8.3 # OR call PHP directly php8.3 cli-create-client-access.php <allowedFrom> <allowedTo> <allowedHosts> [description]
-
Set Permissions:
chmod 755 logs tmp data/notifier/clients chmod 600 data/notifier/clients/*.json
Deploy the notifier to your web server and ensure index.php is accessible via HTTPS:
// index.php handles all server requests automatically
// Configure via config/config_notifier_server.php or pass config arraySee example files
- index.sample.php (Server)
- cli-test-client.sample.php (Client)
Have alook into config/config_server.php file.
- HTTPS Enforcement: All requests must use HTTPS
- API Key Authentication: Each client requires a unique API key
- IP/Host Restrictions: Optional whitelist of allowed client IPs/hosts
- Rate Limiting: Configurable limits per client
- Input Validation: All email data is validated before processing
- Secure Headers: Security headers automatically added
Enable debug mode in configuration:
'debug' => trueWhen enabled:
- Server: Saves incoming emails to
tmp/debug/ - Client: Saves outgoing emails to
tmp/debug/ - Failed emails are saved to
tmp/failures/
Debug files use format: Y-m-d--H-i-s_[hash].html
Logs are written to logs/debug.log with different levels:
- DEBUG: Detailed debug information
- INFO: General information (successful sends)
- WARNING: Warning conditions (rate limits, invalid IPs)
- ERROR: Error conditions (send failures, validation errors)
notifier/
├── index.php # Server entry point
├── cli-create-client-access.sh # CLI tool for client creation, interactive mode
├── cli-create-client-access.php # CLI tool for client creation
├── composer.json # Dependencies
├── .htaccess # Web server security
├── src/Platomat/
│ ├── Notifier/
│ │ ├── Server.php # Server implementation
│ │ ├── Client.php # Client implementation
│ │ └── Common.php # Shared utilities
│ ├── Core/
│ │ └── Config.php # Configuration management
│ └── Logging/
│ └── Logger.php # Logging implementation
├── config/
│ └── config_notifier.php # configuration
├── data/notifier/clients/ # Client access files (API keys)
├── logs/ # Log files
└── tmp/
├── debug/ # Debug emails
└── failures/ # Failed email attempts
- 400: Bad Request (validation failed, invalid JSON)
- 401: Unauthorized (invalid API key, email mismatch)
- 405: Method Not Allowed (non-POST request)
- 429: Too Many Requests (rate limit exceeded)
- 500: Internal Server Error (email send failure, server error)
Ignored paths (see .gitignore):
tmp/logs/data/notifier/clients/vendor/composer.lockcli-test-client-local.phptest-server-local.phpindex.php