Конфигурация
Три способа построить клиент, все опции и то, что он отклоняет до отправки запроса.
Опции
import OpenEmail, { createOpenEmail, init, openemail } from '@openemail/sdk' init({ apiKey: process.env.OPENEMAIL_API_KEY })await openemail.me.ping() export const billing = createOpenEmail({ apiKey: process.env.BILLING_API_KEY! }) const pinned = new OpenEmail({ apiKey: 'oe_live_…', baseUrl: 'https://api.openemail.uk' }) const quick = new OpenEmail('oe_live_…')| Точка входа | Что вы получаете |
|---|---|
| `init(options)` | Настраивает общий клиент и возвращает его. С этого момента openemail — именно этот клиент, в любом модуле, а всё, что вы не указали, читается из окружения. |
| `openemail` | Общий клиент. При использовании до init он строит себя из OPENEMAIL_API_KEY и OPENEMAIL_BASE_URL при первом вызове. |
| `createOpenEmail(options)` | Отдельный клиент с тем же запасным чтением окружения — для второго ключа рядом с общим или чтобы построить экземпляр, который экспортирует ваш собственный модуль. createClient — та же функция под именем, которое использует envless SDK. |
| `new OpenEmail(options)` или `new OpenEmail(apiKey)` | Отдельный клиент, построенный ровно из того, что вы передали. Он не читает окружение, так что apiKey обязателен. Он же экспорт по умолчанию. |
init({ apiKey: 'oe_live_…', baseUrl: 'https://api.openemail.uk', timeoutMs: 30_000, maxRetries: 2, fetch: myFetch, headers: {}, userAgent: 'billing-service/1.4', disableUpdateNotice: true,})| Опция | По умолчанию | Примечания |
|---|---|---|
| `apiKey` | OPENEMAIL_API_KEY | Читается из окружения функциями init и createOpenEmail. Должен начинаться с oe_live_ или oe_test_. |
| `baseUrl` | https://api.openemail.uk | Или OPENEMAIL_BASE_URL. Завершающий слеш срезается, а init и createOpenEmail подставляют https:// перед голым хостом и http:// перед localhost. |
| `timeoutMs` | 30000 | На попытку, а не на вызов. Покрывает чтение тела, а не только заголовков. 0 отключает его. |
| `maxRetries` | 2 | Дополнительные попытки после первой, для вызовов, которые безопасно повторять. Задаётся на клиенте, а не на вызове. |
| `fetch` | глобальный | Привязывается за вас. Передайте свой для прокси, привязки Worker или тестового двойника. |
| `headers` | {} | Отправляются с каждым запросом. |
| `userAgent` | openemail-sdk/<version> | Отправляется из любой среды, кроме браузера, который не разрешает его задавать. |
| `disableUpdateNotice` | false | Пропускает однократную за процесс проверку новой версии на npm. Проверка выполняется, только когда вывод идёт в терминал, и OPENEMAIL_DISABLE_UPDATE_NOTICE тоже её отключает. |
| `dangerouslyAllowBrowser` | false | Позволяет клиенту стартовать там, где есть window и document. Предназначено для тестового стенда, который их определяет, а не для страницы. |
Что он отклоняет до отправки
Они бросают обычный Error из той строки, где было неправильное значение, а не всплывают как непонятный сбой при вашей первой отправке. В сообщении сказано, что было не так и что передать вместо этого.
| Отклонено | Почему |
|---|---|
| Ключа нет вовсе | Ни apiKey, ни OPENEMAIL_API_KEY не заданы, так что аутентифицироваться нечем. |
| Сессионная кука или сессионный токен | Здесь аутентифицируют только oe_live_ и oe_test_, и API говорит то же самое. Проверка — это префикс и ничего больше, так что отозванный ключ всё равно упадёт на проводе. |
| `baseUrl`, не являющийся http- или https-адресом | Ничего другого получить нельзя, а непроверенный адрес упал бы позже сырым TypeError совсем из другого места. |
| Браузер | Ключ смог бы прочитать любой, кто откроет devtools. См. раздел ниже. |
| Нигде нет `fetch` | Передайте его как fetch или запускайтесь на Node 20+. |
| Пустой идентификатор или идентификатор из одних точек в любом методе | Бросается при вызове метода. Сегмент пути из точек удаляется любым парсером URL, так что запрос попал бы на другой эндпоинт. |
Опции testMode нет и не будет. Схема ключа — часть учётных данных, а не подсказка, так что режим — свойство ключа. openemail.mode читает префикс и ничего не решает.
Один клиент, несколько ключей
Постройте клиент один раз и используйте его совместно. Новый экземпляр на каждый запрос без всякой пользы выбрасывает привязку fetch и конфигурацию, а никакое состояние в нём не привязано к вызывающей стороне.
Для случая, который иначе потребовал бы по экземпляру на ключ, — например, задания, отправляющего от имени нескольких рабочих пространств, — передайте apiKey в вызов. Он заменяет заголовок Authorization для этого запроса и ничего не оставляет на клиенте.
await openemail.emails.send(message) await openemail.emails.send(message, { apiKey: workspace.apiKey }) await openemail.threads.list({ folder: 'inbox', apiKey: workspace.apiKey })await openemail.webhooks.list({ apiKey: workspace.apiKey })Каждый метод вне tempMail принимает его в последнем аргументе, рядом с signal, а в списках — в том же объекте, что и фильтры. Он проверяется до отправки запроса, по тому же правилу, что и в конструкторе, так что опечатка бросит Error с упоминанием { apiKey } on this call, а не 401 про учётные данные, которые потом придётся искать. Повторённый вызов сохраняет выданный ему ключ.
signal — это AbortSignal. Его срабатывание останавливает запрос и любой повтор, ожидающий за ним.
openemail.mode описывает ключ, с которым клиент был СОЗДАН, и не следует за переопределением. Как только один клиент обслуживает несколько ключей, единого режима, о котором можно сообщить, не существует, так что читайте его по переданному ключу.
Из браузера
Клиент отказывается стартовать в браузере и бросает исключение до того, как уйдёт хоть один запрос. Ключ на странице — это опубликованный ключ: он может отправлять почту и читать почтовый ящик для любого, кто откроет devtools. Вызывайте его с сервера, из бессерверной функции или из скрипта.
Одноразовые ящики — исключение. createTempMail() строит клиент, который не несёт ключа API, поэтому он безопасен на странице. Он создаёт ящики анонимно, и каждое чтение отправляет токен, который вернул create, — либо для каждого вызова как inboxToken, либо один раз как createTempMail({ inboxToken }).
import { createTempMail } from '@openemail/sdk' const tempMail = createTempMail() const inbox = await tempMail.create()const { items, expiresAt } = await tempMail.listMessages(inbox.id, { inboxToken: inbox.token })Там, где вы всё же передадите dangerouslyAllowBrowser: true, API пропускает через свой CORS-предзапрос ровно Content-Type, Authorization и Idempotency-Key, так что лишний заголовок в headers провалит предзапрос, а не сам запрос, и то, что браузер об этом сообщит, не скажет ничего полезного.