# Quickstart (/docs/v/0.3.0/getting-started/quickstart)



Start with the scoped package:

```bash
bun add @opencoredev/email-sdk
```

The installed CLI command is named `email-sdk`. If you only need the CLI for a quick check, run `bunx --yes @opencoredev/email-sdk ...` instead. See <a href="/docs/v/0.3.0/getting-started/install">Install</a> for the package and CLI distinction.

## Send through Resend [#send-through-resend]

Set `RESEND_API_KEY`, then create a client with the Resend adapter.

```ts
import { createEmailClient } from "@opencoredev/email-sdk";
import { resend } from "@opencoredev/email-sdk/resend";

const email = createEmailClient({
  adapters: [resend({ apiKey: process.env.RESEND_API_KEY! })],
});

await email.send({
  from: "Acme <hello@acme.com>",
  to: "user@example.com",
  subject: "Welcome to Acme",
  text: "Your account is ready.",
});
```

## Check the send result [#check-the-send-result]

`send` resolves with the normalized adapter response. The `provider` value tells you which adapter
actually handled the send.

```ts
const result = await email.send(message);

console.log(result.provider);
console.log(result.id);
```

If the adapter returns a message ID, Email SDK exposes it as both `id` and `messageId`. Provider
responses are still available through `raw` when an adapter includes them.

## Verify from the CLI [#verify-from-the-cli]

Use `doctor` to check that the selected adapter has the required environment variables.

```bash
RESEND_API_KEY="re_..." bunx --yes @opencoredev/email-sdk doctor --adapter resend
```

Use `--dry-run` to validate the message shape without sending email.

```bash
bunx --yes @opencoredev/email-sdk send \
  --adapter resend \
  --from "Acme <hello@acme.com>" \
  --to "user@example.com" \
  --subject "Hello" \
  --text "It works" \
  --dry-run
```

When the package is installed in your project, the same command can run through the installed binary:

```bash
bun email-sdk doctor --adapter resend
```

## Add SMTP fallback [#add-smtp-fallback]

Add SMTP when you want a second route for the same transactional email. The SMTP adapter is built in
and does not require Nodemailer. When SMTP auth is configured on a non-secure connection, Email SDK
upgrades with STARTTLS before authenticating.

Only use fallback adapters that can send the same message shape. For example, SMTP supports address
fields and headers, but not provider-only fields like tags, metadata, or attachments.

```ts
import { createEmailClient } from "@opencoredev/email-sdk";
import { resend } from "@opencoredev/email-sdk/resend";
import { smtp } from "@opencoredev/email-sdk/smtp";

export const email = createEmailClient({
  adapters: [
    resend({ apiKey: process.env.RESEND_API_KEY! }),
    smtp({
      host: "smtp.purelymail.com",
      port: 587,
      auth: {
        user: process.env.SMTP_USER!,
        pass: process.env.SMTP_PASS!,
      },
    }),
  ],
  fallback: ["smtp"],
});
```

Your application still sends the same way:

```ts
await email.send({
  from: "Acme <hello@acme.com>",
  to: "user@example.com",
  subject: "Receipt",
  text: "Thanks for your order.",
});
```
