ulams sends e-mail from the API through SMTP. Message bodies come from e-mail templates written in MJML, which a small rendering service turns into HTML.
Set on api (with the LARAVEL_ prefix in Compose):
| Variable | Example | Notes |
|---|---|---|
MAIL_DRIVER |
smtp |
The config uses the legacy mail.driver key, so this is MAIL_DRIVER, not MAIL_MAILER |
MAIL_HOST, MAIL_PORT |
smtp.example.com, 587 |
|
MAIL_USERNAME, MAIL_PASSWORD |
||
MAIL_ENCRYPTION |
tls |
Default tls |
MAIL_FROM_ADDRESS, MAIL_FROM_NAME |
no-reply@example.com, ulams |
Platform sender; quote names with spaces, see Environment |
Each tenant’s env file overrides the sender: MAIL_FROM_ADDRESS=no-reply@<email domain> and
MAIL_FROM_NAME=<tenant name>, where the e-mail domain comes from TENANCY_EMAIL_DOMAIN
(default {slug}.ulams.app; the production example uses {slug}.<your domain>). All tenants
share the platform’s SMTP credentials.
MJML rendering
Section titled “MJML rendering”The API image contains no mjml binary (no Node.js in the PHP image). Templates are rendered by
an MJML HTTP service:
| Variable | Value in the example |
|---|---|
MJML_API_URL |
http://mjml:15500/v1 |
Setting MJML_API_URL switches the renderer to the API (config/ulams_templates_email.php). The
example runs danihodovic/mjml-server on the internal network; it needs no inbound or outbound
access. Alternatives are the hosted MJML API (MJML_API_ID, MJML_API_SECRET) or a binary path
(MJML_BINARY_PATH) in a custom image.
Queues and the scheduler
Section titled “Queues and the scheduler”Template e-mails are sent by an event listener (packages/templates) in the process that raised
the event: in the web request for most actions, in a queue worker for events raised by jobs.
Reminders and deadline notices come from scheduled jobs (webinar and consultation reminders,
course deadlines, overdue tasks), so they need the scheduler and the workers: Horizon for the
platform and queue.sh for tenants, both inside api unless disabled with DISABLE_HORIZON,
DISABLE_QUEUE or DISABLE_SCHEDULER (see Monitoring).
Testing
Section titled “Testing”Use a staging relay or a capture service (the development stack uses MailHog on port 8025) before pointing a server at real learners. A password-reset request from the sign-in page is a quick end-to-end test of SMTP, MJML and the queue.