Documentation › Outils › send_email
send_email
Écrit un premier message à un destinataire depuis une boîte.
En bref
| Propriété | Valeur |
|---|---|
| Titre | Envoyer un e-mail |
| Outil MCP | send_email, sur https://api.subagent.fr/mcp |
| Appel HTTP | POST https://api.subagent.fr/v1/send_email |
| Accès | permission send |
| État de l’espace | vérifié : sinon, refus space_unverified |
| Effet | écriture |
| Vue dans l’assistant | oui : voir Vues |
Ce que fait l’outil
Le serveur décrit l’outil ainsi à l’agent qui se branche :
Écrit un premier message à un destinataire depuis une boîte. Le message ne part pas tout de suite : il entre en file et part dans le créneau d’envoi de l’espace (jours ouvrés, heure de Paris), dans la limite du quota du jour de la boîte (réchauffage) et avec un étalement entre deux envois ; ou il reste brouillon si une validation humaine est demandée. Refusé si le destinataire est bloqué (désinscrit, adresse morte), s’il a déjà reçu un premier message de cette boîte récemment (pour relancer :
reply_to_thread), ou si la boîte est suspendue. Un lien de désinscription en un clic est toujours ajouté.
Paramètres
send_email accepte ces paramètres. Un paramètre inconnu est refusé avec le code invalid_argument.
| Paramètre | Type | Obligatoire | Description |
|---|---|---|---|
inbox_id | identifiant inb_… | oui | Boîte d’envoi (inb_…, voir list_inboxes). |
to | texte | oui | Adresse du destinataire. |
to_name | texte | non | Nom du destinataire, facultatif. 120 caractères au plus. |
subject | texte | oui | Sujet (une ligne). 300 caractères au plus. |
test | booléen | non | Envoi de test, à soi-même seulement (l’e-mail de l’humain de l’espace ou une autre boîte de l’espace) : pas de règle de doublon, et son lien de désinscription ne désinscrit personne. |
text | texte | oui | Texte brut du message (obligatoire). Écrivez {{unsubscribe_url}} pour placer vous-même le lien de désinscription ; sinon Subagent ajoute une mention en pied, tant que le correspondant n’a pas écrit dans le fil. Aucun autre {{champ}} n’est accepté : remplacez-les avant. |
html | texte | non | Version HTML facultative, même contenu que text. |
reply_to | texte | non | Adresse de réponse, si elle diffère de la boîte. |
metadata | objet | non | Données libres de l’agent (8 000 caractères au plus), rendues telles quelles dans les lectures et les webhooks. |
requires_approval | booléen | non | true : le message reste brouillon jusqu’à ce qu’un humain le valide (approve_message). Certains espaces l’imposent toujours. |
send_after | date | non | Pas avant cette date (ISO 8601, ou heure de Paris sans fuseau). Le créneau (sauf pour une réponse dans une conversation) et les quotas s’appliquent ensuite. |
idempotency_key | texte | non | Clé unique de cet envoi (1 à 255 caractères). Rejouer la même clé avec le même contenu rend le message déjà créé ; avec un contenu différent, refus explicite. Recommandée pour tout réessai. |
Résultat
L’outil rend un texte lisible en français et un objet structuré (structuredContent). En HTTP, la réponse est cet objet.
| Champ | Type | Contenu |
|---|---|---|
estimated_send_at | texte ou null | Départ au plus tôt (estimation : créneau, étalement, quota). |
inbox | objet | Une boîte. Voir les champs d’une boîte. |
message | objet | Un message. Voir les champs d’un message. |
replayed | booléen | true : même clé d’idempotence et même contenu, rien de nouveau n’a été créé. |
thread | objet | Un fil. Voir les champs d’un fil. |
Exemple d’appel
Les valeurs sont fictives.
HTTP
curl -X POST https://api.subagent.fr/v1/send_email \
-H "Authorization: Bearer $SUBAGENT_KEY" \
-H "Content-Type: application/json" \
-d '{
"inbox_id": "inb_3f9c2a7e5b1d4c8e9a0f6b2d7c4e1a95",
"to": "nadia.morel@exemple.com",
"to_name": "Nadia Morel",
"subject": "Rendez-vous de jeudi",
"text": "Bonjour Madame Morel,\n\nPouvons-nous déplacer notre rendez-vous de jeudi à vendredi, à la même heure ?\n\nAtelier Exemple",
"idempotency_key": "rdv-morel-2026-10-13"
}'MCP · tools/call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "send_email",
"arguments": {
"inbox_id": "inb_3f9c2a7e5b1d4c8e9a0f6b2d7c4e1a95",
"to": "nadia.morel@exemple.com",
"to_name": "Nadia Morel",
"subject": "Rendez-vous de jeudi",
"text": "Bonjour Madame Morel,\n\nPouvons-nous déplacer notre rendez-vous de jeudi à vendredi, à la même heure ?\n\nAtelier Exemple",
"idempotency_key": "rdv-morel-2026-10-13"
}
}
}Refus possibles
| Code | HTTP | Ce qui s’est passé | Que faire |
|---|---|---|---|
space_unverified | 403 | L’espace n’est pas vérifié : ses boîtes reçoivent, mais n’envoient pas. | Demander à l’humain le code à 6 chiffres, puis appeler verify. S’il n’a rien reçu, ou si aucun e-mail n’est rattaché à l’espace : attach_human. |
payment_required | 402 | L’espace n’a pas de forfait en cours : sa boîte reçoit, prépare des brouillons et n’écrit qu’à son humain. Le refus vaut pour un envoi à un tiers, la validation d’un brouillon, une seconde boîte et add_domain. | Appeler subscribe, après l’accord de l’humain, et lui remettre le lien de paiement. Ensuite, billing_status dit si le forfait est en cours. |
own_domain_required | 422 | La boîte est sur le domaine commun : elle ne fait que répondre à qui lui a écrit. Un premier message, ou une relance sans réponse, n’en part pas. | Enregistrer le domaine de l’humain (add_domain), le faire vérifier (verify_domain), y créer une boîte (create_inbox) et écrire depuis elle. |
not_found | 404 | L’objet n’existe pas pour cette clé. | Vérifier l’identifiant : il vient de list_inboxes, list_threads, get_thread ou list_drafts. |
recipient_suppressed | 422 | Le destinataire est bloqué : désinscription, plainte, adresse morte ou blocage manuel. | Ne plus écrire à cette adresse, depuis aucune boîte. |
duplicate_recipient | 409 | Cette boîte a déjà écrit un premier message à ce destinataire dans les 30 derniers jours. | Répondre dans le fil donné par la piste, avec reply_to_thread. |
key_daily_cap | 429 | Le plafond de messages par jour de la clé est atteint. | Reprendre le lendemain, à partir de 0 h, heure de Paris. |
inbox_suspended | 409 | Le coupe-circuit a suspendu la boîte. La raison est dans le message. | Vérifier la liste de destinataires. La reprise est manuelle, par un administrateur de Subagent : l’humain la demande avec request_inbox_review. |
domain_not_verified | 409 | Le domaine de la boîte n’est pas encore vérifié. | Publier ses enregistrements DNS, puis appeler verify_domain. |
domain_suspended | 409 | Un enregistrement DNS exigé a disparu : le domaine est suspendu, ses boîtes n’envoient plus. | Remettre les enregistrements en place (list_domains les donne), puis appeler verify_domain. |
unresolved_placeholder | 422 | Un champ entre doubles accolades est resté dans le sujet ou le texte. | Remplacer chaque champ par sa valeur. Seul {{unsubscribe_url}} est accepté. |
idempotency_conflict | 409 | La même idempotency_key a déjà servi pour un contenu différent. | Même message : réutiliser la clé telle quelle. Nouveau message : en prendre une nouvelle. |
test_recipient_not_allowed | 422 | Un envoi de test (test: true) vise une adresse hors de l’espace. | Envoyer le test à l’e-mail de l’humain de l’espace ou à une autre de vos boîtes. Pour écrire à ce destinataire : retirer test. |
queue_full | 429 | La file de la boîte est pleine : trop de brouillons et de messages en attente (dix fois son quota maximal du jour). | Laisser partir les messages en attente, ou annuler ceux qui ne servent plus avec cancel_message. |
S’y ajoutent les refus communs à tous les outils (unauthorized, forbidden, invalid_argument, rate_limited, internal) : voir Erreurs.