Skip to the documentation
Python

Schedule and cancel

`scheduledAt`, `emails.reschedule` and `emails.cancel`.

Sending later

schedule.py
from datetime import datetime, timezone from openemail import openemailfrom openemail.types import EmailSend message: EmailSend = {'from': sender, 'to': recipient, 'subject': subject, 'text': text} openemail.emails.send({**message, 'scheduledAt': 'PT1H'})openemail.emails.send({**message, 'scheduledAt': datetime(2027, 1, 1, 9, 0, tzinfo=timezone.utc)})openemail.emails.send({**message, 'scheduledAt': '2027-01-01T09:00:00.000Z'})

A datetime, an ISO-8601 instant, or a duration like PT1H / P2D. Up to a year out, never in the past.

A datetime is sent in UTC, and a naive one is read as this machine’s local time first, the way astimezone reads it, so pass an aware one when the zone matters. A timedelta is not accepted: add it to datetime.now(timezone.utc), or send a duration such as PT1H.

Moving and stopping

reschedule.py
from datetime import datetime, timedelta, timezone from openemail import openemailfrom openemail.types import EmailSend message: EmailSend = {'from': sender, 'to': recipient, 'subject': subject, 'text': text} queued = openemail.emails.send({**message, 'scheduledAt': 'PT1H'}) openemail.emails.reschedule(queued['id'], datetime.now(timezone.utc) + timedelta(days=1))openemail.emails.cancel(queued['id'])

Only queued and scheduled messages can be stopped; anything further on is a conflict_error, because some of it is already in somebody's mailbox. Cancelling an already-cancelled message succeeds and changes nothing.

An undo window instead

undo_window.py
from openemail import openemailfrom openemail.types import EmailSend message: EmailSend = {'from': sender, 'to': recipient, 'subject': subject, 'text': text} openemail.emails.send({**message, 'cancellableForSeconds': 30})

A scheduled message is already cancellable until it goes, so the two cannot be combined, and the server refuses it. Use this one for an undo-send window on an immediate message.

Parameters: scheduling

scheduledAtdatetime | str
When to send, on `emails.send`: a `datetime`, an ISO-8601 instant, or a duration like `PT1H` or `P2D`, which the client renders to a string for the wire. At least one second in the future and at most 365 days out, with either bound a `validation_error` on `scheduledAt`, and natural language is not accepted, because parsing "next Tuesday" wrongly sends a message at a time that cannot be taken back.
cancellableForSecondsint
An undo-send window on an IMMEDIATE send: an integer from 0 to 900, defaulting to 0. Any value above 0 is refused alongside `scheduledAt`, which is already cancellable until it goes, and a message held this way sits at `queued` rather than `scheduled`. It is the same deferral mechanism with a short delay.
idstrrequired
The `msg_…` id, and the first argument to both `emails.cancel` and `emails.reschedule`. Both need `emails:send` rather than a scope of their own, and both resolve within the key's own workspace, so an id belonging to another one is a `not_found_error` exactly like an id that never existed.
scheduled_atdatetime | strrequired
The new time, as the second argument to `emails.reschedule`, parsed by the same rules and against the same one-year window, and the only thing the underlying `PATCH /emails/{id}` will change. A duration is relative to when the SERVER reads it, so a retried reschedule lands slightly later than the first would have: later, never earlier.

Response: EmailResource

objectLiteral['email']
Always `email`. Both calls answer with the whole message rather than an acknowledgement, so nothing has to be re-fetched to see what changed; `emails.send` returns this same shape plus `replayed`.
idstr
The `msg_…` handle. Stable for the life of the message and the id every other call on it takes.
statusEmailStatus
`cancelled` after a cancel and `scheduled` after a reschedule, including for a message that was only `queued` behind an undo window, which a reschedule turns into a real schedule. Only `queued` and `scheduled` messages can be moved or stopped; anything further on is a `conflict_error` with code `email_not_cancellable`, because some of it is already in somebody's mailbox.
scheduledAtstr | None
The ISO instant the message is due to be dispatched. Set for an undo window as well as for a `scheduledAt` send, since the two are one mechanism, and null on a plain immediate send.
cancellableUntilstr | None
When cancelling stops working, which is the same instant as `scheduledAt` on both deferred paths. Null on an immediate send, which has already gone by the time the call returns.
sentAtstr | None
When the message actually left. Null while it waits, and null for ever on a cancelled one.
messageIdstr | None
The RFC 5322 Message-ID, null until the MIME exists, so always null on a message these two calls can act on. Not something to address the API with, and not what a later bounce comes back on either: the sending service rewrites the header on the way out.
threadIdstr | None
The thread this message belongs to, taken from the request and rewritten with whatever the transport reports once it sends. Null when it is not a reply.
transportEmailTransport | str | None
How the bytes left, and null until dispatch, so null on every message a cancel or a reschedule can return. A test-mode send records `test`, and the union stays open so a transport this SDK does not yet name is not a breaking change.
attemptsint
How many times dispatch has claimed this row. It is incremented by the claim rather than by a successful send, and is 0 for anything still waiting.
lastErrorstr | None
The last failure recorded against the message, null while nothing has failed. A deferred send whose job could not be enqueued is written here as `Could not schedule: …` and moved to `failed`, which is the one way a scheduled message stops being cancellable without anybody asking.
fromstr
The address the message was authorised to go out as: the `from` that was sent, stored bare and lower-cased. Any display name is dropped here, because `emails.list`'s `from_` filter compares on equality.

Reference