MailLandDocs
Email entrant

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 correspondanceDescription
exactLa partie locale correspond exactement au motif
prefixLa partie locale commence par le motif
suffixLa partie locale se termine par le motif
containsLa partie locale contient le motif
plusaddressingLa partie locale est le motif suivi de +n'importe quoi (support correspond à support+ticket123)
catchallCorrespond à tout destinataire ; aucun motif requis
regexLa 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 :

ActionDescription
storeStocker l'e-mail analysé pour récupération via l'API et le tableau de bord
webhookLivrer l'e-mail analysé à un webhook (nécessite webhookId)
forwardEnvoyer une copie de l'e-mail à forwardToEmail, via le circuit d'envoi normal
rejectRefuser le message au niveau SMTP avec rejectStatus/rejectMessage
dropAccepter le message par SMTP, puis l'ignorer silencieusement, sans stockage, sans webhook
unsubscribeTraiter 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 :

  1. 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.
  2. 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}
Réponse d'une destination de transfert
{
  "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}/resend

Uniquement 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
Create route request
{
  "name": "Support Inbox",
  "matchType": "exact",
  "matchPattern": "support",
  "actions": ["store", "webhook"],
  "webhookId": "w4k8m2q7p9x3z1",
  "priority": 10
}
ChampTypeRequisDescription
namestringOuiNom de la route
matchTypestringOuiL'un des types de correspondance ci-dessus
matchPatternstringOuiMotif à comparer à la partie locale (ignoré pour catchall, 64 caractères max, 200 pour regex)
actionsstring[]OuiUne ou plusieurs valeurs parmi store, webhook, forward, reject, drop, unsubscribe
webhookIdstringCond.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
forwardToEmailstringCond.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)
rejectStatusstringNonStatut SMTP pour reject, ex. 550 ou 550 5.1.1 (par défaut 550 5.1.1)
rejectMessagestringNonTexte de rejet SMTP pour reject
priorityintNonNombre 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
Create an inbound route
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

Route response
{
  "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 :

Réponse de route avec un transfert en attente
{
  "...": "...",
  "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}/routes

Retourne toutes les routes du domaine, triées par priorité (la plus basse en premier).

List routes for a domain
curl https://api.mail.land/v1/transactional/inbound/domains/k3v9x2m8q1w7z4/routes \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
Route list response
{
  "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ètreTypeDéfautDescription
cursorstring-Curseur opaque issu du nextCursor de la page précédente. À omettre pour la première page
limitint50Éléments par page

Obtenir les détails d'une route

GET https://api.mail.land/v1/transactional/inbound/routes/{routeId}
Get route details
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.

Update an inbound route
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}/toggle
Toggle a route
curl -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
Reorder routes request
{
  "routeIds": ["r7k3m9q2p4w8x1", "m2p8w4x1k7q3z9", "x4k1p7m3q9w2z8"]
}
Reorder routes
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
Test route request
{
  "emailAddress": "[email protected]"
}
Test a route
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]"
  }'
Test route response : match found
{
  "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}
Delete a route
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 :

Catch-all route
{
  "name": "Catch All",
  "matchType": "catchall",
  "matchPattern": "*",
  "actions": ["store"],
  "priority": 999
}

Adressage plus : router toutes les variantes de support+*@yourdomain.com vers un webhook :

Plus-addressing route
{
  "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é :

Reject route
{
  "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-To du 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 quarantine ou reject, déterminée en remontant depuis le domaine de l'expéditeur jusqu'au premier enregistrement applicable, de sorte que le sp= propre à un sous-domaine prévaut sur le p= de son domaine organisationnel, et un enregistrement t=y (test) ou pct=0 est 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 sur un e-mail entrant
"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"
  }
]
ChampTypeDescription
destinationstringL'adresse de destination du transfert
statusstringL'un des statuts ci-dessous
reasonstring | nullCode de détail lisible par machine (par exemple hop_limit), ou null
omittedAttachmentCountnombrePièces jointes exclues de la copie car dépassant les limites de pièces jointes sortantes
messageIdstring | nullL'id de message de la copie transférée une fois admise, sinon null
createdAt / updatedAtstringHorodatages ISO-8601 de l'enregistrement de transfert

status est l'une des valeurs suivantes :

StatutSignification
PendingÉcrit avec le message entrant ; pas encore pris en charge par le worker de transfert
ProcessingPris en charge par le worker de transfert ; en cours
DeferredUn refus transitoire (délai de politique, débit, fenêtre de quota, panne) ; réessayé avec backoff pendant jusqu'à 24 heures
AdmittedEnvoyé via le pipeline d'envoi normal : messageId désigne la copie, dont le propre statut de livraison (en file/envoyé/livré/rejeté) fait foi
SkippedLoopProtection 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
SkippedSpamLe 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é)
SkippedTooLargeLe message dépasse la limite de taille de transfert sortant
RefusedSuppressedLa destination est supprimée, ou refusée par la protection des destinataires
RefusedDomainNotVerifiedLe domaine de la route n'est pas (ou plus) vérifié pour l'envoi
RefusedPolicyUn refus définitif de politique ou de compte
RefusedRouteInactiveLa route a été désactivée, supprimée, a perdu son action forward, ou a changé de destination après réception du message
RefusedInvalidLe message stocké n'a pas pu être transformé en copie envoyable
ExpiredEncore Deferred à la fermeture de la fenêtre de nouvelle tentative de 24 heures
RefusedDestinationUnconfirmedLa destination n'a pas encore confirmé (voir Destinations de transfert)
RefusedDestinationDeclinedLe 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

StatutCodeDescription
400VALIDATION_FAILED (champ forwardToEmail)À la création : actions inclut forward mais forwardToEmail est vide
400FORWARD_DESTINATION_REQUIREDÀ la mise à jour (PUT) : la route effective résultante transfère mais n'a pas de forwardToEmail
400FORWARD_DOMAIN_NOT_VERIFIEDLe 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
404RESOURCE_NOT_FOUNDDestination de transfert introuvable
409FORWARD_DESTINATION_NOT_PENDINGRenvoi demandé pour une destination ayant déjà confirmé ou refusé
409FORWARD_DESTINATION_NO_CONFIRMATION_NEEDEDRenvoi demandé pour une destination sur l'un de vos propres domaines d'envoi vérifiés
410FORWARD_CONFIRMATION_EXPIREDLe lien de confirmation a expiré (7 jours) sans avoir été décidé
409FORWARD_CONFIRMATION_ALREADY_DECIDEDLe lien a été utilisé pour l'autre décision
429FORWARD_CONFIRMATION_RATE_LIMITEDRenvoi demandé trop tôt, ou limite quotidienne de renvoi atteinte

Réponses d'erreur

StatutCodeDescription
400VALIDATION_FAILEDChamps requis manquants, matchType/actions invalides, ou une action terminale combinée à une autre
400INVALID_REQUESTUne route avec cette priority existe déjà pour le domaine, ou le webhookId référencé est introuvable
400PLAN_LIMIT_REACHEDCré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)
403FORBIDDENPermissions insuffisantes
404RESOURCE_NOT_FOUNDDomaine 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

Sur cette page