Journal des versions

Ce qui a été livré, et ce que ça change

Chaque changement visible par la clientèle, dans l’ordre où il est arrivé. Quand un changement modifie un comportement sur lequel vous comptiez, c’est dit — et quand il ne change rien pour les clés existantes, c’est dit aussi, parce que c’est habituellement la première question.

29 entrées  ·  juillet–octobre 2026  ·  mise à jour 2026-10-30

Novembre 2026

Une référence de l’API, sur zedmail.com/docs

Il n’y en avait aucune jusqu’ici, et la raison honnête était qu’un document décrivant une API finit par s’écarter de l’API au point qu’on ne sait plus laquelle des deux moitiés est fausse. Celle qui est maintenant publiée couvre chaque point d’accès /v1 avec la portée qu’il exige, l’enveloppe d’erreur et tous ses codes, l’idempotence, les limites publiées, la requête d’envoi champ par champ et le sens de chaque état de message — en français et en anglais.

Elle est vérifiée contre le routeur à chaque déploiement, dans les deux sens : un point d’accès qui existe sans entrée fait échouer la construction, et une entrée pour un point d’accès retiré aussi. C’est le second cas qui vous concerne, parce qu’un point d’accès documenté qui répond 404 vous fait d’abord soupçonner votre propre requête.

Les charges utiles des webhooks, la vérification de signature et le calendrier des reprises restent sur la page Webhooks de votre compte, où les exemples peuvent nommer vos propres points de terminaison.

L’exemple de vérification des webhooks nommait un champ inexistant

L’exemple de vérification de signature de votre page Compte vous disait de lire $event['type']. Il n’existe aucun champ type — c’est event. Quiconque a copié cet exemple obtenait null et devait en chercher la raison, à cause de notre documentation plutôt que grâce à elle. C’est corrigé, et la correction a été vérifiée contre de vraies livraisons de production, non contre l’exemple lui-même.

Deux autres choses qu’il taisait. La liste des événements omettait blocked, opened et clicked. Et unsubscribed n’a pas la même forme que les autres : message_id vaut null, il n’y a pas de champ email au premier niveau, et l’adresse se trouve dans data.email — un traitement écrit d’après l’ancien exemple lisait donc une adresse vide précisément sur l’événement qu’il ne faut jamais manquer.

L’exemple montre aussi maintenant quoi faire contre le rejeu, ce qui est la paire de champs sur laquelle on nous interroge. L’en-tête de signature porte t=, l’heure Unix de la signature, et elle est comprise dans la chaîne signée — rejetez donc tout ce dont le t remonte à plus de quelques minutes; l’exemple utilise 300 secondes. Dédoublonnez ensuite sur id, l’uuid de la livraison, identique à chaque nouvelle tentative. Ensemble, ces deux champs rendent une livraison rejouée indiscernable d’une reprise de celle-ci, et une reprise déjà traitée ne fait rien.

Octobre 2026

Les livraisons de webhooks portent désormais un identifiant stable pour le dédoublonnage

Chaque livraison de webhook porte désormais son propre identifiant : id dans le corps JSON, repris dans un en-tête X-SES-Delivery-Id. C’est un UUID, et il est le même à chaque nouvelle tentative de cette livraison — vous pouvez donc le conserver et ignorer sans risque ce que vous avez déjà traité.

Les nouvelles tentatives réexpédiaient déjà le corps à l’octet près, ce qui rendait le corps lui-même utilisable comme clé de dédoublonnage, mais rien dans la charge utile ne le disait. Il y a maintenant un champ pour cela. Lisez-le dans le corps plutôt que dans l’en-tête lorsque cela compte : la signature couvre le corps, et l’en-tête se trouve en dehors.

Le calendrier des nouvelles tentatives est aussi documenté sur la page Webhooks : jusqu’à sept tentatives — immédiatement, puis après 1 minute, 5 minutes, 30 minutes, 2 heures, 8 heures et 24 heures. Toute réponse 2xx y met fin. Rien d’autre dans la charge utile ne change.

