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

# Email client

> Full reference for the Paubox Node.js SDK email service: building messages, sending email, tracking delivery, dynamic templates, and error handling.

## Create the service

```javascript theme={null}
const pbMail  = require('paubox-node');

// Read credentials from environment variables
const service = pbMail.emailService();

// Or pass credentials directly
const service = pbMail.emailService({ apiKey: 'YOUR_API_KEY', apiUsername: 'YOUR_USERNAME' });
```

## Build a message

```javascript theme={null}
const message = pbMail.message({
  from:         'sender@yourdomain.com',  // required
  to:           ['alice@example.com'],    // required; array of recipients
  subject:      'Your results are ready', // optional
  reply_to:     'support@yourdomain.com', // optional
  cc:           ['manager@example.com'],  // optional
  bcc:          ['audit@example.com'],    // optional
  text_content: 'Plain text body.',       // at least one of text/html required
  html_content: '<p>HTML body.</p>',      // optional; auto base64-encoded
  allowNonTLS:  false,                    // optional; default false
  forceSecureNotification: false,         // optional; default false
  custom_headers: { 'X-Custom': 'value' },// optional; keys must start with X-
  list_unsubscribe:      '<mailto:unsub@yourdomain.com>', // optional
  list_unsubscribe_post: 'List-Unsubscribe=One-Click',   // optional
  attachments: [attachment]               // optional; see below
});
```

### Attachments

```javascript theme={null}
const fs = require('fs');

const attachment = {
  fileName:    'report.pdf',
  contentType: 'application/pdf',
  content:     fs.readFileSync('report.pdf').toString('base64')
};
```

## Send a message

```javascript theme={null}
const response = await service.sendMessage(message);
console.log('Tracking ID:', response.sourceTrackingId);
```

## Send bulk messages

Send up to 50 messages in a single API call. Each message gets its own tracking ID.

```javascript theme={null}
const messages = [
  pbMail.message({ from: 'f@yourdomain.com', to: ['alice@example.com'], subject: 'Hi Alice', text_content: 'Hello Alice' }),
  pbMail.message({ from: 'f@yourdomain.com', to: ['bob@example.com'],   subject: 'Hi Bob',   text_content: 'Hello Bob' }),
];

const response = await service.sendBulkMessages(messages);

for (const msg of response.messages) {
  console.log('Tracking ID:', msg.sourceTrackingId);
}
```

## Check delivery status

```javascript theme={null}
const disposition = await service.getEmailDisposition(sourceTrackingId);

for (const delivery of disposition.data.message.message_deliveries) {
  console.log(`${delivery.recipient} → ${delivery.status.deliveryStatus}`);
}
```

Common `deliveryStatus` values: `delivered`, `opened`, `failed`, `pending`. The `openedStatus` field defaults to `"unopened"` if not yet set.

## Dynamic templates

Templates use [Handlebars](https://handlebarsjs.com) syntax (`{{variable_name}}`). Template content can be a string, `Buffer`, or readable `Stream`.

### Create a template

```javascript theme={null}
const fs = require('fs');

const response = await service.createDynamicTemplate(
  'appointment-confirmation',
  fs.createReadStream('templates/appointment.html')
);
```

### List templates

```javascript theme={null}
const templates = await service.listDynamicTemplates();
for (const t of templates) {
  console.log(t.id, t.name);
}
```

### Get a template

```javascript theme={null}
const template = await service.getDynamicTemplate(templateId);
```

### Update a template

Pass `null` for fields you want to leave unchanged:

```javascript theme={null}
await service.updateDynamicTemplate(
  templateId,
  'appointment-confirmation-v2', // new name, or null to keep current
  null                            // content unchanged
);
```

### Delete a template

```javascript theme={null}
await service.deleteDynamicTemplate(templateId);
```

### Send a templated message

```javascript theme={null}
const message = pbMail.templatedMessage({
  from:            'appointments@yourclinic.com',
  to:              ['jane@example.com'],
  subject:         'Your appointment is confirmed',
  template_name:   'appointment-confirmation',
  template_values: {
    first_name: 'Jane',
    date:       '2024-03-15',
    time:       '2:00 PM'
  }
});

const response = await service.sendTemplatedMessage(message);
```

## Error handling

All service methods return Promises and reject on API errors. Use `try/catch` in async functions:

```javascript theme={null}
try {
  const response = await service.sendMessage(message);
  console.log('Sent:', response.sourceTrackingId);
} catch (err) {
  console.error('Send failed:', err.message);
}
```
