Mail Event
Creates a Microsoft Graph change-notification subscription on publish, renews it before it expires, and starts one run per notification.
Start a run when a message is created, updated or deleted in an Outlook / Microsoft 365 mailbox.
Connection
- Required
- Yes — the node will not save without one
- Auth type
- OAuth 2.0
- Providers
- Outlook / Microsoft 365
- Secret shape
- the Microsoft {client_id, client_secret, refresh_token} triple
- Config it needs
- tenant
- Resolved by
- config.connection_id, else node.connection_id
- Note
- The refresh token needs read access to what it subscribes to — Mail.Read for messages, Calendars.Read for events, Contacts.Read for contacts. Graph refuses a subscription for a resource the token cannot read. Publishing also needs MANTLE_APP_PUBLIC_BASE_URL set to an https URL Graph can reach and that answers its validation probe within ten seconds.
Configuration
2 fields, none required. A dotted path is a nested object and name[] an array of objects — the editor renders the same tree.
| Field | Type | Required | Default | Constraints | Example |
|---|---|---|---|---|---|
resource The Graph resource to watch, e.g. me/mailFolders('inbox')/messages for the inbox, me/messages for the whole mailbox, or me/events / me/contacts for the calendar and contacts. Leave it blank for the inbox. | string | No | me/mailFolders('inbox')/messages | — | me/mailFolders('inbox')/messages |
change_types Which changes start a run. 'created' alone means new mail; adding 'updated' also fires when a message is read, flagged, moved or categorised, which is far noisier than most workflows expect. | array | No | ["created"] | 1–3 characters; array of string | — |
Example configuration
Every value below is the contract’s own example or default — nothing invented.
{
"change_types": [
"created"
],
"resource": "me/mailFolders('inbox')/messages"
}Output
One shape.
graph notification
One Microsoft Graph change notification, flattened. Graph sends the id of what changed, not its content.
Extra keys beyond the ones listed can appear.
| Field | Type | Example |
|---|---|---|
notification_id Graph's own id for this notification, and the run's idempotency key when it is present. Graph retries a delivery for up to four hours, reusing it, so a retry joins the run it already started. | string | lsgTZMr9KwAAA |
change_type What happened: created, updated or deleted. Branch on this when the trigger subscribes to more than one. | string | created |
resource The Graph path of the thing that changed, as Graph writes it. | string | Users/8ee44408-0679-472c-bc2a-692812af3437/Messages/AAMkAGVmMDEz |
resource_id Id of the message (or event, or contact). This is a BASIC notification: Graph sends the id, not the mail — read it back with the Outlook nodes, and expect a 404 when change_type is deleted. | string | AAMkAGVmMDEz |
resource_type Graph's type marker for it, e.g. #Microsoft.Graph.Message. | string | #Microsoft.Graph.Message |
etag The version of the resource this notification is about. It changes with the resource, which is what makes an update distinguishable from the update before it. | string | — |
subscription_id The Graph subscription that delivered this — constant while the workflow stays published, across renewals. | string | 7f105c7d-2dc5-4530-97cd-4e7ae6534c07 |
subscription_expires_at When that subscription expires, as Graph reports it. The renewal sweep extends it well before this; it is here for diagnosis. | string | — |
tenant_id The Microsoft 365 directory the change happened in — NOT the Mantle tenant. | string | — |
payload Graph's notification exactly as it arrived, minus clientState, which is the shared secret the delivery was verified against. | object | — |
{
"change_type": "created",
"etag": "W/\"CQAAABYAAADkrWGo7bouTKlsgTZMr9KwAAAUWRHf\"",
"notification_id": "lsgTZMr9KwAAA",
"payload": {
"changeType": "created",
"id": "lsgTZMr9KwAAA",
"resource": "Users/8ee44408-0679-472c-bc2a-692812af3437/Messages/AAMkAGVmMDEz",
"resourceData": {
"@odata.type": "#Microsoft.Graph.Message",
"id": "AAMkAGVmMDEz"
},
"subscriptionId": "7f105c7d-2dc5-4530-97cd-4e7ae6534c07"
},
"resource": "Users/8ee44408-0679-472c-bc2a-692812af3437/Messages/AAMkAGVmMDEz",
"resource_id": "AAMkAGVmMDEz",
"resource_type": "#Microsoft.Graph.Message",
"subscription_expires_at": "2026-09-17T09:00:00Z",
"subscription_id": "7f105c7d-2dc5-4530-97cd-4e7ae6534c07",
"tenant_id": "84bd8158-6d4d-4958-8b9f-9d6445542f95"
}Notes
- Publishing creates the subscription in Microsoft Graph; unpublishing, disabling or archiving deletes it. A workflow that is off is off at Graph too.
- A Graph subscription on Outlook mail expires after at most seven days. Mantle renews it in place well before that, so the id and the shared secret survive; nothing has to be re-authorised.
- This is a BASIC notification: Graph sends the id of what changed, not the message. Follow the trigger with an Outlook read node.
- Graph refuses a second subscription with the same resource and change types on the same mailbox with a 409, so two published workflows cannot watch the same folder for the same change through one connection.
- A delivery is authenticated by the clientState Graph echoes back, not by a signature — Graph does not sign notifications. That value is a secret and is stripped from the emitted payload.
- Graph gives a delivery three seconds before it counts as slow and retries for up to four hours; every retry carries the same notification id, so a retry joins the run it already started.
See Mail Event run in a workflow.
In a technical demo we add the Outlook / Microsoft 365 connection, drop the node on the canvas and let Workflow Health pre-flight it before the first real run.