Le courrier transactionnel n’annonce plus le désabonnement en un clic

Une clé transactionnelle n’ajoutait déjà aucun pied de page de désabonnement. Elle envoyait pourtant les en-têtes List-Unsubscribe, ceux qui affichent le bouton de désabonnement natif de Gmail et d’Apple Mail — et ce bouton ne demande aucune confirmation. Un destinataire qui l’utilisait sur un reçu se trouvait désabonné de tous vos reçus, sans que rien à l’écran ne le lui dise. Ces en-têtes ne sont plus envoyés sur le flux transactionnel. La diffusion et les clés plus anciennes sans flux ne changent pas.

Si vous voulez ce bouton sur le courrier transactionnel, activez le désabonnement par clé sur cette clé : les en-têtes reviennent et un désabonnement ne touche que le courrier de cette clé. La balise {{unsubscribe_url}} n’a jamais été concernée et fonctionne toujours sur les deux flux — elle mène à une page qui annonce ce qu’elle fera avant de le faire.

Chaque message porte désormais aussi un en-tête List-Help (RFC 2369) qui mène à une page destinée à vos destinataires : qui a envoyé le message, pourquoi vous seul pouvez dire comment leur adresse vous est parvenue, comment faire cesser l’envoi sur ce flux, et comment signaler un courriel auquel ils n’ont jamais consenti. Elle nomme votre domaine d’envoi et rien du destinataire — aucune adresse, aucun jeton, aucun identifiant de message.

Vos propres en-têtes, sur le message et de retour sur le webhook

Envoyez jusqu’à dix en-têtes de votre choix avec un message — un identifiant de sondage, un numéro de facture, une référence de dossier — et ils voyagent sur le message puis vous reviennent sur chacun de ses événements de webhook. Les noms sont vérifiés contre une liste réservée publiée, et tout ce qui écraserait l’un des nôtres, ou porterait un saut de ligne, fait échouer l’envoi avec un 422 qui nomme l’en-tête plutôt que d’être retiré en silence. Si rien, à la réception, n’a besoin de lire la valeur, tags fait toujours le même travail et la garde privée.

Les en-têtes de désabonnement en un clic sont maintenant signés

List-Unsubscribe et List-Unsubscribe-Post sont désormais à l’intérieur de la signature DKIM sur les deux chemins d’envoi, et non simplement présents sur le message. La RFC 8058 le demande, et un destinataire qui vérifie les verra couverts par la liste h=. Rien ne change de votre côté, et rien de ce qui est déjà parti n’a été touché.

Une FAQ publique, dans les deux langues

Une FAQ publique à /faq, répondue en français et en anglais : ce que nous conservons et ce que nous ne conservons pas, où vivent les données, ce qui arrive à un compte suspendu, comment fonctionne la suppression, et quel flux convient à une clé. Écrite à partir de questions que des clients ont réellement posées, ce qui explique que certaines réponses soient moins flatteuses qu’une page de vente ne le permettrait. Elle s’enrichit à mesure que les questions arrivent plutôt que d’être terminée.

Les nouvelles clés peuvent diagnostiquer, pas seulement envoyer

Une nouvelle clé d’API est créée avec le profil Envoi et diagnostic : elle peut envoyer, et elle peut relire ce qui s’est passé — état de livraison, rejets, suppressions, quel enregistrement DNS manque à un domaine. Elle ne peut toujours pas supprimer une adresse, créer un point de terminaison webhook, ajouter un domaine d’envoi ni toucher à votre équipe. Les clés existantes conservent la portée avec laquelle elles ont été créées ; faites la rotation d’une clé pour adopter le nouveau profil par défaut.

Des reprises qui ne peuvent pas envoyer deux fois

