Routes entrantes
Configurez des règles de routage pour diriger les e-mails entrants vers le stockage, un webhook ou d'autres actions
Les routes définissent la manière dont MailLand traite les e-mails entrants d'un domaine. Chaque
route correspond à la partie locale du destinataire (la partie de l'adresse avant le @) et
exécute une ou plusieurs actions : stocker, livrer à un webhook, transférer, rejeter au niveau SMTP
ou supprimer. Les routes sont évaluées par ordre de priorité (le nombre le plus bas en premier) et
la première correspondance l'emporte.
Les routes ne correspondent qu'à la partie locale de l'adresse du destinataire. Il n'y a aucune
correspondance sur l'expéditeur, l'objet ou d'autres en-têtes : une route ne peut pas filtrer sur
from ou subject.
Types de correspondance
| Type de correspondance | Description |
|---|---|
exact | La partie locale correspond exactement au motif |
prefix | La partie locale commence par le motif |
suffix | La partie locale se termine par le motif |
contains | La partie locale contient le motif |
plusaddressing | La partie locale est le motif suivi de +n'importe quoi (support correspond à support+ticket123) |
catchall | Correspond à tout destinataire ; aucun motif requis |
regex | La partie locale correspond au motif en tant qu'expression régulière (200 caractères max, délai de 1 seconde) |
La correspondance ne tient pas compte de la casse et s'effectue toujours sur la partie locale,
[email protected] et [email protected] correspondent tous deux à une route avec le
motif support limitée au même domaine.
Le type de correspondance regex nécessite un forfait prenant en charge le routage entrant par
expression régulière (Pro et Max aujourd'hui, pas Free). Créer une route avec
matchType: "regex", ou mettre à jour une route existante pour que son type de correspondance
devienne regex, sur un forfait qui ne le prend pas en charge renvoie 400 PLAN_LIMIT_REACHED.
Une route déjà en regex continue de correspondre même si l'espace de travail est ensuite
rétrogradé, et la modifier sans changer son type de correspondance n'est pas affecté.
Actions de route
Le champ actions d'une route est une liste d'une ou plusieurs des valeurs de chaîne suivantes :
| Action | Description |
|---|---|
store | Stocker l'e-mail analysé pour récupération via l'API et le tableau de bord |
webhook | Livrer l'e-mail analysé à un webhook (nécessite webhookId) |
forward | Envoyer une copie de l'e-mail à forwardToEmail, via le circuit d'envoi normal |
reject | Refuser le message au niveau SMTP avec rejectStatus/rejectMessage |
drop | Accepter le message par SMTP, puis l'ignorer silencieusement, sans stockage, sans webhook |
unsubscribe | Traiter l'adresse comme une boîte List-Unsubscribe ; terminale, voir ci-dessous |
store et webhook peuvent être combinées entre elles et avec forward. reject, drop et
unsubscribe sont terminales : chacune doit être la seule action de la route ; l'API rejette
une demande qui combine l'une d'elles avec une autre action.
Une copie transférée n'est pas envoyée par relais SMTP brut : elle passe par le même circuit d'envoi que tout autre e-mail transactionnel, c'est pourquoi elle nécessite le consentement du destinataire (ci-dessous), compte dans votre quota d'envoi et apparaît dans votre journal des messages comme tout autre envoi.
Destinations de transfert
Avant qu'un e-mail ne soit transféré à une adresse, le propriétaire de cette adresse doit le confirmer : sauf si l'adresse se trouve sur l'un de vos propres domaines entièrement vérifié pour l'envoi. Pour une adresse externe, il n'y a aucun moyen de contourner cela : cela protège le propriétaire de la destination de recevoir des e-mails auxquels il n'a jamais consenti, et protège votre réputation d'envoi d'une adresse qui rebondit ou se plaint.
Lors de la création ou de la mise à jour d'une route avec forward dans actions, MailLand
effectue automatiquement :
- La création (ou la réutilisation) d'un enregistrement de destination de transfert pour
forwardToEmail, propre à votre tenant : la même adresse est mémorisée sur toutes les routes qui transfèrent vers elle. - Si l'adresse nécessite une confirmation et n'a jamais été sollicitée, l'envoi d'un e-mail de confirmation contenant un lien.
L'enregistrement de la route réussit toujours ; un e-mail de confirmation qui échoue ne fait pas
échouer la route : la destination reste simplement pending (rien n'y est transféré) jusqu'à ce que
vous renvoyiez la confirmation.
Lien de confirmation
Le lien de l'e-mail de confirmation est valable 7 jours et à usage unique : une fois que le
destinataire confirme ou refuse, revisiter le lien affiche simplement la même décision, elle ne
peut pas être annulée en le revisitant. Un lien expiré et jamais décidé renvoie 410 Gone s'il est
rouvert.
- Confirmer : l'e-mail transféré pour ce tenant sera désormais envoyé à l'adresse.
- Refuser : définitif. Plus rien n'est jamais transféré à l'adresse pour ce tenant, et le tenant ne peut plus demander de confirmation pour elle.
Récupérer une destination de transfert
GET https://api.mail.land/v1/transactional/inbound/forward-destinations/{destinationId}{
"id": "f2k9m3q7p4w8x1",
"email": "[email protected]",
"status": "pending",
"confirmedVia": null,
"lastSentAt": "2026-09-26T10:00:00Z",
"confirmedAt": null,
"declinedAt": null
}status vaut pending, confirmed ou declined. confirmedVia vaut link lorsque le
propriétaire a confirmé via l'e-mail, verified_domain lorsque l'adresse est sur l'un de vos propres
domaines vérifiés pour l'envoi et n'a nécessité aucune confirmation, ou null sinon. La réponse
d'une route porte aussi ce même objet sous forwardDestination (voir la réponse de route
ci-dessous).
Renvoyer une confirmation
POST https://api.mail.land/v1/transactional/inbound/forward-destinations/{destinationId}/resendUniquement pour une destination encore pending qui a réellement besoin d'un lien (une adresse sur
l'un de vos propres domaines d'envoi vérifiés renvoie
409 FORWARD_DESTINATION_NO_CONFIRMATION_NEEDED, puisqu'il n'y a rien à renvoyer). Limité en
fréquence : au plus une fois toutes les 5 minutes et 5 fois par jour par destination, et 50 fois par
jour pour l'ensemble du tenant. Dépasser l'une ou l'autre limite renvoie
429 FORWARD_CONFIRMATION_RATE_LIMITED.
Il n'existe aucun moyen d'annuler le refus d'une destination via l'API une fois qu'elle a refusé : une adresse refusée reste bloquée pour ce tenant.
Créer une route
Les routes appartiennent à un domaine et sont créées sous ce domaine.
POST https://api.mail.land/v1/transactional/inbound/domains/{domainId}/routes{
"name": "Support Inbox",
"matchType": "exact",
"matchPattern": "support",
"actions": ["store", "webhook"],
"webhookId": "w4k8m2q7p9x3z1",
"priority": 10
}| Champ | Type | Requis | Description |
|---|---|---|---|
name | string | Oui | Nom de la route |
matchType | string | Oui | L'un des types de correspondance ci-dessus |
matchPattern | string | Oui | Motif à comparer à la partie locale (ignoré pour catchall, 64 caractères max, 200 pour regex) |
actions | string[] | Oui | Une ou plusieurs valeurs parmi store, webhook, forward, reject, drop, unsubscribe |
webhookId | string | Cond. | ID public d'un webhook existant ; requis lorsque actions inclut webhook. Les routes ne créent jamais de webhook en ligne : créez-le d'abord sur la page Webhooks |
forwardToEmail | string | Cond. | Destination pour forward ; requis lorsque actions inclut forward. Doit être une adresse nue (sans nom d'affichage, sans chevrons). Le domaine propre de la route doit être entièrement vérifié pour l'envoi, la copie transférée est envoyée depuis lui, sinon la demande est rejetée avec 400 FORWARD_DOMAIN_NOT_VERIFIED. La destination elle-même doit confirmer séparément, sauf si elle est sur l'un de vos propres domaines vérifiés pour l'envoi (voir Destinations de transfert) |
rejectStatus | string | Non | Statut SMTP pour reject, ex. 550 ou 550 5.1.1 (par défaut 550 5.1.1) |
rejectMessage | string | Non | Texte de rejet SMTP pour reject |
priority | int | Non | Nombre plus bas = évalué en premier. Par défaut, un de plus que la priorité la plus élevée actuelle du domaine. Doit être unique par domaine |
curl -X POST https://api.mail.land/v1/transactional/inbound/domains/k3v9x2m8q1w7z4/routes \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{
"name": "Support Inbox",
"matchType": "exact",
"matchPattern": "support",
"actions": ["store", "webhook"],
"webhookId": "w4k8m2q7p9x3z1",
"priority": 10
}'Réponse
{
"id": "r7k3m9q2p4w8x1",
"name": "Support Inbox",
"domainId": "k3v9x2m8q1w7z4",
"domainName": "yourdomain.com",
"priority": 10,
"isEnabled": true,
"matchType": "Exact",
"matchPattern": "support",
"actions": ["store", "webhook"],
"webhookId": "w4k8m2q7p9x3z1",
"webhookName": "Support Webhook",
"webhookUrl": "https://yourapp.com/webhooks/support",
"forwardToEmail": null,
"forwardDestination": null,
"rejectStatus": null,
"rejectMessage": null,
"createdAt": "2026-02-17T12:00:00Z",
"updatedAt": "2026-02-17T12:00:00Z"
}Les requêtes acceptent matchType dans n'importe quelle casse ; les réponses renvoient toujours le
nom de l'énumération avec une majuscule initiale : Exact, Prefix, Suffix, Contains,
PlusAddressing, CatchAll, Regex. Ne comparez pas le matchType d'une réponse à une chaîne en
minuscules.
forwardDestination n'est renseigné que lorsque actions inclut forward ; il porte le même objet
que décrit dans Récupérer une destination de transfert :
{
"...": "...",
"actions": ["store", "forward"],
"forwardToEmail": "[email protected]",
"forwardDestination": {
"id": "f2k9m3q7p4w8x1",
"email": "[email protected]",
"status": "pending",
"confirmedVia": null,
"lastSentAt": "2026-09-26T10:00:00Z",
"confirmedAt": null,
"declinedAt": null
}
}Lister les routes d'un domaine
GET https://api.mail.land/v1/transactional/inbound/domains/{domainId}/routesRetourne toutes les routes du domaine, triées par priorité (la plus basse en premier).
curl https://api.mail.land/v1/transactional/inbound/domains/k3v9x2m8q1w7z4/routes \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."{
"items": [
{ "id": "r7k3m9q2p4w8x1", "name": "Support Inbox", "priority": 10, "isEnabled": true, "..." : "..." }
],
"totalCount": 1
}Lister toutes les routes
Pour lister les routes de tous les domaines d'un tenant, utilisez plutôt le point de terminaison paginé par curseur :
GET https://api.mail.land/v1/transactional/inbound/routes| Paramètre | Type | Défaut | Description |
|---|---|---|---|
cursor | string | - | Curseur opaque issu du nextCursor de la page précédente. À omettre pour la première page |
limit | int | 50 | Éléments par page |
Obtenir les détails d'une route
GET https://api.mail.land/v1/transactional/inbound/routes/{routeId}curl https://api.mail.land/v1/transactional/inbound/routes/r7k3m9q2p4w8x1 \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."Mettre à jour une route
PUT https://api.mail.land/v1/transactional/inbound/routes/{routeId}Le corps de la requête correspond à celui de la création, mais chaque champ est optionnel : seuls les champs envoyés sont mis à jour.
curl -X PUT https://api.mail.land/v1/transactional/inbound/routes/r7k3m9q2p4w8x1 \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{
"matchPattern": "help",
"priority": 5
}'Activer ou désactiver une route
Bascule isEnabled sans toucher aux autres champs. Pas de corps de requête.
POST https://api.mail.land/v1/transactional/inbound/routes/{routeId}/togglecurl -X POST https://api.mail.land/v1/transactional/inbound/routes/r7k3m9q2p4w8x1/toggle \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."Réordonner les routes
Met à jour la priorité de toutes les routes d'un domaine en une seule fois, en passant les ID de route dans l'ordre souhaité : le premier ID devient priorité 1, le deuxième priorité 2, et ainsi de suite.
POST https://api.mail.land/v1/transactional/inbound/domains/{domainId}/routes/reorder{
"routeIds": ["r7k3m9q2p4w8x1", "m2p8w4x1k7q3z9", "x4k1p7m3q9w2z8"]
}curl -X POST https://api.mail.land/v1/transactional/inbound/domains/k3v9x2m8q1w7z4/routes/reorder \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{
"routeIds": ["r7k3m9q2p4w8x1", "m2p8w4x1k7q3z9", "x4k1p7m3q9w2z8"]
}'Tester une route
Vérifiez quelle route correspondrait à une adresse de destinataire donnée sans traiter d'e-mail.
POST https://api.mail.land/v1/transactional/inbound/domains/{domainId}/routes/test{
"emailAddress": "[email protected]"
}curl -X POST https://api.mail.land/v1/transactional/inbound/domains/k3v9x2m8q1w7z4/routes/test \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{
"emailAddress": "[email protected]"
}'{
"matched": true,
"matchedRouteId": "r7k3m9q2p4w8x1",
"matchedRouteName": "Support Inbox",
"actions": ["store", "webhook"]
}Si aucune route ne correspond, la réponse est 200 avec matched: false, et matchedRouteId/matchedRouteName/actions sont tous null. 404 signifie que le domaine est introuvable, ou que l'adresse testée est invalide (pas de @).
Supprimer une route
DELETE https://api.mail.land/v1/transactional/inbound/routes/{routeId}curl -X DELETE https://api.mail.land/v1/transactional/inbound/routes/r7k3m9q2p4w8x1 \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."Exemples de routes
Route catch-all : stocker tout destinataire non reconnu :
{
"name": "Catch All",
"matchType": "catchall",
"matchPattern": "*",
"actions": ["store"],
"priority": 999
}Adressage plus : router toutes les variantes de support+*@yourdomain.com vers un webhook :
{
"name": "Support Tickets",
"matchType": "plusaddressing",
"matchPattern": "support",
"actions": ["store", "webhook"],
"webhookId": "w4k8m2q7p9x3z1",
"priority": 5
}Rejet au niveau SMTP : refuser le courrier vers une boîte retirée avant qu'il ne soit accepté :
{
"name": "Retired Mailbox",
"matchType": "exact",
"matchPattern": "old-team",
"actions": ["reject"],
"rejectStatus": "550 5.1.1",
"rejectMessage": "Mailbox does not exist",
"priority": 1
}Les routes sont évaluées par ordre de priorité (le nombre le plus bas en premier). Placez les routes spécifiques sur des numéros de priorité plus bas et les routes catch-all sur le numéro le plus élevé afin qu'elles s'exécutent en dernier.
À quoi ressemble une copie transférée
Une copie transférée est un nouvel e-mail transactionnel ordinaire, pas un relais brut des octets d'origine, envoyé depuis votre domaine vérifié afin de passer DKIM et DMARC chez le fournisseur de messagerie du destinataire :
- From :
"<nom de l'expéditeur d'origine> via <adresse correspondante>@<votre domaine>", par ex."Jane Doe via [email protected]". Un nom d'affichage qui ressemble à une adresse (contient@,<ou>) est remplacé par l'adresse d'origine nue, afin qu'une copie ne puisse jamais usurper une marque sous votre DKIM. - Reply-To : le
Reply-Todu message d'origine s'il en avait un, sinon l'adresse de l'expéditeur d'origine, afin que les réponses atteignent le véritable auteur, pas vous. - Aucun suivi : le suivi des ouvertures et des clics est toujours désactivé sur une copie transférée, quels que soient les réglages de suivi de votre espace de travail.
- Aucun pied de page de marque : le pied de page du plan gratuit que d'autres envois peuvent porter n'est jamais ajouté.
- Pièces jointes : filtrées selon les mêmes règles qu'un envoi sortant par API (type, nombre, taille totale). Ce qui est omis est signalé par une note en haut de la copie : "Forwarded without N attachment(s) that exceed the outbound attachment limits: ...", la copie arrive quand même, simplement sans ces éléments.
- Étiquette : chaque copie transférée porte l'étiquette
inbound-forward, afin que vous puissiez les retrouver dans votre journal des messages habituel ; son statut de livraison (queued, sent, delivered, bounced, etc.) est le même statut que tout autre envoi transactionnel, car elle passe par le même circuit de livraison. - Utilisation : chaque copie transférée compte comme un envoi contre le quota et la facturation de votre plan, et apparaît comme sa propre ligne « Inbound forward » dans l'utilisation, distincte des envois par API, SMTP, campagnes et automatisations.
Ce qui n'est jamais transféré
Un message correspondant à une route forward n'est pas transféré, et jamais facturé, lorsque :
- Il a été signalé comme spam, ou l'expéditeur est bloqué comme spammeur.
- Il a échoué DMARC selon la politique effective du domaine expéditeur, qui est
quarantineoureject, déterminée en remontant depuis le domaine de l'expéditeur jusqu'au premier enregistrement applicable, de sorte que lesp=propre à un sous-domaine prévaut sur lep=de son domaine organisationnel, et un enregistrementt=y(test) oupct=0est traité un niveau de politique en dessous, le transférer resignerait un message que l'expéditeur a explicitement demandé aux destinataires de refuser. - Lui, ou son corps HTML/texte, dépasse les limites de taille sortante de la plateforme.
- Le transférer créerait une boucle : la destination est l'un des propres destinataires du message,
ou il porte déjà trop de sauts ou d'en-têtes
Received.
Une copie éligible mais temporairement impossible à envoyer (une pause de politique, une fenêtre de quota, une panne) est retentée avec un délai croissant pendant jusqu'à 24 heures, puis expire sans être envoyée. Une route désactivée, supprimée, ou dont la destination change après réception d'un message, arrête aussi toute copie encore en attente : la configuration actuelle de la route fait toujours autorité.
Vérifier le résultat d'un transfert
Chaque e-mail entrant ayant correspondu à une route forward porte un tableau forwards dans sa
réponse détaillée (GET /v1/transactional/inbound/emails/{id}) : une entrée par destination vers laquelle le
message a été mis en file pour transfert, afin que vous voyiez ce qui s'est réellement passé, pas
seulement la destination configurée.
"forwards": [
{
"destination": "[email protected]",
"status": "Admitted",
"reason": null,
"omittedAttachmentCount": 0,
"messageId": "m_01hz3k...",
"createdAt": "2026-09-26T10:00:00Z",
"updatedAt": "2026-09-26T10:00:02Z"
}
]| Champ | Type | Description |
|---|---|---|
destination | string | L'adresse de destination du transfert |
status | string | L'un des statuts ci-dessous |
reason | string | null | Code de détail lisible par machine (par exemple hop_limit), ou null |
omittedAttachmentCount | nombre | Pièces jointes exclues de la copie car dépassant les limites de pièces jointes sortantes |
messageId | string | null | L'id de message de la copie transférée une fois admise, sinon null |
createdAt / updatedAt | string | Horodatages ISO-8601 de l'enregistrement de transfert |
status est l'une des valeurs suivantes :
| Statut | Signification |
|---|---|
Pending | Écrit avec le message entrant ; pas encore pris en charge par le worker de transfert |
Processing | Pris en charge par le worker de transfert ; en cours |
Deferred | Un refus transitoire (délai de politique, débit, fenêtre de quota, panne) ; réessayé avec backoff pendant jusqu'à 24 heures |
Admitted | Envoyé via le pipeline d'envoi normal : messageId désigne la copie, dont le propre statut de livraison (en file/envoyé/livré/rejeté) fait foi |
SkippedLoop | Protection contre les boucles : limite de sauts, trop d'en-têtes Received, ou la destination est l'un des destinataires du message lui-même |
SkippedSpam | Le message a été signalé comme spam, ou l'expéditeur est sur liste noire pour spam |
SkippedAuthFail | Échec DMARC selon la politique effective du domaine expéditeur (quarantine ou reject, sp= du sous-domaine respecté) |
SkippedTooLarge | Le message dépasse la limite de taille de transfert sortant |
RefusedSuppressed | La destination est supprimée, ou refusée par la protection des destinataires |
RefusedDomainNotVerified | Le domaine de la route n'est pas (ou plus) vérifié pour l'envoi |
RefusedPolicy | Un refus définitif de politique ou de compte |
RefusedRouteInactive | La route a été désactivée, supprimée, a perdu son action forward, ou a changé de destination après réception du message |
RefusedInvalid | Le message stocké n'a pas pu être transformé en copie envoyable |
Expired | Encore Deferred à la fermeture de la fenêtre de nouvelle tentative de 24 heures |
RefusedDestinationUnconfirmed | La destination n'a pas encore confirmé (voir Destinations de transfert) |
RefusedDestinationDeclined | Le propriétaire de la destination a refusé ; rien n'est plus jamais transféré vers cette adresse |
Pending, Processing et Deferred sont les seuls statuts non définitifs, toute autre valeur
est définitive.
Réponses d'erreur de transfert
| Statut | Code | Description |
|---|---|---|
400 | VALIDATION_FAILED (champ forwardToEmail) | À la création : actions inclut forward mais forwardToEmail est vide |
400 | FORWARD_DESTINATION_REQUIRED | À la mise à jour (PUT) : la route effective résultante transfère mais n'a pas de forwardToEmail |
400 | FORWARD_DOMAIN_NOT_VERIFIED | Le domaine de la route n'est pas entièrement vérifié pour l'envoi, donc aucune copie transférée n'aurait jamais pu en être envoyée |
404 | RESOURCE_NOT_FOUND | Destination de transfert introuvable |
409 | FORWARD_DESTINATION_NOT_PENDING | Renvoi demandé pour une destination ayant déjà confirmé ou refusé |
409 | FORWARD_DESTINATION_NO_CONFIRMATION_NEEDED | Renvoi demandé pour une destination sur l'un de vos propres domaines d'envoi vérifiés |
410 | FORWARD_CONFIRMATION_EXPIRED | Le lien de confirmation a expiré (7 jours) sans avoir été décidé |
409 | FORWARD_CONFIRMATION_ALREADY_DECIDED | Le lien a été utilisé pour l'autre décision |
429 | FORWARD_CONFIRMATION_RATE_LIMITED | Renvoi demandé trop tôt, ou limite quotidienne de renvoi atteinte |
Réponses d'erreur
| Statut | Code | Description |
|---|---|---|
400 | VALIDATION_FAILED | Champs requis manquants, matchType/actions invalides, ou une action terminale combinée à une autre |
400 | INVALID_REQUEST | Une route avec cette priority existe déjà pour le domaine, ou le webhookId référencé est introuvable |
400 | PLAN_LIMIT_REACHED | Créer une route avec matchType: "regex", ou mettre à jour une route pour que son type de correspondance devienne regex, sur un forfait sans prise en charge des routes regex (Free aujourd'hui) |
403 | FORBIDDEN | Permissions insuffisantes |
404 | RESOURCE_NOT_FOUND | Domaine ou route introuvable (point de terminaison de test : aussi une adresse invalide sans @ ; l'absence de correspondance est 200 avec matched: false, pas un 404) |
Étapes suivantes
- Inbound Overview : fonctionnement du traitement des e-mails entrants
- Inbound Webhooks : format de payload et livraison des webhooks
- Domains : configurer les enregistrements MX pour les e-mails entrants