SDK
Планирование и отмена
`scheduledAt`, `emails.reschedule` и `emails.cancel`.
Отправка позже
await openemail.emails.send({ ...message, scheduledAt: 'PT1H' })await openemail.emails.send({ ...message, scheduledAt: new Date('2027-01-01T09:00:00Z') })await openemail.emails.send({ ...message, scheduledAt: '2027-01-01T09:00:00.000Z' })Date, момент в ISO-8601 или длительность вроде PT1H / P2D. Не дальше года вперёд и никогда в прошлое.
Перенос и остановка
const queued = await openemail.emails.send({ ...message, scheduledAt: 'PT1H' }) await openemail.emails.reschedule(queued.id, new Date(Date.now() + 86_400_000))await openemail.emails.cancel(queued.id)Остановить можно только сообщения в состоянии queued и scheduled; всё, что прошло дальше, — это conflict_error, потому что часть его уже лежит у кого-то в почтовом ящике. Отмена уже отменённого сообщения удаётся и ничего не меняет.
Окно отмены вместо этого
await openemail.emails.send({ ...message, cancellableForSeconds: 30 })Запланированное сообщение и так можно отменить до его ухода, поэтому эти два нельзя сочетать, и сервер это отклоняет. Используйте это для окна отмены у немедленного сообщения.
Параметры: планирование
scheduledAtDate | string- Когда отправлять, в `emails.send`: `Date`, момент в ISO-8601 или длительность вроде `PT1H` или `P2D`, которую клиент приводит к строке для провода. Не меньше секунды в будущем и не дальше 365 дней, причём любая граница — это `validation_error` на `scheduledAt`; естественный язык не принимается, потому что неверно разобранное «в следующий вторник» отправит сообщение в момент, который уже не отозвать.
cancellableForSecondsnumber- Окно отмены у НЕМЕДЛЕННОЙ отправки: целое от 0 до 900, по умолчанию 0. Любое значение выше 0 отклоняется вместе с `scheduledAt`, которое и так отменяемо до ухода, а удержанное так сообщение стоит в `queued`, а не в `scheduled`. Это тот же механизм отсрочки с короткой задержкой.
idstringобязательно- Идентификатор `msg_…`, первый аргумент и у `emails.cancel`, и у `emails.reschedule`. Обоим нужна `emails:send`, а не собственная область доступа, и оба разрешаются внутри рабочего пространства самого ключа, так что идентификатор из чужого — это `not_found_error`, ровно как идентификатор, которого никогда не было.
reschedule.scheduledAtDate | stringобязательно- Новое время, второй аргумент `emails.reschedule`, разбираемое по тем же правилам и в том же годовом окне, и единственное, что изменит лежащий в основе `PATCH /emails/{id}`. Длительность отсчитывается от момента, когда её читает СЕРВЕР, так что повторённый перенос приземляется чуть позже, чем приземлился бы первый: позже, но никогда не раньше.
Ответ: EmailResource
object'email'- Всегда `email`. Оба вызова отвечают целым сообщением, а не подтверждением, так что ничего не нужно запрашивать заново, чтобы увидеть, что изменилось; `emails.send` возвращает ту же форму плюс `replayed`.
idstring- Ручка `msg_…`. Стабильна всё время жизни сообщения и принимается каждым другим вызовом по нему.
statusEmailStatus- `cancelled` после отмены и `scheduled` после переноса, в том числе для сообщения, которое было лишь `queued` за окном отмены, — перенос превращает его в настоящее расписание. Перенести или остановить можно только сообщения в состоянии `queued` и `scheduled`; всё, что прошло дальше, — это `conflict_error` с кодом `email_not_cancellable`, потому что часть его уже лежит у кого-то в почтовом ящике.
scheduledAtstring | null- Момент в ISO, когда сообщение должно быть отправлено. Задаётся и для окна отмены, и для отправки с `scheduledAt`, поскольку это один механизм, и null у обычной немедленной отправки.
cancellableUntilstring | null- Когда отмена перестаёт работать, — тот же момент, что и `scheduledAt`, на обоих отложенных путях. Null у немедленной отправки, которая к моменту возврата из вызова уже ушла.
sentAtstring | null- Когда сообщение действительно ушло. Null, пока оно ждёт, и навсегда null у отменённого.
messageIdstring | null- Message-ID по RFC 5322, null до появления MIME, а значит всегда null у сообщения, с которым эти два вызова могут что-то сделать. Не то, чем следует обращаться к API, и не то, с чем вернётся позднейший отбой: сервис отправки переписывает заголовок на выходе.
threadIdstring | null- Цепочка, которой принадлежит сообщение, взятая из запроса и переписанная тем, что сообщит транспорт после отправки. Null, когда это не ответ.
transportEmailTransport | (string & {}) | null- Как ушли байты, и null до отправки, а значит null у каждого сообщения, которое может вернуть отмена или перенос. Отправка в тестовом режиме записывает `test`, а объединение остаётся открытым, чтобы транспорт, которого этот SDK ещё не называет, не был ломающим изменением.
attemptsnumber- Сколько раз отправка забирала эту строку. Увеличивается при захвате, а не при успешной отправке, и равно 0 для всего, что ещё ждёт.
lastErrorstring | null- Последний сбой, записанный для сообщения, null, пока ничего не падало. Отложенная отправка, задание для которой не удалось поставить в очередь, записывается здесь как `Could not schedule: …` и переводится в `failed`, и это единственный способ, которым запланированное сообщение перестаёт быть отменяемым без чьей-либо просьбы.
fromstring- Адрес, под которым сообщение было авторизовано уйти, хранимый голым и в нижнем регистре. Не всегда тот, который запрашивали (суженный ключ, не называющий `from`, разрешается в первый доступный ему адрес), и любое отображаемое имя здесь отбрасывается, потому что фильтр `from` у `emails.list` сравнивает на равенство.