Ir a la documentación
PHP

Programar y cancelar

`scheduledAt`, `emails->reschedule`, `emails->update` y `emails->cancel`.

Enviar más tarde

schedule.php
$message = [    'from' => '[email protected]',    'to' => '[email protected]',    'subject' => 'Your September invoice',    'text' => 'Invoice attached.',]; $client->emails->send([...$message, 'scheduledAt' => 'PT1H']);$client->emails->send([...$message, 'scheduledAt' => new \DateTimeImmutable('2027-01-01 09:00', new \DateTimeZone('UTC'))]);$client->emails->send([...$message, 'scheduledAt' => '2027-01-01T09:00:00.000Z']);

Un DateTimeInterface, un instante ISO 8601 como cadena, o una duración como PT1H o P2D. Hasta un año en el futuro, nunca en el pasado. Expandir un mensaje que construiste antes en un array nuevo con scheduledAt al lado añade el campo y deja el original intacto.

Un DateTimeInterface se envía como un instante en UTC sea cual sea la zona en que se creó, así que las 09:00 en Europe/London salen como el instante que indican. Una cadena de fecha sin hora, como 2027-01-01, se lee como medianoche UTC de ese día, así que pasa un instante cuando la hora importe.

Mover y detener

reschedule.php
$message = [    'from' => '[email protected]',    'to' => '[email protected]',    'subject' => 'Your September invoice',    'text' => 'Invoice attached.',]; $queued = $client->emails->send([...$message, 'scheduledAt' => 'PT1H']); $client->emails->reschedule($queued['id'], new \DateTimeImmutable('+1 day'));$client->emails->cancel($queued['id']);

Solo se pueden detener los mensajes en queued y scheduled. Cualquier cosa más avanzada lanza una ConflictException, porque parte del mensaje ya está en el buzón de alguien. Cancelar un mensaje ya cancelado tiene éxito y no cambia nada.

Para encontrar lo que espera para salir en una ventana de tiempo, lista con status: ['scheduled', 'queued'] y scheduledFrom: y scheduledTo:, como hace el calendario de la app.

Cambiarlo antes de que salga

emails->update cambia un mensaje que aún no ha salido: cuándo sale con scheduledAt, qué dice con subject, html y text, la dirección desde la que sale con from, y a quién va con to, cc y bcc. Envía los que quieras a la vez, y un campo que omitas conserva su valor. Una lista de destinatarios sustituye entera a la almacenada. Es lo que hace editar un mensaje programado en el calendario de la app.

update.php
$updated = $client->emails->update('msg_3f9a1c07d2b84e6a9c5b1f20', [    'subject' => 'Your September invoice, corrected',    'to' => ['[email protected]', '[email protected]'],    'scheduledAt' => new \DateTimeImmutable('2026-10-05 08:00', new \DateTimeZone('UTC')),]); echo $updated['status'], ' ', $updated['subject'], ' ', $updated['scheduledAt'], PHP_EOL;

from se comprueba igual que en un envío, así que tiene que ser una dirección con la que la clave pueda enviar. Un mensaje que se tradujo al aceptarse conserva su redacción aprobada, así que un subject, html o text nuevo en él es un 409 translation_locked, y uno que se cifró antes de programarse conserva su redacción y sus destinatarios. En esos casos, cancela y vuelve a enviar.

Una ventana de deshacer en su lugar

undo_window.php
$message = [    'from' => '[email protected]',    'to' => '[email protected]',    'subject' => 'Your September invoice',    'text' => 'Invoice attached.',]; $held = $client->emails->send([...$message, 'cancellableForSeconds' => 30]); echo $held['status'], ' ', $held['cancellableUntil'], PHP_EOL;

Un mensaje programado ya se puede cancelar hasta que sale, así que no se pueden combinar ambos y el servidor lo rechaza. Usa este para una ventana de deshacer el envío en un mensaje inmediato.

Parámetros: programación

