# SMTP Client

Send emails via SMTP with support for HTML content, CC/BCC, reply-to, and attachments.

## Methods

| Method                     | Description            |
| -------------------------- | ---------------------- |
| `send(options, metadata?)` | Send an email via SMTP |

## Usage

### Send a Simple Email

```typescript
import { api, z, smtp } from "@superblocksteam/sdk-api";

// Integration ID from the integrations panel
const MAILER = "a1b2c3d4-5678-90ab-cdef-111111111111";

export default api({
  name: "SendEmail",
  integrations: {
    mailer: smtp(MAILER),
  },
  input: z.object({
    to: z.string(),
    subject: z.string(),
    body: z.string(),
  }),
  output: z.object({ success: z.boolean() }),

  async run(ctx, { to, subject, body }) {
    await ctx.integrations.mailer.send({
      from: "noreply@example.com",
      to,
      subject,
      body,
    });

    return { success: true };
  },
});
```

### Send HTML Email

```typescript
await ctx.integrations.mailer.send({
  from: "noreply@example.com",
  to: "user@example.com",
  subject: "Welcome!",
  body: "<h1>Welcome!</h1><p>Thank you for signing up.</p>",
});
```

### Send with CC and BCC

```typescript
await ctx.integrations.mailer.send({
  from: "noreply@example.com",
  to: "user@example.com",
  subject: "Team Update",
  body: "Hello team!",
  cc: "manager@example.com,lead@example.com",
  bcc: "archive@example.com",
  replyTo: "support@example.com",
});
```

### Send to Multiple Recipients

Use comma-separated email addresses:

```typescript
await ctx.integrations.mailer.send({
  from: "noreply@example.com",
  to: "user1@example.com,user2@example.com,user3@example.com",
  subject: "Announcement",
  body: "<p>Important update for the team.</p>",
});
```

### Send with Attachments

Attachments are passed as a JSON string containing an array of objects with `content` (base64-encoded), `name` (filename), and `type` (MIME type):

```typescript
const attachments = JSON.stringify([
  {
    content: base64EncodedPdf, // Base64-encoded file content
    name: "report.pdf",
    type: "application/pdf",
  },
  {
    content: base64EncodedCsv,
    name: "data.csv",
    type: "text/csv",
  },
]);

await ctx.integrations.mailer.send({
  from: "reports@example.com",
  to: "user@example.com",
  subject: "Your Report",
  body: "<p>Please find the attached report.</p>",
  attachments,
});
```

## Trace Metadata

The `send` method accepts an optional `metadata` parameter as the last argument for diagnostics labeling:

```typescript
await ctx.integrations.mailer.send(
  {
    from: "noreply@example.com",
    to: "user@example.com",
    subject: "Welcome",
    body: "Hello!",
  },
  { label: "Send welcome email" },
);
```

When `includeDiagnostics` is enabled, `label` and `description` appear in the trace view. See the [root SDK README](../../../README.md#trace-metadata) for details.

## Send Options Reference

| Option        | Type     | Required | Description                                   |
| ------------- | -------- | -------- | --------------------------------------------- |
| `from`        | `string` | Yes      | Sender email address                          |
| `to`          | `string` | Yes      | Recipient(s), comma-separated for multiple    |
| `subject`     | `string` | Yes      | Email subject line                            |
| `body`        | `string` | Yes      | Email body (HTML or plain text)               |
| `cc`          | `string` | No       | CC recipient(s), comma-separated              |
| `bcc`         | `string` | No       | BCC recipient(s), comma-separated             |
| `replyTo`     | `string` | No       | Reply-to email address                        |
| `attachments` | `string` | No       | JSON array of `{content, name, type}` objects |

## Common Pitfalls

### Use the `send` Method, Not `apiRequest`

Unlike most integrations, SMTP has a dedicated `send()` method:

```typescript
// WRONG - apiRequest does not exist on SmtpClient
await ctx.integrations.mailer.apiRequest({ ... });

// CORRECT - Use send()
await ctx.integrations.mailer.send({
  from: "noreply@example.com",
  to: "user@example.com",
  subject: "Hello",
  body: "World",
});
```

### Attachments Must Be a JSON String

```typescript
// WRONG - Passing an array directly
await ctx.integrations.mailer.send({
  from: "noreply@example.com",
  to: "user@example.com",
  subject: "Report",
  body: "See attached",
  attachments: [{ content: "...", name: "file.pdf", type: "application/pdf" }],
});

// CORRECT - JSON.stringify the array
await ctx.integrations.mailer.send({
  from: "noreply@example.com",
  to: "user@example.com",
  subject: "Report",
  body: "See attached",
  attachments: JSON.stringify([
    { content: "...", name: "file.pdf", type: "application/pdf" },
  ]),
});
```

### Multiple Recipients Use Comma Separation

```typescript
// WRONG - Array of recipients
await ctx.integrations.mailer.send({
  to: ["user1@example.com", "user2@example.com"],
  // ...
});

// CORRECT - Comma-separated string
await ctx.integrations.mailer.send({
  to: "user1@example.com,user2@example.com",
  // ...
});
```

## Error Handling

```typescript
import { IntegrationError } from "@superblocksteam/sdk-api";

try {
  await ctx.integrations.mailer.send({
    from: "noreply@example.com",
    to: "user@example.com",
    subject: "Test",
    body: "Hello",
  });
} catch (error) {
  if (error instanceof IntegrationError) {
    console.error(
      `SMTP error in ${error.integrationName}.${error.method}: ${error.message}`,
    );
  }
}
```
