Skip to content

EMAIL_TRANSPORT doesn't actually select the email transport #1240

Description

@ThisIsMissEm

EMAIL_TRANSPORT looks like it selects the email transport, but it only
recognises one of the three that exist. The rest are chosen by side conditions.

Current behaviour

makeSendEmail (server/services/sendEmailService/sendEmailService.ts) falls
through in this order:

  1. an SES client was injected → SES
  2. EMAIL_TRANSPORT=console → console
  3. SENDGRID_API_KEY is set → SendGrid
  4. otherwise → SES via new SESClient({})

So setting an API key silently changes which transport you use, and there is no
value of EMAIL_TRANSPORT that selects SES or SendGrid deliberately.

Problems

The console transport needs a guard to be safe. It logs recipient addresses
and rendered notification content to stdout, so it throws unless
NODE_ENV=development. That guard is the tell: it is a debugging hack occupying
the slot that should hold a proper fake.

There is no local development story for email. You either print to the
console or send real mail. Nothing renders an actual message for inspection.

Email sending is untraced. All three transports go through vendor SDKs, and
per #1238 those are not instrumented under ESM anyway, so adding OpenTelemetry
coverage today would require solving that first.

Proposal

  1. Make EMAIL_TRANSPORT a real selector — ses, sendgrid, smtp — with the
    transport map alongside it, matching how @adonisjs/mail shapes this
    (default plus a mailers map) and how config/database.ts,
    config/redis.ts and config/dataWarehouse.ts now shape connections.
  2. Add an SMTP transport and a Mailpit service to docker-compose.yaml, so
    local development sees real rendered email in a UI.
  3. Replace the console transport with a fake/mock transport, and delete its
    NODE_ENV guard along with it.
  4. Optionally consolidate: one library behind all transports instead of three
    vendor SDKs (@aws-sdk/client-ses, @sendgrid/mail, plus whatever provides
    SMTP). Both Upyo (MIT, scoped @upyo/* packages per
    transport, includes mock and opentelemetry) and
    nodemailer would serve; either is fine.

server/config/email.ts already exists as of #1235, so the reads are in one
place and this change is only about how the transport is chosen.

Gates

Adding a mail library and a Mailpit compose service both require human approval
per AGENTS.md — a dependency licence/CVE check, and docker-compose.yaml is
on the approval list. Worth noting Upyo is pre-1.0 (0.6.0), which matters more
than usual given customers self-host.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    • Status
      Todo
    • Status
      Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions