envelopeSMTP Configuration

Configure SMTP delivery for transactional emails such as account confirmation and password reset.

Hexabot uses SMTP for transactional emails sent by the API. In the current NestJS implementation, SMTP is used for account confirmation emails and password reset emails.

The mailer is configured from EMAIL_SMTP_* environment variables, then registered with @nestjs-modules/mailer, Nodemailer SMTP transport, and MJMLarrow-up-right templates.

How Email Delivery Works

At API startup, Hexabot reads the SMTP environment variables and builds config.emails:

Config field
Source

config.emails.isEnabled

EMAIL_SMTP_ENABLED

config.emails.smtp.host

EMAIL_SMTP_HOST

config.emails.smtp.port

EMAIL_SMTP_PORT

config.emails.smtp.secure

EMAIL_SMTP_SECURE

config.emails.smtp.auth.user

EMAIL_SMTP_USER

config.emails.smtp.auth.pass

EMAIL_SMTP_PASS

config.emails.from

EMAIL_SMTP_FROM

When EMAIL_SMTP_ENABLED=true, the API registers a real SMTP transporter. When it is false, the API does not register the NestJS mailer transport and injects a fallback MailerService whose sendMail() method throws Email Service is not enabled.

That means SMTP can be disabled for local development only if you do not need email-dependent flows. Account creation still succeeds when the confirmation email cannot be sent, but the new user remains inactive until confirmed or enabled manually. Password reset requests require email delivery and will fail if SMTP is disabled or unreachable.

SMTP settings are read only at startup. Restart the API after changing environment variables.

SMTP Variables

EMAIL_SMTP_ENABLED=true
EMAIL_SMTP_HOST=smtp.example.com
EMAIL_SMTP_PORT=587
EMAIL_SMTP_SECURE=false
EMAIL_SMTP_USER=your-smtp-username
EMAIL_SMTP_PASS=your-smtp-password
EMAIL_SMTP_FROM="Hexabot <[email protected]>"
Variable
Required for sending
Default
Notes

EMAIL_SMTP_ENABLED

Yes

false

Must be exactly true to enable the real mailer module.

EMAIL_SMTP_HOST

Yes

localhost

Hostname reachable from the API process or API container.

EMAIL_SMTP_PORT

Yes

25

Common values are 25, 587, and 465, depending on the provider.

EMAIL_SMTP_SECURE

Yes

false

Use true for implicit TLS from connection start, usually port 465. Use false for plain SMTP or STARTTLS, commonly ports 25 or 587.

EMAIL_SMTP_USER

Usually

empty

SMTP username, API key username, or provider-specific login.

EMAIL_SMTP_PASS

Usually

empty

SMTP password, app password, or provider API key.

EMAIL_SMTP_FROM

Yes

Default sender used by MailerModule for outgoing email. Many providers require this address or domain to be verified.

Hexabot sets Nodemailer ignoreTLS to false, so STARTTLS can be used when the SMTP server advertises it and EMAIL_SMTP_SECURE=false.

Email templates include links back to the frontend. Set the public frontend URL correctly, especially in production:

The current templates use this value for:

Email
Link shape

Account confirmation

FRONTEND_BASE_URL/login/<token>

Password reset

FRONTEND_BASE_URL/reset/<token>

Set production-grade secrets and expiration values for the email tokens:

Do not reuse the development defaults in production.

Local Testing with smtp4dev

The repository includes a Docker Compose override for smtp4dev at docker/docker-compose.smtp4dev.yml.

smtp4dev exposes:

Service
Address

SMTP inside the Docker Compose network

smtp4dev:25

Web inbox on the host

http://localhost:9002

For Docker-based development, enable SMTP and point the API container at the smtp4dev service:

Then start Docker with the smtp4dev compose file. With the CLI:

Or directly from this repository:

Open http://localhost:9002 to inspect captured messages.

If the API runs on the host machine instead of inside the Docker Compose network, use the host mapping instead:

Production Example

For a typical authenticated SMTP provider using STARTTLS on port 587:

For a provider that requires implicit TLS on port 465, change only the port and secure flag:

Before going live, verify the provider-side requirements:

Requirement
Why it matters

Verified sender or domain

Providers often reject or rewrite unverified EMAIL_SMTP_FROM addresses.

Valid SMTP credentials

Some providers use API keys as the SMTP password.

Allowed outbound SMTP port

Cloud networks and hosting providers may block ports 25, 465, or 587.

Correct TLS mode

A port/secure mismatch is a common cause of connection failures.

The current environment mapping does not expose advanced Nodemailer options such as custom TLS certificates, requireTLS, or multiple transports. Add code-level configuration if your SMTP provider requires those options.

Verifying the Configuration

  1. Restart the API after editing the environment file.

  2. Open the dashboard and check Integrations Health.

  3. Look for Email (SMTP).

  4. A healthy SMTP card means verifyAllTransporters() succeeded.

  5. Trigger a real email flow, such as a password reset request or creating a user that should receive an account confirmation email.

  6. Check the recipient inbox, provider logs, or smtp4dev web inbox.

The API also exposes integration health through /api/stats/integration-health for authenticated dashboard requests. The SMTP item reports one of these reasons:

Reason
Meaning

smtp.disabled

EMAIL_SMTP_ENABLED is not true.

smtp.verified

The configured transporter verified successfully.

smtp.verify_failed

The transporter verification failed.

smtp.timeout

Verification did not complete within the API health timeout.

Troubleshooting

Symptom
Likely cause
What to check

Email (SMTP) shows disabled

SMTP is not enabled

Set EMAIL_SMTP_ENABLED=true and restart the API.

Password reset returns an email error

Mailer is disabled or cannot send

Check SMTP health, API logs, and provider logs.

getaddrinfo ENOTFOUND smtp4dev

API process cannot resolve the Docker service name

Use smtp4dev only from inside Compose. Use localhost when the API runs on the host.

TLS or SSL handshake error

EMAIL_SMTP_SECURE does not match the port

Use secure=true for port 465; use secure=false for STARTTLS ports such as 587.

Authentication failed

Wrong user, password, API key, or sender policy

Regenerate credentials and confirm the provider's SMTP login format.

Emails send but links point to localhost

FRONTEND_BASE_URL still uses a development value

Set it to the public frontend URL and restart.

Health check times out

Network, firewall, or provider connectivity issue

Confirm the host and port are reachable from the API container or host.

Templates

Transactional email templates live in packages/api/src/templates:

  • account_confirmation.mjml

  • password_reset.mjml

The Nest build copies these files into dist/templates, and the mailer reads templates from that compiled directory at runtime. Templates are MJML files rendered through Handlebars. Keep template variable names aligned with the context objects passed by PasswordResetService and ValidateAccountService; missing Handlebars values render as empty strings.

Text translations used by the templates live under packages/api/src/config/i18n.

Last updated

Was this helpful?