Fournissez votre propre idempotency_key à l’envoi et une reprise cesse d’être un risque. Une reprise identique dans les 24 heures renvoie la première réponse, avec un code HTTP 200 et un en-tête Idempotent-Replay: true, et aucun deuxième message ne part. Une reprise pendant que le premier envoi est encore en cours répond 409 ; la même clé accompagnée d’un message différent est refusée avec un 422 plutôt que de vous rendre discrètement l’identifiant du premier message. Un envoi que nous refusons libère sa clé : une adresse fautive se corrige et se reprend avec la même clé. Sans clé, rien ne change.

Un point de terminaison webhook par clé d’API

Un point de terminaison peut être lié à une seule clé : les événements de votre environnement d’essai atteignent votre récepteur d’essai, et la production atteint la production. Laissez-le sur Toutes les clés et il se comporte comme avant — tous les points de terminaison qui existaient déjà ne sont liés à aucune clé. Chaque événement que nous pouvons attribuer à une clé transporte maintenant aussi api_key_id, pour qu’un point de terminaison partagé puisse plutôt s’en servir pour router.

Sept outils de plus pour les assistants IA

Le serveur MCP de Zedmail a gagné les outils de diagnostic : vérifier le DNS d’un domaine, savoir pourquoi une adresse ne reçoit pas, lire les taux de rejet et de plainte, lister et tester les points de terminaison webhook. Un assistant peut maintenant répondre à « pourquoi ce message a-t-il été rejeté ? » sans que personne ouvre un billet. Une clé ne voit jamais que les outils que ses propres portées autorisent.

90 jours de préavis si nous devions fermer

L’article 7 des conditions engage maintenant un préavis écrit d’au moins 90 jours, le service fonctionnant normalement pendant toute cette période, rien de facturé après la date d’arrêt, le crédit prépayé non utilisé remboursé, et vos données d’envoi, vos journaux de livraison et vos listes de suppression exportables tout du long. Un client municipal l’a demandé par écrit : une demande légitime, et quelque chose que nous aurions dû énoncer plus tôt.

Un désabonnement peut se limiter à une seule clé

Quelqu’un qui refuse votre infolettre ne devrait pas du même coup refuser ses propres réinitialisations de mot de passe. Sur une clé transactionnelle, le désabonnement peut être restreint à cette clé seule plutôt qu’à tout le compte. Les plaintes pour pourriel et les rejets définitifs restent à l’échelle du compte, délibérément : une plainte est une déclaration à votre sujet et à celui de ce destinataire, et une boîte morte est morte pour toutes vos clés.

Vous l’apprenez de nous, pas d’une erreur 401

Si l’envoi est jamais suspendu sur votre compte — un taux de rejet ou de plainte au-delà du seuil, par exemple — vous recevez immédiatement un courriel qui en donne la raison. Jusqu’ici, le seul avis qu’un compte recevait était l’échec de son prochain appel d’API.

Un vérificateur d’authentification public

/email-check lit le SPF, le DKIM et le DMARC de n’importe quel domaine comme le fait un serveur destinataire, et dit ce qui ne va pas. Gratuit, sans compte, et ça fonctionne pour des domaines qui n’ont rien à voir avec nous.

Listes de suppression hachées au repos

La liste de suppression commune à tout le service est stockée hachée plutôt qu’en clair. Une entrée commune persiste aussi longtemps qu’un compte supprime encore l’adresse, selon un délai de trois ans, et les conservations exigées par la loi sont permanentes.

Une entente de traitement des données publiée

Rédigée avec un conseiller juridique et publiée à /dpa.php plutôt que fournie sur demande. Elle fait partie des conditions et est acceptée avec elles ; nous en signerons un exemplaire si votre processus en exige un au dossier.

Septembre – début octobre 2026

Pièces jointes

Jusqu’à dix fichiers et 10 Mo par message. Nous ne les gardons pas : les octets sont supprimés au moment où le message nous quitte, et seuls le nom de fichier, le type et la taille restent au dossier.

Choisissez votre conservation, de 7 à 365 jours

