Programar y cancelar
`scheduledAt`, `emails->reschedule`, `emails->update` y `emails->cancel`.
Enviar más tarde
$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
$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.
$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
$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.