Email Sender
The Email Sender (mailer) module provides email delivery capabilities for the entire system. It operates as an asynchronous event-driven service that consumes email send requests from other modules via RabbitMQ and delivers them through a configured SMTP server.
Core Features
SMTP Integration
The module uses standard SMTP protocol for email delivery:
- STARTTLS Support: Configurable TLS encryption for secure email transmission
- Authentication: Username/password-based SMTP authentication
- Plain Connection Option: Support for unencrypted connections (for testing or trusted networks)
- Dynamic Configuration: SMTP settings can be reloaded without service restart
Event-Driven Architecture
All email sending is triggered through RabbitMQ events:
- Asynchronous Processing: Email sending doesn’t block the calling service
- Reliable Delivery: RabbitMQ ensures events are not lost if the mailer is temporarily unavailable
- Decoupled Design: Other modules don’t need direct dependencies on mailer code
Template System
Pre-defined email templates with embedded assets:
- HTML Templates: Rich HTML email templates with inline styling
- Embedded Assets: Logo and other assets are compiled into the binary (no external files needed)
- Template Types: Register verification, OTP codes, password reset, package expiration notifications
Architecture
Configuration Storage
SMTP configuration is stored in Redis using the Manage module’s config provider system:
- Config Key:
mailer - Hot Reload: The module periodically checks Redis for config changes and rebuilds the SMTP connection if needed
- Sensitive Data Protection: Passwords are redacted in debug logs
Configuration fields:
host: SMTP server hostnameport: SMTP server port (typically 587 for STARTTLS, 25 for plain)username: SMTP authentication usernamepassword: SMTP authentication passwordsender: Default sender email address (used whenfromis not specified)starttls: Whether to use STARTTLS encryption
Event Consumption
The module consumes two types of events:
-
Generic Email Events (
MailSendCall): Direct email sending with full control over content- Queue:
helium_mailer_send - Exchange:
mailer(Direct) - Routing Key:
send
- Queue:
-
Template-based Email Events: Events from other modules (primarily Auth and Telecom) that trigger template rendering
- Register verification emails
- OTP email codes
- Password reset emails
- Package expiration notifications
Hooks (Event Processors)
Each hook implements the Processor pattern to handle specific event types:
- MailerHook: Core processor for
MailSendCallevents, handles actual SMTP transmission - RegisterEmailHook: Processes user registration verification emails
- OtpEmailHook: Processes one-time password emails for 2FA
- ForgotPasswordEmailHook: Processes password reset emails
- AllPackageExpiredHook: Processes telecom package expiration notifications
All hooks follow the standard pattern: receive event → render template (if needed) → publish MailSendCall → SMTP delivery.
Integration Points
With Auth Module
The mailer consumes three types of email events from Auth:
RegisterEmailSendCall: When a new user registersOtpEmailSendCall: When OTP authentication is requiredForgotPasswordEmailSendCall: When a user requests password reset
With Telecom Module
AllPackageExpiredEvent: Sent when all of a user’s telecom packages expire
With Manage Module
- Uses Manage’s
config_providerto fetch SMTP configuration from Redis - SMTP settings can be updated via Manage’s admin configuration APIs
Email Sending Flow
When another module needs to send an email:
- The calling module publishes an event (either a specific template event or a generic
MailSendCall) - If it’s a template event, the corresponding hook receives it and:
- Fetches necessary data from the database (e.g., user email)
- Renders the HTML template
- Publishes a
MailSendCallevent
MailerHookreceives theMailSendCallevent- SMTP connection is used to transmit the email
- Errors are logged but don’t crash the worker (events can be retried by RabbitMQ)
Development Notes
- All email content is sent as HTML with
Content-Type: text/html - The SMTP sender can be overridden per-email via the
fromfield inMailSendCall - Email templates use the
askamatemplating engine - The module doesn’t expose any gRPC services (it’s worker-only)
- All processors follow the Processor pattern (not OOP)
- Email addresses are validated before sending; invalid addresses result in
Error::InvalidInput - The module doesn’t track email delivery status or bounces (delegated to SMTP server)
Worker Setup
The mailer runs as a dedicated worker process that needs:
- PostgreSQL connection (for template data like user emails)
- Redis connection (for SMTP configuration)
- RabbitMQ connection (for event consumption)
Refer to the helium-server deployment documentation for worker configuration details.