Réglée par flux, pour que vos journaux transactionnels et vos journaux de campagne n’aient pas à suivre le même calendrier. À l’échéance, tout l’enregistrement part ensemble : destinataire, objet, corps et état de livraison. Sept jours est le plancher.

Flux transactionnel et flux de diffusion

Chaque clé d’API que vous créez est maintenant l’un ou l’autre, et ce choix change le comportement plutôt que de le nommer. Le transactionnel n’ajoute aucun pied de page de désabonnement — personne ne devrait pouvoir se désabonner de sa propre réinitialisation de mot de passe. La diffusion en ajoute toujours un, dans la langue du destinataire. Les deux gardent aussi leur réputation séparée : une campagne qui connaît une mauvaise semaine ne suit pas vos reçus jusque dans le dossier des pourriels. Les clés existantes ne changent pas.

Une deuxième et une troisième adresse d’envoi

Des blocs d’adresses IP distincts, chauffés délibérément sur des mois, pour que le problème de liste d’un expéditeur cesse d’être le problème de livraison de tout le monde. Le chauffage déplace une fraction mesurée du trafic réel plutôt que de déplacer un expéditeur, parce que les serveurs destinataires jugent une nouvelle adresse sur la forme de son volume.

Un TLS vérifié que vous pouvez exiger

Par clé, vous pouvez exiger qu’un message soit chiffré vers un serveur qui prouve son identité. Si le destinataire n’en est pas capable, le message est retenu au lieu de partir en clair, et nous vous disons quels destinataires sont touchés — et ils ne sont pas désabonnés pour autant. Pour les grands fournisseurs grand public, c’est appliqué de toute façon, parce qu’ils publient des politiques disant que leurs serveurs ne devraient jamais accepter de courrier non chiffré.

Août 2026

Un effacement distinct d’une suspension

Un effacement demandé par la personne elle-même, au titre du RGPD ou de la Loi 25, est maintenant un état terminal à part entière plutôt qu’une suspension qui y ressemble : les rapports, le soutien et chaque barrière d’accès peuvent distinguer les deux.

Sauvegardes hors site chiffrées, vérifiées chaque nuit

Des sauvegardes chiffrées chaque nuit vers un stockage objet au Québec, la clé de déchiffrement étant gardée hors ligne pour qu’un serveur compromis ne puisse pas les lire. Fraîcheur, taille et somme de contrôle sont vérifiées chaque nuit, et un déchiffrement-restauration complet est testé périodiquement. Une sauvegarde que personne n’a restaurée est un espoir, pas un contrôle.

Suspendre l’envoi, sans suspendre un compte

Une retenue réversible qui ne touche que l’envoi. Un compte à l’étude arrête d’envoyer mais garde son tableau de bord, ses clés et ses données — c’est la différence entre une question et une punition.

Juillet 2026

Un guide simple du DNS

/domain-setup, écrit pour la personne à qui on a remis un accès de registraire et une liste d’enregistrements, et lié depuis le tableau de bord, là où cette personne se trouve vraiment.

Des dates dans votre fuseau horaire

Chaque horodatage du tableau de bord s’affiche dans le fuseau horaire inscrit à votre compte. Il était collecté, validé et stocké depuis des années alors que toutes les dates à l’écran étaient encore en UTC.

Le français, pour de vrai

Le tableau de bord, les pages publiques, les courriels de compte, et les pages de désabonnement et de rétroaction que voient vos destinataires. Les pages destinées aux abonnés négocient la langue avec le navigateur, parce qu’un destinataire n’a pas de compte chez nous pour porter une préférence.

Facturation dans votre monnaie

Dollars canadiens, livres, euros ou dollars américains, choisis à l’inscription, avec leurs propres prix plutôt qu’une conversion. Une facture garde la monnaie dans laquelle elle a été émise.

Les correctifs mineurs ne sont pas listés. Le travail de livrabilité non plus, la plupart du temps, parce qu’il est continu plutôt que datable — mais quand il change quelque chose d’observable, comme une adresse d’envoi ou un rejet que vous auriez vu autrement, il paraît ici.