E-mails transactionnels

POST /smtp/email envoie un e-mail par l'infrastructure du site : relais d'envoi (SMTP ou SES) configuré dans la console, journal des envois, suivi des ouvertures et des clics.

{
  "sender": { "name": "Ma Boutique", "email": "contact@ma-boutique.fr" },
  "to": [{ "email": "client@example.com", "name": "Camille" }],
  "subject": "Votre commande {{ params.order.id }}",
  "htmlContent": "<p>Merci {{ contact.FIRSTNAME | default: \"\" }} !</p>",
  "params": { "order": { "id": "1042" } },
  "tags": ["commande"]
}

Réponse 201 : { "messageId": "<…@smtp-relay.mailin.fr>" }.

Contenu

Fournissez au choix :

  • htmlContent et/ou textContent, avec subject ;
  • ou templateId, l'identifiant d'un modèle (voir « Modèles » plus bas). Le modèle doit être actif ; son expéditeur, son objet, son adresse de réponse, son étiquette (tag) et sa pièce jointe servent de valeurs par défaut.

Si textContent est absent, une version texte est déduite du HTML. Avec textContent seul, la partie HTML reprend le texte dans un bloc préformaté.

Expéditeur

sender accepte { "email", "name" } ou { "id" } (un expéditeur créé avec /senders). Sans sender, l'expéditeur du modèle est utilisé, sinon l'expéditeur par défaut du site.

Paramètres et langage de modèle

params alimente les variables du contenu et de l'objet. Les attributs du contact (le premier destinataire to, s'il existe dans vos contacts) sont disponibles sous contact.* ; contact.EMAIL est toujours renseigné.

Bonjour {{ contact.FIRSTNAME | default: "client" }},
Commande n°{{ params.order.id }} : total {{ params.order.total | floatformat: 2 }} €
{% if params.vip %}Livraison offerte !{% elif params.pays == "BE" %}Livraison : 6,90 €{% else %}Livraison : 4,90 €{% endif %}
{% for item in params.items %}{{ forloop.counter }}. {{ item.name }}
{% empty %}Aucun article.{% endfor %}

Filtres : default, upper, lower, capfirst, title, truncatechars, length, floatformat, join, escape, safe. Conditions : == != > < >= <= in and or not. Dans une boucle : forloop.counter, forloop.counter0, forloop.first, forloop.last. Dans htmlContent, les valeurs sont échappées en HTML, sauf avec | safe ; l'objet et textContent ne sont pas échappés.

Destinataires, versions, pièces jointes

  • to (obligatoire, 99 destinataires max.), cc, bcc : tableaux de { "email", "name" } ;
  • replyTo : un objet { "email", "name" } ;
  • tags : tableau de chaînes, utilisé pour filtrer les statistiques ;
  • messageVersions : jusqu'à 1 000 variantes dans une seule requête. Chaque version peut redéfinir to, cc, bcc, replyTo, params (fusionnés avec ceux de la requête), subject, htmlContent et textContent. La réponse contient alors messageIds ;
  • attachment : [{ "name": "facture.pdf", "content": "<base64>" }] ou [{ "url": "https://…/facture.pdf" }]. L'URL doit être publique (http ou https) ; sans name, le nom est tiré de l'URL ;
  • headers : en-têtes personnalisés transmis tels quels.

Idempotence

Ajoutez "headers": { "idempotencyKey": "commande-1042" } : pendant 24 h, une requête répétée avec la même clé renvoie le même messageId (ou les mêmes messageIds) sans renvoyer l'e-mail.

Planification

scheduledAt (ISO 8601, 72 h max.) met l'envoi en file : réponse 202 avec messageId (messageIds avec des versions, plus un batchId quand il y en a plusieurs). Une date passée ou à moins de 30 secondes envoie tout de suite (201).

Action Requête
État GET /smtp/emailStatus/{messageId ou batchId} : queued, inProgress, processed ou error
Annulation DELETE /smtp/email/{messageId ou batchId} : 204, ou 404 si l'envoi n'est plus planifié

Le messageId contient <, > et @ : encodez-le dans l'URL.

Liste de blocage

Avant l'envoi, chaque destinataire to est comparé à la liste de blocage transactionnelle du site, aux domaines bloqués et aux suppressions de la plateforme. Un destinataire bloqué ne reçoit rien et produit un événement blocked ; la requête reste en 201. Un rejet définitif (hard bounce) ou une plainte pour spam ajoute automatiquement l'adresse à la liste de blocage.

Action Requête
Contacts bloqués GET /smtp/blockedContacts (startDate, endDate, senders, limit ≤ 100)
Débloquer un contact DELETE /smtp/blockedContacts/{email}
Domaines bloqués GET /smtp/blockedDomains, POST /smtp/blockedDomains avec { "domain": "example.com" }
Débloquer un domaine DELETE /smtp/blockedDomains/{domain}
Effacer les rejets définitifs POST /smtp/deleteHardbounces (contactEmail, startDate, endDate, tous facultatifs)

Erreurs d'envoi

Statut code Cas
400 missing_parameter ni htmlContent, ni textContent, ni templateId ; to ou subject absent ; aucun expéditeur
400 invalid_parameter adresse invalide, modèle inactif, sender.id inconnu, URL de pièce jointe inaccessible ou non publique
400 out_of_range plus de 99 to, plus de 1 000 versions, scheduledAt au-delà de 72 h
404 document_not_found templateId inconnu

Journaux et statistiques

Besoin Endpoint
Liste des envois GET /smtp/emails (email, messageId, templateId, startDate, endDate, limit ≤ 1000, offset, sort)
Détail d'un envoi (corps, événements) GET /smtp/emails/{uuid}
Événements GET /smtp/statistics/events (event, email, messageId, templateId, tags, dates, limit ≤ 5000)
Totaux GET /smtp/statistics/aggregatedReport (tag, dates)
Par jour GET /smtp/statistics/reports (tag, dates, limit ≤ 30)
Effacer un journal DELETE /smtp/log/{email ou messageId}

Pour les événements et les rapports, les dates se passent avec startDate et endDate ensemble, ou avec days ; par défaut, ils portent sur les 30 derniers jours. Valeurs de event : requests, delivered, opened, clicks, bounces, hardBounces, softBounces, deferred, spam, blocked, invalid, unsubscribed, error. Les envois planifiés ou annulés n'apparaissent pas dans /smtp/emails.

Modèles

Action Requête
Lister GET /smtp/templates (templateStatus=true ou false, limit, offset, sort)
Créer POST /smtp/templates : templateName, subject, sender et htmlContent (ou htmlUrl) obligatoires ; replyTo, tag, toField, attachmentUrl, isActive facultatifs. Réponse 201 { "id" }
Lire, modifier, supprimer GET, PUT, DELETE /smtp/templates/{templateId}
Envoi de test POST /smtp/templates/{templateId}/sendTest avec { "emailTo": ["…"] } (objet préfixé par [Test])
Aperçu rendu POST /smtp/template/preview avec templateId, params et email (contact dont les attributs alimentent contact.*)

Un modèle créé est actif par défaut ; passez "isActive": false pour le créer inactif (il ne peut alors pas servir à POST /smtp/email).