Outbound (SMTP)

Última actualización: May 6, 2026Sección: General

Outbound (SMTP)

Mailoo sends email through three distinct layers. Each layer has different credentials, security boundaries, and intended recipients.

::: {.contents local="" depth="2"} :::

1. Integration SMTP (outboundMail)

What: SMTP settings stored on a specific integration under integration.config.outboundMail (dashboard: Connection & settingsOutbound email (SMTP)).

Who receives mail: End users and business flows for that integration only, for example:

  • Dashboard Create reply to inbound messages (FORM / CONTACT_FORM).
  • Optional welcome email after a new form subscription when an ON_EVENT / SUBSCRIBER_CREATED campaign is configured.
  • Market email checkout: confirmation email to the buyer after POST …/market/…/orders (same outboundMail as the Market integration that owns the catalog).

API: Owner-only Bearer routes to PATCH integration config / outboundMail and to test SMTP:

POST /api/v1/projects/{projectUid}/integrations/{integrationId}/outbound-mail/test

Supported integration types for this panel and test route: FORM, CONTACT_FORM, and MARKET.

Security: SMTP passwords are stored encrypted (API env MAIL_SMTP_ENCRYPTION_KEY). The API never returns ciphertext or plaintext to clients; responses may include hasSmtpPassword only.

No fallback: If integration SMTP is missing, invalid, or sending fails, Mailoo does not substitute the global mailer. Dashboard Create reply returns an error when SMTP is not configured; welcome emails are skipped and logged when SMTP is unavailable; Market orders return emailToCustomer.status: NOT_CONFIGURED when outboundMail is not set.

See ../../../development/environment{.interpreted-text role="doc"} for variable names.

2. Offer Generator SMTP (separate from outboundMail)

What: Per--offer-generator mail settings in OfferGeneratorMailSettings (not integration.config.outboundMail).

Who receives mail: Wizard submitters (customer delivery) and optional internal notification address configured on the generator.

Why separate: Offer Generator may use different branding, relay limits, or operators than the rest of the Market integration.

This iteration does not merge Offer Generator SMTP with integration outboundMail.

3. Global / platform SMTP (GLOBAL_SMTP_*, GLOBAL_MAIL_FROM)

What: Environment variables on the API host only.

Intended use: Reserved for operator / platform notifications (billing, security alerts, compliance, future system mail). Not used for subscriber-facing mail, Market buyer confirmations, or Offer Generator delivery.

Current product behavior: No user-facing feature depends on global SMTP in this release; configure it when you introduce platform-level mail.

No fallback: Global SMTP is never substituted when integration SMTP fails.

External use of integration SMTP (integrator sites)

Not implemented in this iteration. Today, integrators should not embed Mailoo integration SMTP credentials in public browser code. Prefer:

  • Server or BFF calls to Mailoo APIs that trigger Mailoo-side email (e.g. Market order create sends confirmation from Mailoo using outboundMail), or
  • The integrator's own mailer on their backend.

If a future external SMTP API is added, it would require at minimum: a dedicated API-key scope, strict rate limits, abuse monitoring, audit logging, and a clear threat model (credential exfiltration, spam relay).

Dashboard test email

On Connection & settingsOutbound email (SMTP), use Send test email to verify the current field values (you do not have to save first). Mailoo sends one message to your Mailoo account email (the signed-in user). Nothing is persisted by the test alone; saving still uses Save SMTP settings.

If the API host is missing MAIL_SMTP_ENCRYPTION_KEY and you enter a new SMTP password in the form, save and test return 503 with a clear configuration message---set the key on the API (same value on every replica), e.g. openssl rand -base64 32.

Owner API (optional)

Same as the dashboard test: POST /api/v1/projects/{projectUid}/integrations/{integrationId}/outbound-mail/test with Bearer auth; body { "outboundMail": { … } } matches the PATCH outboundMail field shape.