Email infrastructure built for AI agents
Donnez à un agent la capacité d'envoyer un email, d'authentifier un domaine, de suivre la remise et de diagnostiquer sa délivrabilité. Sans qu'un humain lise un tableau de bord entre deux étapes. Serveurs en Allemagne, envoi via Amazon SES Europe.
Ce parcours est réel. Déclaration du domaine, essai à blanc, envoi, relance après un délai réseau, statut de remise. La relance rend le même identifiant : le message n'est pas parti deux fois.
Un agent échoue autrement qu'une personne.
Il relance, il ne lit pas de tableau de bord, et il annonce une réussite parce qu'il a reçu un 200. L'API est faite pour ça.
Accepté n'est pas remis
Un envoi rend 202 et un identifiant : le message est en file, pas dans la boîte du destinataire. Seul le suivi dit ce qu'il est devenu, et les descriptions d'outils le disent noir sur blanc pour qu'un agent n'annonce pas une remise qu'il ne peut pas connaître.
GET /api/v1/messages/2841 "status": "delivered" "events": [ delivered, opened ]
Relancer n'envoie pas deux fois
Un en-tête Idempotency-Key et la première réponse est rejouée pendant 24 heures au lieu de partir une seconde fois. La même clé avec un contenu différent est refusée : c'est une erreur d'appel, pas un rejeu.
Idempotency-Key: task-837-invoice Idempotent-Replay: true
Chaque erreur dit quoi faire
Un code stable sur lequel brancher un comportement, la mention de ce qui peut être retenté, et l'action corrective avec l'endpoint qui la réalise. Pas de "Invalid request".
{
"code": "DOMAIN_NOT_VERIFIED",
"retryable": false,
"resolution": {
"action": "add_dns_records",
"endpoint": "/api/v1/domains"
}
}
Une clé bornée ne déborde pas
Portées par clé, plafond d'envois par jour, nombre de destinataires par message, liste des domaines expéditeurs autorisés. Un agent ne peut pas engager plus que ce que sa clé permet, et la consommation restante se lit par API.
"scopes": ["email.send", "email.read_status"] "max_emails_per_day": 100 "daily_remaining": 63
Autonome, mais redevable
Une ligne par appel : quelle clé, quelle opération, quels paramètres, quel résultat. Le corps des messages n'y figure jamais. C'est ce qui permet à un agent d'expliquer exactement ce qu'il a fait, et à un humain de le relire après coup.
Les étapes humaines sont nommées
Publier un enregistrement DNS en est une. Un enregistrement dont la valeur dépend encore de la configuration du serveur d'envoi est marqué publishable: false : le poser tel quel casserait l'authentification du domaine. L'agent le signale au lieu de le faire.
Treize outils, et ce que chacun ne fait pas.
Le serveur MCP s'installe en une commande et n'a aucune dépendance. Node 18 suffit.
| Outil | Ce qu'il fait |
|---|---|
| vaemail_capabilities | Ce que le service sait faire. Aucune clé nécessaire, c'est l'appel qui sert à décider si VaEmail couvre le besoin. |
| vaemail_send_email | Met un email en file et rend son identifiant. Accepte une clé d'idempotence. |
| vaemail_validate_email | Essai à blanc : dit si l'envoi passerait et nomme ce qui le bloquerait. N'envoie rien. |
| vaemail_get_message | Statut de remise d'un message et tous ses événements, y compris le motif d'échec. |
| vaemail_list_messages | Messages récents, filtrés par statut, étiquette ou destinataire. |
| vaemail_list_domains | Domaines d'envoi et état réel de leur SPF, DKIM et DMARC, lu dans le DNS public. |
| vaemail_create_domain | Déclare un domaine et rend les enregistrements DNS à publier, avec le rôle de chacun. |
| vaemail_verify_domain | Relit le DNS et dit ce qui est authentifié. |
| vaemail_dns_requirements | Ce qui manque encore à un domaine déjà déclaré. |
| vaemail_diagnose_deliverability | Pourquoi le courrier arrive mal : authentification, rebonds, plaintes, provenance des contacts, et les actions qui corrigent. |
| vaemail_list_bounces | Adresses sorties du circuit et raison de chacune. |
| vaemail_get_usage | Quota, plafond journalier de la clé, ce qu'il reste. |
| vaemail_get_audit_log | Ce que cette clé a fait, pour le rapporter sans le reconstituer de mémoire. |
Trois façons de brancher, selon ce que fait votre agent.
MCP
Pour un agent conversationnel qui décide de ses outils. Claude Code, Claude Desktop, ou tout client MCP.
claude mcp add vaemail \ --env VAEMAIL_API_KEY=swm_... \ -- npx -y vaemail mcp
CLI
Pour un agent qui exécute des commandes, ou pour vérifier une configuration en dix secondes. --json sur n'importe quelle commande pour une sortie exploitable.
npx vaemail doctor npx vaemail send --to a@b.fr \ --subject Bonjour --html '<p>Salut</p>'
REST et OpenAPI
Pour du code. La spécification est générée depuis les routes réellement servies : elle ne peut pas décrire un endpoint disparu ni taire un endpoint récent.
curl -H "api-key: swm_..." \ https://app.vaemail.fr/api/v1/capabilities https://app.vaemail.fr/openapi.json
SMTP
Pour une application existante qu'on ne réécrit pas. L'API compatible Brevo répond aux mêmes chemins, avec le même schéma : changer l'URL de base suffit.
https://app.vaemail.fr/v3/smtp/email
Ce que VaEmail ne fait pas.
Une capacité annoncée à tort coûte plus cher qu'une capacité absente : l'agent construit dessus et échoue plus loin.
- Pas de boîte de réception générique. On ne peut pas créer une adresse à la volée pour recevoir un code de vérification ou s'inscrire quelque part. Les réponses aux séquences de prospection, elles, sont bien relevées et on peut y répondre dans le fil.
- Pas de création de compte par API. Ouvrir un compte et générer une première clé passe par un humain. Tout le reste s'enchaîne ensuite sans intervention.
- Pas de publication DNS à votre place. Les enregistrements sont rendus prêts à poser, avec le rôle de chacun ; les publier reste une action chez votre registrar.
- Pas de coût par message exposé en API. La consommation et les quotas se lisent, la facturation non.