Aller à la documentation
Ruby

Planifier et annuler

`scheduledAt`, `emails.reschedule`, `emails.update` et `emails.cancel`.

Envoyer plus tard

schedule.rb
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: Time.utc(2027, 1, 1, 9))client.emails.send(message, scheduledAt: "2027-01-01T09:00:00.000Z")

Un Time ou un DateTime, un instant ISO 8601 sous forme de String, ou une durée comme PT1H ou P2D. Jusqu'à un an à l'avance, jamais dans le passé. Un argument nommé à côté du Hash ajoute le champ à un message construit plus tôt.

Une Date Ruby est envoyée comme une date nue telle que 2027-01-01, que l'API lit comme minuit UTC ce jour-là. Passez un Time, comme Time.utc(2027, 1, 1, 9), quand l'heure compte.

Déplacer et arrêter

reschedule.rb
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], Time.now + 86_400)client.emails.cancel(queued[:id])

Seuls les messages queued et scheduled peuvent être arrêtés. Tout ce qui est plus avancé lève une OpenEmail::ConflictError, car une partie est déjà dans la boîte de quelqu'un. Annuler un message déjà annulé réussit et ne change rien.

Pour trouver ce qui attend de partir dans une fenêtre de temps, listez avec status: ["scheduled", "queued"] ainsi que scheduled_from: et scheduled_to:, comme le fait le calendrier de l'application.

Le modifier avant son départ

emails.update modifie un message qui n'est pas encore parti : quand il part, avec scheduledAt, ce qu'il dit, avec subject, html et text, l'adresse depuis laquelle il part, avec from, et à qui il est envoyé, avec to, cc et bcc. Envoyez-en autant que vous voulez ensemble, et un champ omis garde sa valeur. Une liste de destinataires remplace entièrement celle qui est stockée. C'est ce que fait la modification d'un message planifié dans le calendrier de l'application.

update.rb
updated = client.emails.update(  "msg_3f9a1c07d2b84e6a9c5b1f20",  subject: "Your September invoice, corrected",  to: ["[email protected]", "[email protected]"],  scheduledAt: Time.utc(2026, 10, 5, 8)) puts updated[:status], updated[:subject], updated[:scheduledAt]

from est vérifié comme lors d'un envoi : ce doit donc être une adresse depuis laquelle la clé peut envoyer. Un message traduit au moment de son acceptation garde sa formulation approuvée : un nouveau subject, html ou text sur lui donne donc un 409 translation_locked, et un message chiffré avant d'être planifié garde sa formulation et ses destinataires. Annulez-les et envoyez à nouveau à la place.

Une fenêtre d'annulation à la place

undo_window.rb
message = {from: "[email protected]", to: "[email protected]", subject: "Your September invoice", text: "Invoice attached."} held = client.emails.send(message, cancellableForSeconds: 30) puts held[:status], held[:cancellableUntil]

Un message planifié est déjà annulable jusqu'à son départ : les deux ne peuvent donc pas être combinés, et le serveur le refuse. Utilisez celui-ci pour une fenêtre d'annulation sur un message immédiat.

Paramètres : planification

scheduledAtTime, DateTime or String
Quand envoyer, sur `emails.send` : un Time ou un DateTime, un instant ISO 8601 sous forme de String, ou une durée comme `PT1H` ou `P2D`. Un Time ou un DateTime est envoyé comme un instant UTC, une String telle quelle, et une Date Ruby comme une date nue qui signifie minuit UTC. Au moins une seconde dans le futur et au plus 365 jours à l'avance, chacune des deux bornes donnant une `validation_error` sur `scheduledAt`, et le langage naturel n'est pas accepté, car interpréter « mardi prochain » de travers envoie un message à une heure sur laquelle on ne peut pas revenir.
cancellableForSecondsInteger
Une fenêtre d'annulation sur un envoi IMMÉDIAT : un Integer de 0 à 900, 0 par défaut. Toute valeur supérieure à 0 est refusée en présence de `scheduledAt`, qui est déjà annulable jusqu'à son départ, et un message retenu ainsi reste à `queued` plutôt qu'à `scheduled`. C'est le même mécanisme de report, avec un court délai.
idStringobligatoire
L'id `msg_`, et le premier argument d'`emails.cancel`, d'`emails.reschedule` et d'`emails.update`. Ils exigent `emails:send` plutôt qu'une portée qui leur serait propre, et cherchent l'id à l'intérieur de l'espace de travail de la clé : un id appartenant à un autre espace de travail donne donc une `not_found_error`, exactement comme un id qui n'a jamais existé.
scheduled_atTime, DateTime or Stringobligatoire
La nouvelle heure, en deuxième argument d'`emails.reschedule`, lue selon les mêmes règles et dans la même fenêtre d'un an. C'est la seule chose que `reschedule` modifie, et le client n'envoie rien d'autre. Une durée est relative au moment où le SERVEUR la lit : une replanification réessayée tombe donc un peu plus tard que la première ne l'aurait fait. Plus tard, jamais plus tôt.
api_keyString
Agit avec cette clé au lieu de celle du client, sur chacun des trois appels.

