> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bosonware.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Sending emails

> Full reference for sendEmail: parameters, client-side validation, JSON vs multipart transport, Result fields, and TypeScript and JavaScript examples.

`sendEmail` is the primary method for submitting messages through the BosonMail API. It accepts a recipient list, a subject, and a body object that can contain text, HTML, CC, BCC, and attachments. The method always resolves, even on failure, and returns a `Result` object that tells you whether the API accepted the message.

## Signature

```typescript theme={null}
sendEmail(
  to: string | string[],
  subject: string,
  body: SendEmailBody
): Promise<Result>
```

## Parameters

**to** `string | string[]` *required*

Primary recipient(s). A single email address or an array of addresses. Must contain at least one non-empty string after trimming. The SDK does not validate email address format; the API checks that server-side.

**subject** `string` *required*

Email subject line. Must be a non-empty string after trimming.

**body** `SendEmailBody` *required*

The email content and optional fields.

### SendEmailBody fields

**body.text** `string`

Plain text content. Either `text` or `html` (or both) must be provided as a non-empty string after trimming.

**body.html** `string`

HTML content. Either `text` or `html` (or both) must be provided as a non-empty string after trimming.

**body.cc** `string | string[]`

Carbon-copy recipients. Accepts a single address or an array.

**body.bcc** `string | string[]`

Blind carbon-copy recipients. Accepts a single address or an array.

**body.attachments** `SendAttachment[]`

File attachments. When present, the request switches to `multipart/form-data`. See [Attachments](https://docs.bosonware.com/sdk/attachments.md) for full details.

## Return value

**success** `boolean` *required*

`true` when the API accepted the email. `false` for any validation, network, API, or timeout failure.

**errorMessage** `string`

Human-readable description when `success` is `false`.

**statusCode** `number`

HTTP status code from the API response. Absent for client-side validation errors and network/timeout failures.

**id** `string`

BosonMail message ID, returned as a string when present in the API response.

**messageId** `string`

API message identifier. May be `undefined` even on success, so always check it before calling `getEmailStatus`.

**status** `EmailSentStatus`

Initial status from the API. Defaults to `"queued"` when the API omits it.

## Transport: JSON vs multipart

The SDK chooses the request format automatically:

* **No attachments**: `Content-Type: application/json`, `POST /emails/send`. Body fields `to`, `cc`, `bcc` are joined with `,` (no space) when arrays.
* **With attachments**: `multipart/form-data` (boundary set by `fetch`), `POST /emails/send`. Fields: `to`, `subject`, `textContent`, `htmlContent`, `cc`, `bcc`, and one `attachments` field per file. Array fields are joined with `, ` (comma + space) after trimming each element.

> [!NOTE]
>
> The SDK does not set the `Content-Type` header for multipart requests; `fetch` handles the boundary automatically.

> [!WARNING]
>
> The published README lists the endpoint as `POST /mail/send`, but the SDK source code (v0.2.0 and v0.2.1) calls `POST /emails/send`. The code is authoritative. Contact BosonWare at [support@bosonware.com](mailto:support@bosonware.com) to confirm the intended endpoint.

## Client-side validation

Before any network request, the SDK validates the input. These errors return `{ success: false, errorMessage }` with no `statusCode`:

| Validation rule | Exact error message |
| - | - |
| `to` is empty or all elements empty after trim | `'to' must contain at least one recipient` |
| `subject` is empty after trim | `'subject' must be a non-empty string` |
| `body` is not an object | `'body' must be an object` |
| `text` or `html` is not a string | `'text' and 'html' must be strings` |
| Neither `text` nor `html` is non-empty after trim | `Email must contain text or HTML content` |
| `attachments` is not an array | `'attachments' must be an array` |
| More than 10 attachments | `A maximum of 10 attachments is allowed` |
| Attachment missing `filename` | `Each attachment must have a filename` |
| Attachment `content` is not Blob, ArrayBuffer, or Uint8Array | `Invalid content for attachment "<filename>"` |
| Attachment exceeds 10 MiB | `Attachment "<filename>" exceeds the 10 MB per-attachment limit` |
| Total attachment size exceeds 20 MiB | `Total attachment size exceeds the 20 MB limit` |
| Request body preparation fails | `Failed to prepare email: <message>` |

## What success means

A successful `sendEmail` means the BosonMail API **accepted** the message. The typical initial `status` is `"queued"`. It does not mean the email has been delivered, read, or that the recipient address is valid. Use [getEmailStatus](https://docs.bosonware.com/sdk/email-status.md) to track delivery progress.

## Examples

### Plain text email

```typescript send-text.ts theme={null}
import BosonMailClient from "@bosonware-ent/bosonmail";

const client = new BosonMailClient({ apiKey: process.env.BOSONMAIL_API_KEY! });

const result = await client.sendEmail(
  "customer@example.com",
  "Your order confirmation",
  { text: "Thank you for your order. We will notify you when it ships." }
);

if (result.success) {
  console.log("Accepted:", result.messageId, "Status:", result.status);
} else {
  console.error("Failed:", result.errorMessage, "HTTP:", result.statusCode);
}
```

```javascript send-text.mjs theme={null}
import BosonMailClient from "@bosonware-ent/bosonmail";

const client = new BosonMailClient({ apiKey: process.env.BOSONMAIL_API_KEY });

const result = await client.sendEmail(
  "customer@example.com",
  "Your order confirmation",
  { text: "Thank you for your order. We will notify you when it ships." }
);

if (result.success) {
  console.log("Accepted:", result.messageId, "Status:", result.status);
} else {
  console.error("Failed:", result.errorMessage, "HTTP:", result.statusCode);
}
```

### HTML email with CC

```typescript send-html-cc.ts theme={null}
import BosonMailClient from "@bosonware-ent/bosonmail";

const client = new BosonMailClient({ apiKey: process.env.BOSONMAIL_API_KEY! });

const result = await client.sendEmail(
  ["customer@example.com", "partner@example.com"],
  "Monthly report",
  {
    html: "<h1>Monthly report</h1><p>Your report is attached.</p>",
    cc: "manager@example.com"
  }
);

if (result.success && result.messageId) {
  console.log("Message ID:", result.messageId);
}
```

### With attachments

```typescript send-with-attachments.ts theme={null}
import BosonMailClient from "@bosonware-ent/bosonmail";
import { readFile } from "node:fs/promises";

const client = new BosonMailClient({ apiKey: process.env.BOSONMAIL_API_KEY! });

const pdf = await readFile("./invoice.pdf");

const result = await client.sendEmail(
  "billing@example.com",
  "Invoice for October",
  {
    text: "Your invoice is attached.",
    html: "<p>Your invoice is attached.</p>",
    attachments: [
      { filename: "invoice-october.pdf", content: pdf, contentType: "application/pdf" }
    ]
  }
);
```

> [card] [HTML emails](https://docs.bosonware.com/sdk/html-emails.md)
>
> Best practices for HTML content, multipart compatibility, and escaping user input.

> [card] [Attachments](https://docs.bosonware.com/sdk/attachments.md)
>
> Supported content types, size limits, and security considerations.

> [card] [Multiple recipients](https://docs.bosonware.com/sdk/multiple-recipients.md)
>
> How arrays are serialized and when to send individual emails instead.

> [card] [Error handling](https://docs.bosonware.com/sdk/error-handling.md)
>
> How to classify failures and decide when to retry.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.