Open Schedule sends transactional emails for:
- Forgot password — password reset link / temporary password
- Welcome — signup confirmation
- Session share — share a session with someone
All outbound email is managed by a unified mail subsystem with:
- environment-based defaults in
application.yml - optional runtime overrides stored in the database
- an admin UI at
Admin → Mail settings - support for SMTP, SendGrid, Mailjet, and Postal
The admin UI is only available to authenticated administrators. It can:
- enable or disable outbound email
- choose the provider type
- update sender identity
- update host, port, credentials, timeouts, and security mode
- send a test email
- store secrets encrypted in the database when explicitly enabled
Open Schedule resolves mail settings in this order:
- Stored admin overrides from the
mail_settingstable - Environment defaults from
application.email.* - Provider-specific safe defaults for SendGrid and Mailjet
Secrets are handled differently:
- if
EMAIL_SETTINGS_MASTER_KEYandEMAIL_ALLOW_UI_SECRET_PERSISTENCE=trueare configured, admins can store secrets encrypted from the UI - otherwise, secrets must come from environment variables such as
EMAIL_SMTP_PASSWORDorPOSTAL_API_KEY - the UI never displays the raw secret value
| Scenario | Configuration |
|---|---|
| Local development | SMTP → Mailpit (default, no credentials needed) |
| Production with SendGrid | SendGrid via SMTP relay |
| Production with Mailjet | Mailjet via SMTP relay |
| Production with Postal | Postal HTTP API (POSTAL_ENABLED=true) |
| Disable email entirely | EMAIL_OUTBOUND_ENABLED=false or disable in the admin UI |
When POSTAL_ENABLED=true, Postal becomes the default provider on first boot unless an admin has already saved a different provider in the UI.
Works with any SMTP server including your own Postfix/Exim, business email, or self-hosted relay.
EMAIL_OUTBOUND_ENABLED=true
EMAIL_PROVIDER_TYPE=SMTP
EMAIL_SECURITY_MODE=STARTTLS
EMAIL_AUTH_ENABLED=true
EMAIL_SMTP_HOST=mail.yourdomain.com
EMAIL_SMTP_PORT=587
EMAIL_SMTP_USERNAME=no-reply@yourdomain.com
EMAIL_SMTP_PASSWORD=your-smtp-password
EMAIL_FROM_ADDRESS=no-reply@yourdomain.com
EMAIL_FROM_NAME=Open ScheduleFor servers with self-signed TLS certificates (e.g. internal mail relays):
EMAIL_SMTP_SSL_TRUST=mail.yourdomain.comLeave EMAIL_SMTP_SSL_TRUST blank for all public providers — they have valid certificates.
SendGrid offers a free tier (100 emails/day) and a reliable SMTP relay.
Prerequisites: Verify your sender domain in the SendGrid dashboard under Settings → Sender Authentication.
EMAIL_OUTBOUND_ENABLED=true
EMAIL_PROVIDER_TYPE=SENDGRID
EMAIL_SMTP_HOST=smtp.sendgrid.net
EMAIL_SMTP_PORT=587
EMAIL_SMTP_USERNAME=apikey
EMAIL_SMTP_PASSWORD=SG.xxxxxxxxxxxxxxxxxxxx # your SendGrid API key
EMAIL_FROM_ADDRESS=no-reply@yourdomain.com
EMAIL_FROM_NAME=Open ScheduleThe username is literally the string
apikey— SendGrid uses the API key as the password.
Mailjet offers a free tier (200 emails/day) and simple SMTP relay.
Prerequisites: Verify your sender domain in Mailjet under Account → Sender domains & addresses.
EMAIL_OUTBOUND_ENABLED=true
EMAIL_PROVIDER_TYPE=MAILJET
EMAIL_SMTP_HOST=in-smtp.mailjet.com
EMAIL_SMTP_PORT=587
EMAIL_SMTP_USERNAME=your-mailjet-api-key
EMAIL_SMTP_PASSWORD=your-mailjet-secret-key
EMAIL_FROM_ADDRESS=no-reply@yourdomain.com
EMAIL_FROM_NAME=Open ScheduleGet your API key and Secret key from the Mailjet API Key Management page.
Postal is a fully open-source mail delivery platform. Open Schedule integrates with its HTTP API directly — not via SMTP.
Prerequisites:
- A running Postal installation
- An organization, server, and credential created in Postal
- Your sender domain added and DNS records verified
POSTAL_ENABLED=true
EMAIL_PROVIDER_TYPE=POSTAL
EMAIL_OUTBOUND_ENABLED=true
POSTAL_BASE_URL=https://postal.yourdomain.com
POSTAL_API_KEY=your-postal-server-api-key
POSTAL_API_KEY_HEADER=X-Server-API-Key
# Sender info (shared with all providers)
EMAIL_FROM_ADDRESS=no-reply@yourdomain.com
EMAIL_FROM_NAME=Open ScheduleHow to get the API key:
- Log in to your Postal instance
- Go to your mail server → Credentials
- Create an API credential
- Copy the key
API call details (for debugging):
POST https://postal.yourdomain.com/api/v1/send/message
X-Server-API-Key: your-api-key
Content-Type: application/json
{
"from": "Open Schedule <no-reply@yourdomain.com>",
"to": ["user@example.com"],
"subject": "Your subject",
"html_body": "<h1>Hello</h1>"
}
For local development, the default configuration points to Mailpit, a lightweight email catcher that captures all outbound email without delivering it.
# These are the defaults in .env.dist — no changes needed for dev
EMAIL_OUTBOUND_ENABLED=true
EMAIL_PROVIDER_TYPE=SMTP
EMAIL_SMTP_HOST=localhost
EMAIL_SMTP_PORT=1026
EMAIL_SMTP_USERNAME=dev@example.com
EMAIL_SMTP_PASSWORD=
EMAIL_FROM_ADDRESS=no-reply@example.com
EMAIL_FROM_NAME=Open ScheduleStart Mailpit with Docker:
docker compose up -d mailpitView captured emails at http://localhost:8026.
- Sign in as an administrator
- Open
Admin → Mail settings - Select the provider type
- Fill in sender identity and provider fields
- Save the configuration
- Enter a
Test recipientaddress - Click
Send test email
If encrypted secret persistence is disabled, the view will tell you that secrets must be provided through environment variables.
Recommended flow:
- Configure the provider from environment variables and/or the admin UI
- Save settings from
Admin → Mail settings - Send a test email from the admin view
- Validate provider-side logs or delivery dashboards
Fallback flow:
- Open the app and click
Forgot password - Enter a valid user's email address
- Check your provider logs for delivery status
For Postal, the Postal web UI shows message delivery status, bounces, and logs per message.
- Store
EMAIL_SMTP_PASSWORD,POSTAL_API_KEY, andEMAIL_SETTINGS_MASTER_KEYin a secrets manager, not in plain.envfiles on the server - Verify your sending domain with SPF, DKIM, and DMARC records to avoid spam filtering
- Do not set
EMAIL_SMTP_SSL_TRUSTin production unless you genuinely need to bypass certificate validation - Only enable
EMAIL_ALLOW_UI_SECRET_PERSISTENCE=truewhen you also provide a strongEMAIL_SETTINGS_MASTER_KEY - Rotate API keys periodically
| Symptom | Likely cause | Fix |
|---|---|---|
| Emails not sent, no error in logs | Outbound email disabled | Set EMAIL_OUTBOUND_ENABLED=true or enable outbound email in the admin UI |
Authentication failed |
Wrong credentials | Verify EMAIL_SMTP_USERNAME / PASSWORD |
Connection refused |
Wrong host/port | Check EMAIL_SMTP_HOST and EMAIL_SMTP_PORT |
| Emails go to spam | Domain not verified | Add SPF/DKIM/DMARC records |
| SendGrid 403 | Sender not verified | Verify sender in SendGrid dashboard |
Postal non-success status |
Invalid API key or server URL | Check POSTAL_BASE_URL (no trailing slash) and POSTAL_API_KEY |
| Self-signed TLS error | Cert not trusted | Set EMAIL_SMTP_SSL_TRUST=your-smtp-host |
| UI cannot store the secret | Secret persistence disabled | Configure EMAIL_SETTINGS_MASTER_KEY and EMAIL_ALLOW_UI_SECRET_PERSISTENCE=true, or keep the secret in environment variables |