Passer au contenu principal
Un e-mail transactionnel part vers une personne précise, à cause de ce qu’elle vient de faire. Il n’a pas besoin de liste ni de consentement marketing, et il est journalisé et suivi comme une campagne. Voir Vue d’ensemble.

Avec un modèle

Le plus propre : le contenu vit dans Lekalao, l’application n’envoie que les données. Créez un modèle nommé confirmation-commande (Modèles transactionnels), puis :
Dans le modèle :
Les variables sont échappées ; les boucles portent sur des listes de valeurs simples. Toute la syntaxe est dans Personnalisation.

Sans modèle

Envoyez le HTML tel quel :

Les champs

Chaque adresse compte dans le quota du mois, copies comprises : un e-mail à une personne en to et deux en cc compte pour trois. Un e-mail transactionnel s’écrit à quelqu’un, il ne se diffuse pas : plus de 50 adresses répondent 422 too_many_recipients.

En plusieurs langues

Un modèle peut avoir une version par langue (Langues). locale choisit : Passez la langue de votre client telle que votre application la connaît : Lekalao se rabat tout seul.

La réponse

L’appel reçoit sa réponse dès que l’e-mail est écrit. Il part d’une file d’attente un instant plus tard. Un refus est une erreur comme une autre — message, code, doc_url — avec l’e-mail journalisé sous data quand il y en a un :
429 Too Many Requests
L’e-mail lui-même :
202 Accepted
Traitez 201 et 202 de la même façon : Lekalao a l’e-mail. Gardez son id ; status dit s’il est déjà parti. Les adresses de la liste de suppression sont retirées de to, cc et bcc sans erreur. L’e-mail part aux autres, et n’échoue que s’il ne reste aucun to.

Ensuite, dans la file

Lekalao remet l’e-mail au fournisseur. Quand le fournisseur échoue (délai dépassé, erreur, refus), Lekalao réessaie après 5 secondes, puis 30 secondes, 2 minutes, 10 minutes et 30 minutes. Il abandonne après le sixième essai raté, et de toute façon six heures après l’appel. status passe alors à failed, avec failure_code: provider_error et la dernière erreur du fournisseur dans failure_reason. Un e-mail dont la tâche s’est perdue en route — un worker arrêté, une file vidée — ne reste pas pending pour toujours : sept heures après l’appel, il passe failed avec failure_code: lost. Son contenu n’a peut-être pas été gardé, il n’est donc pas renvoyé dans votre dos : renvoyez-le vous-même. Les e-mails transactionnels ont leur propre file : ils n’attendent jamais derrière une campagne. La limite de débit du fournisseur s’applique toujours.

Le suivre par les webhooks

Plutôt que de relire l’e-mail encore et encore, laissez Lekalao vous prévenir. Abonnez une adresse aux événements transactional.* (Webhooks) : Chacun porte l’e-mail tel que l’API le montre : gardez son id avec votre commande, et faites le lien par lui. sent veut dire que le fournisseur l’a, pas qu’il est arrivé. delivered_at est rempli quand le fournisseur signale une remise, bounced_at quand l’adresse a rebondi définitivement, complained_at quand un lecteur l’a signalé comme spam ; status reste sent, et après un rebond failure_reason prend la raison du fournisseur. L’adresse part dans la liste de suppression après un rebond dur ou une plainte : le prochain e-mail vers elle ne partira pas. La même nouvelle arrive aussi par mail.bounced et mail.complaint, avec transactional_mail égal à l’id de l’e-mail.

Ou le relire

Sans adresse de webhook, relisez l’e-mail avec GET /v1/transactional-mails/{id} jusqu’à ce que status ne soit plus pending. Le jeton doit pouvoir Lecture, ce que fait un jeton Lecture et écriture.
Espacez les appels. Ils comptent dans la limite du jeton (120 appels par minute par défaut), avec tout ce que fait le jeton :

Quand l’appel lui-même échoue

Un délai dépassé ou un 5xx vous laisse sans savoir si Lekalao a l’e-mail. Renvoyez le même appel avec la même Idempotency-Key :
  • si Lekalao avait répondu la première fois, vous recevez cette première réponse, avec Idempotent-Replay: true, et aucun second e-mail ne part. C’est la réponse telle qu’elle était, pending compris : lisez l’e-mail pour savoir où il en est. Un 422 ou un 429 est gardé aussi : la même clé donne le même refus ;
  • un 502 n’est pas retenu : la même clé envoie de nouveau.
Une clé est gardée 24 heures. Voir Idempotence.

Suivre et renvoyer

Un renvoi reprend les mêmes destinataires, variables, langue, objet et adresse d’expéditeur (from_email), et le même fournisseur. Il ne reprend pas les pièces jointes, qui ne sont jamais gardées, ni un from_name ou un reply_to donnés au premier appel : ceux du modèle, ou de l’équipe, sont utilisés. Un e-mail de test renvoyé reste un e-mail de test.

Sans rien envoyer

Une clé de test n’envoie rien : l’e-mail est vérifié, rendu et journalisé, marqué sent avec "sandbox": true, et compté dans aucun quota. Écrit à delivered@sink.lekalao.dev, bounced@sink.lekalao.dev et leurs voisines, il reçoit la réponse du fournisseur et ses webhooks, pour essayer vos gestionnaires de bout en bout.

Autres chemins

  • Une application Laravel peut garder Mail::to()->send() : voir Transport Laravel.
  • Un logiciel qui ne sait parler que SMTP : voir Relais SMTP.