# Quickstart: SMTP relay

> Point any existing SMTP config at the Email Fast relay: smtp.emailfast.dev on 587 STARTTLS or 465 TLS, project as username, API key as password.

Canonical: https://emailfast.dev/docs/quickstart-smtp

## The settings

Any framework, CMS, or legacy app with an SMTP config block can point here:

```text
host:     smtp.emailfast.dev
port:     587   (STARTTLS)  — or 465 (implicit TLS)
username: your project slug
password: your API key
```

Two rules worth knowing before you paste those in:

- **Auth is refused before TLS.** The relay will not accept `AUTH` on a
  plaintext connection — on 587 the session must upgrade via STARTTLS first, on
  465 it is encrypted from the first byte. Your API key is never on the wire in
  the clear.
- **This ingress arms at launch.** The relay is built and tested, but live SMTP
  submission opens with GA. Today, evaluate against the sandbox via the REST
  API — sandbox keys (ef_sandbox_…) that run the real pipeline dry: real validation, real rendering, real events, a hosted capture inbox — and no email leaves — and stage your config change for launch day.

## Nodemailer

```js
import nodemailer from "nodemailer";

const transport = nodemailer.createTransport({
  host: "smtp.emailfast.dev",
  port: 587,
  secure: false, // 587 = STARTTLS; set true with port 465 for implicit TLS
  requireTLS: true, // never fall back to plaintext
  auth: {
    user: "your-project",
    pass: process.env.EMAILFAST_API_KEY,
  },
});

await transport.sendMail({
  from: "you@yourdomain.com",
  to: "ada@example.com",
  subject: "Welcome",
  html: "<h1>Hi Ada</h1>",
  headers: { "Idempotency-Key": "welcome-ada-1" }, // retry-safe, per recipient
});
```

## Any other app

Most software takes the same five values, whatever it calls them:

```ini
SMTP_HOST=smtp.emailfast.dev
SMTP_PORT=587            ; or 465
SMTP_ENCRYPTION=starttls ; "tls"/"ssl" if your app means implicit TLS on 465
SMTP_USERNAME=your-project
SMTP_PASSWORD=ef_live_...
```

## What happens to the message

SMTP here is an ingress, not a bypass. Each recipient in the envelope is admitted
individually through the same checkpoint as an API call — every send — REST, SMTP, browser SDK, compatibility endpoints, broadcasts, automations — passes through one admission gate: idempotency, suppression, quota, and content policy in a single checkpoint no ingress can skip.

That per-recipient admission carries idempotent retry semantics: pass an
`Idempotency-Key` header and a client that reconnects and resends after a dropped
connection cannot double-send: a 202 from the API means the send is committed to a durable, partitioned outbox before we answer — a crash can't lose it, and a retry with the same idempotency key can't double-send.

## Next

- [Prefer HTTP? The REST quickstart](/docs/quickstart-curl)
- [Migrating from SendGrid/Mailgun/Postmark](/features/migration)
- [All docs](/docs)
