E-mailer
How BizKitHub queues, dispatches, retries, and audits every outgoing e-mail — from the platform's own transactional messages to admin-triggered marketing sends.
Overview
The Emailer is the core platform service that stores, queues, and delivers every e-mail sent from BizKitHub. It guarantees at-least-once delivery, handles retries when the upstream SMTP is unreachable, and keeps a complete audit trail for every message — regardless of whether the mail was triggered by an admin operator, a workflow rule, or an API call from an external integration.
Key capabilities
- Queue management — persistent storage of the outgoing queue with the full configuration required to redeliver a message if the first attempt fails.
- Template formatting — server-side rendering of the appropriate template (transactional, marketing, notification) with HTML and plain-text output.
- System messages — automatic dispatch of platform-level notifications (order status, invoice sent, workflow escalation) without operator involvement.
- Fallback logic — retries with exponential back-off, quarantine of undeliverable addresses, and automatic pause of the queue while the SMTP endpoint is unhealthy.
Delivery queue
Every message enters the same queue regardless of source. The queue row captures everything needed to send, retry, and audit the message — sender, recipient, headers, body, priority and delivery state.
Recorded fields
| Field | Type | Purpose |
|---|---|---|
id | int | Internal identifier of the e-mail. |
external_id | char(32) | Public identifier of the e-mail. |
status | smallint | Delivery state (see below). |
datetime_inserted | timestamp | When the message entered the queue. |
datetime_sent | timestamp | When delivery succeeded. |
priority | smallint | Higher number = higher priority. |
failed_attempts_count | smallint | Failed delivery attempts so far. |
send_earliest_at | timestamp | Do not send before this time. |
send_earliest_next_attempt_at | timestamp | Do not retry before this time. |
note | text | Internal comment, error message or last SMTP response. |
from | text | Sender address. |
to | text | Recipient address. |
subject | text | Subject line. |
cc | text | Carbon copy. |
bcc | text | Blind carbon copy. |
reply_to | text | Reply-to address. |
html_body | text | Full HTML body of the message. |
organisation_id | int | Organisation the message belongs to. |
from_member_id | int | Member that triggered the send, when known. |
tag | varchar(64) | Technical tag for search (e.g. order-123). |
Delivery order
Messages are drained from the queue with ORDER BY priority DESC, datetime_inserted ASC — higher-priority mail leaves the queue first; within the same priority, the oldest message wins.
How the queue is drained
Delivery is asynchronous: enqueuing is a millisecond-level DB write, actual sending happens in the background via a scheduled worker.
- Insertion. The API or workflow places the row in the queue — the write takes tens of milliseconds.
- Scan. A worker polls the queue at a short interval and picks the next batch of messages that are due and eligible.
- Parallel dispatch. Up to 25 e-mails are sent concurrently across all organisations, respecting priorities and per-host connection limits.
- Result recording. On success the row is marked as sent; on failure the retry counter is bumped and the next attempt is scheduled with exponential back-off.
Performance envelope
- Enqueue latency — tens of milliseconds.
- Parallel dispatch — up to 25 messages at once.
- Scope — a single worker processes every organisation's queue.
Delivery states
| ID | Code | Meaning |
|---|---|---|
| 1 | in-queue | Queued and ready for the next scan. |
| 2 | not-ready-to-queue | Not yet ready — dependent data is still being assembled. |
| 3 | waiting-for-next-attempt | Previous attempt failed; scheduled to retry. |
| 4 | sent | Delivered successfully. |
| 5 | preparing-error | Error while preparing the message (template render, resource lookup). |
| 6 | sending-error | SMTP or transport error while sending. |
| 7 | undeliverable | Address is permanently invalid or has repeatedly bounced. |
Error handling and recovery
Automatic retries
- Repeated delivery attempts on transient errors.
- Exponential back-off between attempts.
- Automatic marking of persistently undeliverable addresses.
- Every attempt is logged for troubleshooting.
Outage protection
- The queue is paused when the SMTP host is unreachable — no messages are dropped.
- Synthetic test messages verify recovery before regular traffic resumes.
- Once the upstream is healthy again, the queue drains automatically.
- Nothing is lost during the outage — messages accumulate and dispatch in order.
Monitoring and logging
Every Emailer action is logged and monitored. Operators can inspect delivery status, retry history and per-organisation throughput from the admin. Platform operators additionally see cross-organisation health, connection pool state and per-host reject rates.
Integration with the BizKitHub platform
The Emailer is a first-class citizen of the platform: any module that needs to send mail — orders, invoices, workflow, newsletter, notifications — publishes to the queue rather than talking to SMTP directly. Three concrete integration surfaces:
- API integration. External systems trigger sends via the public API using an API key.
- Templates. Every message is formatted through a locale- and organisation-aware template so branding stays consistent.
- Reporting. Delivery metrics feed the analytics module — bounce rate, open rate (when tracking is enabled), retry count per organisation.