scheduledAtDateTimeInterface or string
Cuándo enviar, en `emails->send`: un `DateTimeInterface`, un instante ISO 8601 como cadena, o una duración como `PT1H` o `P2D`. Un `DateTimeInterface` se envía como instante UTC y una cadena tal cual, y una cadena de fecha sin hora significa medianoche UTC. Al menos un segundo en el futuro y como máximo 365 días por delante, y superar cualquiera de los dos límites es un `validation_error` en `scheduledAt`. No se acepta lenguaje natural, porque interpretar mal «el próximo martes» envía un mensaje a una hora que ya no se puede deshacer.
cancellableForSecondsint
Una ventana de deshacer el envío en un envío INMEDIATO: un int de 0 a 900, con 0 por defecto. Cualquier valor superior a 0 se rechaza junto con `scheduledAt`, que ya se puede cancelar hasta que sale, y un mensaje retenido de este modo queda en `queued` y no en `scheduled`. Es el mismo mecanismo de aplazamiento con un retraso corto.
$idstringobligatorio
El id `msg_`, y el primer argumento de `emails->cancel`, `emails->reschedule` y `emails->update`. Necesitan `emails:send` en lugar de un ámbito propio, y buscan el id dentro del espacio de trabajo de la propia clave, así que un id que pertenece a otro es un `not_found_error` exactamente igual que un id que nunca existió.
$scheduledAtDateTimeInterface or stringobligatorio
La nueva hora, como segundo argumento de `emails->reschedule`, leída con las mismas reglas y contra la misma ventana de un año. Es lo único que cambia `reschedule`, y el cliente no envía nada más. Una duración es relativa al momento en que la lee el SERVIDOR, así que una reprogramación reintentada cae algo más tarde de lo que habría caído la primera: más tarde, nunca antes.
apiKeystring
Un argumento nombrado en cualquiera de las tres llamadas. Actúa con esta clave en lugar de la del cliente.

Respuesta

cancel, reschedule y update devuelven cada uno el mensaje completo como un array cuyas claves son los nombres camelCase de la API.

objectstring
Siempre `email`. Estas llamadas responden con el mensaje completo en lugar de con un acuse de recibo, así que no hay que volver a pedir nada para ver qué cambió. `emails->send` devuelve esta misma forma más `replayed`.
idstring
El identificador `msg_`. Estable durante toda la vida del mensaje y el id que aceptan todas las demás llamadas sobre él.
statusstring
`cancelled` tras una cancelación y `scheduled` tras una reprogramación, incluso para un mensaje que solo estaba en `queued` detrás de una ventana de deshacer, que una reprogramación convierte en una programación real. Solo se pueden mover o detener los mensajes en `queued` y `scheduled`. Cualquier cosa más avanzada lanza una `ConflictException` cuyo `errorCode` es `email_not_cancellable`, porque parte del mensaje ya está en el buzón de alguien.
scheduledAtstring or null
El instante ISO 8601 en que está previsto despachar el mensaje. Se establece tanto para una ventana de deshacer como para un envío con `scheduledAt`, ya que ambos son un mismo mecanismo, y es null en un envío inmediato normal.
cancellableUntilstring or null
Cuándo deja de funcionar la cancelación, que es el mismo instante que `scheduledAt` en ambas rutas aplazadas. null en un envío inmediato, que ya ha salido cuando la llamada retorna.
sentAtstring or null
Cuándo salió realmente el mensaje. null mientras espera, y null para siempre en uno cancelado.
messageIdstring or null
El Message-ID de RFC 5322, null hasta que existe el MIME, así que siempre null en un mensaje sobre el que pueden actuar estas llamadas. No es algo con lo que dirigirse a la API, ni tampoco aquello con lo que vuelve un rebote posterior: el servicio de envío reescribe la cabecera a la salida.
threadIdstring or null
El hilo al que pertenece este mensaje, tomado de la solicitud y reescrito con lo que informe el transporte una vez enviado. null cuando no es una respuesta.
transportstring or null
Cómo salieron los bytes, y null hasta el despacho, así que null en todos los mensajes que pueden devolver una cancelación o una reprogramación. Un envío en modo de prueba registra `test`, y puede aparecer un transporte que este paquete aún no nombra, así que trata un valor desconocido como información y no como un error.
attemptsint
Cuántas veces el despacho ha reclamado esta fila. Aumenta con cada reclamación y no con un envío correcto, y es 0 para todo lo que sigue esperando.
lastErrorstring or null
El último fallo registrado contra el mensaje, null mientras no haya fallado nada. Un envío aplazado cuyo trabajo no se pudo encolar se escribe aquí como `Could not schedule: …` y pasa a `failed`, que es la única forma en que un mensaje programado deja de poder cancelarse sin que nadie lo pida.
fromstring
La dirección con la que se autorizó que saliera el mensaje: el `from` que se envió, almacenado escueto y en minúsculas. Aquí se descarta cualquier nombre visible, porque el filtro `from:` de `emails->list` compara por igualdad.