Réponse

cancel, reschedule et update renvoient chacun le message entier sous forme de Hash à clés Symbol.

objectString
Toujours `email`. Ces appels répondent avec le message entier plutôt qu'avec un accusé de réception : rien n'a donc besoin d'être récupéré à nouveau pour voir ce qui a changé. `emails.send` renvoie cette même forme, plus `replayed`.
idString
Le handle `msg_`. Stable pendant toute la vie du message, et c'est l'id que prend tout autre appel le concernant.
statusString
`cancelled` après une annulation et `scheduled` après une replanification, y compris pour un message qui n'était que `queued` derrière une fenêtre d'annulation, qu'une replanification transforme en véritable planification. Seuls les messages `queued` et `scheduled` peuvent être déplacés ou arrêtés. Tout ce qui est plus avancé donne une `conflict_error` avec le code `email_not_cancellable`, car une partie est déjà dans la boîte de quelqu'un.
scheduledAtString or nil
L'instant ISO 8601 auquel le message doit être expédié. Renseigné aussi bien pour une fenêtre d'annulation que pour un envoi avec `scheduledAt`, puisque les deux ne font qu'un seul mécanisme, et nil sur un simple envoi immédiat.
cancellableUntilString or nil
Le moment où l'annulation cesse de fonctionner, soit le même instant que `scheduledAt` sur les deux chemins différés. nil sur un envoi immédiat, déjà parti au moment où l'appel revient.
sentAtString or nil
Quand le message est réellement parti. nil tant qu'il attend, et nil pour toujours sur un message annulé.
messageIdString or nil
Le Message-ID RFC 5322, nil tant que le MIME n'existe pas, donc toujours nil sur un message sur lequel ces appels peuvent agir. Ce n'est pas avec lui qu'on s'adresse à l'API, ni sur lui qu'un bounce ultérieur revient : le service d'envoi réécrit l'en-tête au départ.
threadIdString or nil
Le thread auquel ce message appartient, repris de la requête et réécrit avec ce que rapporte le transport une fois l'envoi fait. nil quand ce n'est pas une réponse.
transportString or nil
Par où les octets sont partis, et nil jusqu'à l'expédition, donc nil sur tout message qu'une annulation ou une replanification peut renvoyer. Un envoi en mode test enregistre `test`, et un transport que cette gem ne nomme pas encore peut apparaître : traitez donc une valeur inconnue comme une information plutôt que comme une erreur.
attemptsInteger
Combien de fois l'expédition a réclamé cette ligne. Le compteur augmente à chaque réclamation et non à chaque envoi réussi, et vaut 0 pour tout ce qui attend encore.
lastErrorString or nil
Le dernier échec enregistré sur le message, nil tant que rien n'a échoué. Un envoi différé dont le job n'a pas pu être mis en file est écrit ici sous la forme `Could not schedule: …` et passe à `failed`, seule manière pour un message planifié de cesser d'être annulable sans que personne ne l'ait demandé.
fromString
L'adresse sous laquelle le message a été autorisé à partir : le `from` envoyé, stocké nu et en minuscules. Tout nom d'affichage est abandonné ici, car le filtre `from:` d'`emails.list` compare sur l'égalité.