Skip to content

Support Cloudflare Email Sending in self-hosted SMTP settings #417

Description

@WPitombeira

Problem

OpenShip already supports custom SMTP and several send-only provider presets,
but Cloudflare Email Sending requires users to manually discover and enter its
fixed submission settings:

  • host: smtp.mx.cloudflare.net
  • port: 465 (implicit TLS)
  • username: api_token
  • password: a Cloudflare API token with Email Sending edit permission

In a self-hosted Docker deployment, that manual configuration currently cannot
complete a send. Nodemailer establishes TLS under Bun but never receives the
SMTP greeting and eventually reports ETIMEDOUT: Greeting never received. The
same Nodemailer version, host, machine, and configuration complete the
greeting/EHLO flow under Node.js 22. Bun 1.3.10 reproduces the timeout, so a Bun
version bump alone does not resolve it.

Proposed approach

  1. Add a Cloudflare send-only preset to the existing shared mail-provider list
    so selecting it prefills the host, port, and fixed username, leaving only the
    From address/domain and API token for the user.
  2. Run the production API container under Node.js 22 so Nodemailer uses Node's
    TLS implementation.
  3. Retain Bun in the final image for existing operational commands, and use the
    existing tsx loader because workspace packages ship TypeScript source with
    extensionless imports.
  4. Keep the existing encrypted SMTP credential storage and test-email endpoint
    unchanged.

This requires no new endpoint, database migration, dependency, or
Cloudflare-specific secret-storage path.

Scope question

Is switching only the production API container runner from Bun to Node (while
retaining Bun in the image) acceptable for this integration, or would
maintainers prefer the runtime fix and provider preset to be proposed
separately?

Verification plan

  • Regression tests for the provider preset and Docker runtime contract
  • API and dashboard workspace checks
  • Full repository test suite
  • Clean API Docker image build and health check
  • Authenticated Nodemailer verify() against a user-controlled Cloudflare
    Email Sending domain
  • User-controlled real test-email delivery

A working fork branch exists for local validation, but I will wait for agreement
on scope and approach before opening the upstream PR, per CONTRIBUTING.md.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions