Skip to main content

Microsoft 365 mailbox

A Microsoft 365 mailbox automation starts a CoderFlow task for each new email in a watched folder. Microsoft Graph pushes notifications through a webhook or Azure Event Hubs; CoderFlow does not poll the mailbox for new mail.

Replies in the same conversation follow up on its task until that task is approved or rejected, or more than 30 days have passed since the conversation's last email. A later reply starts a new task. By default, at most 10 follow-ups reach one task in a rolling 24 hours; further replies are recorded without starting another turn. Administrators can change that limit.

This is a separate, opt-in environment automation. The Outlook add-in lets a person choose an open email and send it to CoderFlow; it does not monitor mailboxes and does not require this connection.

Mailbox access is read-only: Mail.Read. CoderFlow never replies, marks mail read, moves it, tags it or deletes it. Outlook therefore shows no indication that CoderFlow handled a message. Use the automation's History to find its outcome and task. A person replies from Outlook when needed.

Tenant setup​

You need Microsoft Entra and Exchange Online administration access, plus Azure resource administration for Event Hubs delivery.

  1. Register a single-tenant Entra application and create a client secret. Use one app registration per CoderFlow server, including a separate one for a test server.

  2. In Exchange Online PowerShell, create the service principal. Use the Object ID from Enterprise applications, not the app registration's Object ID:

    New-ServicePrincipal -AppId <application-id> -ObjectId <enterprise-application-object-id> -DisplayName "CoderFlow mail"
  3. Define an Exchange management scope containing only the intake mailboxes. Assign the read role to that scope:

    New-ManagementRoleAssignment -App <enterprise-application-object-id> -Role "Application Mail.Read" -CustomResourceScope "CoderFlow intake"

    An administrative unit can be used instead with -RecipientAdministrativeUnitScope.

  4. Do not grant application Mail.Read in Entra. Remove any existing Entra grant: it adds to Exchange RBAC permissions and would bypass the mailbox restriction.

  5. Check an allowed mailbox and an out-of-scope mailbox:

    Test-ServicePrincipalAuthorization -Identity <enterprise-application-object-id> -Resource support@contoso.com

Allow 30 minutes to 2 hours for permission changes to apply. The test command bypasses the cache, so a successful test can precede working mailbox access. See Microsoft's RBAC for Applications setup for defining and testing scopes.

Choose a delivery mode​

Both modes use the same mailbox permissions, filters, limits and task behavior. This integration currently supports the Microsoft public cloud only.

Webhook​

Choose Webhook when Microsoft can reach a public HTTPS address for your CoderFlow server. The reverse proxy must allow /api/webhooks/inbound/*, including Microsoft's validation requests, without requiring a CoderFlow sign-in.

You can expose the webhook-only listener and keep the main application port private. It isolates public routes and ports within the same server process. Configure HTTPS termination at the proxy and use its address as Public base URL.

Optionally restrict inbound connections to Microsoft's notification IP ranges; keep that allowlist current using the link in Microsoft's webhook firewall guidance.

CoderFlow creates the webhook for the connection. Do not create or link a generic webhook yourself. In Automations → Webhooks, it appears as Managed by connection followed by the connection's name. See managed mail webhooks for history and token rotation.

Azure Event Hubs​

Choose Azure Event Hubs when the server can connect outbound to Azure but cannot accept public inbound requests.

  1. Create an Event Hubs namespace and an event hub in your Azure subscription.
  2. Assign Azure Event Hubs Data Sender on the hub to Microsoft Graph Change Tracking. If that service principal is missing, create it in your tenant first. Its application ID is 0bf30f3b-4a52-48df-9a82-234910c4a086; Microsoft's Event Hubs delivery guide includes the creation steps.
  3. Assign Azure Event Hubs Data Receiver on the hub to your CoderFlow app. CoderFlow uses Entra authentication, not SAS keys or connection strings.
  4. Create a consumer group dedicated to this CoderFlow server. $Default is refused. Do not share the hub and consumer group with another server or reader: it could take notifications intended for this server.
  5. Allow outbound port 5671 for AMQP, or 443 for AMQP over WebSockets. CoderFlow falls back automatically. After three silent 5671 attempts across the server process, it uses 443 until the server restarts.
  6. Set the hub's retention to cover the longest outage you expect. After an outage, CoderFlow resumes from saved checkpoints; longer gaps need catch-up.

Add the connection in CoderFlow​

Open Administration → Environments, select the environment, then open Connections. Select Add Connection and the Microsoft 365 type card.

In General, enter Name and an optional Description. Available For is fixed to Automation: the credentials remain on the server and are never injected into task or deployment containers.

FieldWhat to enter
Tenant IDThe tenant's GUID or verified domain, such as contoso.onmicrosoft.com.
Client ID (application ID)The single-tenant app's application GUID.
Client secretThe secret value, not its ID.
DeliveryWebhook or Azure Event Hubs.
Public base URLFor Webhook: a public HTTPS base address, with no credentials, query or fragment. Localhost and private IP addresses are refused.
NamespaceFor Event Hubs: the namespace name, with or without .servicebus.windows.net. The name is 6–50 characters, starts with a letter, ends with a letter or number, and otherwise uses letters, numbers or hyphens.
Event hubThe hub name, 1–256 characters.
Consumer groupThe dedicated group name, 1–50 characters. $Default is not allowed.

Hub and consumer-group names use letters, numbers, periods, hyphens or underscores and start and end with a letter or number.

The secret is stored encrypted and is never shown again. On edit, leave Client secret blank to keep it. If Tenant ID or Client ID (application ID) changes, enter the secret again; a saved secret cannot be reused for a different identity. After a failed save, a typed secret is cleared and the dialog explains whether you must re-enter it or can retain the saved secret.

Test connection​

Select Test connection. Connection checks reports:

CheckSuccessful result
Microsoft Graph tokenMicrosoft Graph token acquired.
Azure Event Hubs token (Event Hubs only)Azure Event Hubs token acquired.
Azure Event Hubs properties (Event Hubs only)The partition count and whether properties were read using AMQP/TLS on port 5671 or AMQP over WebSockets on port 443.

The overall success message is Microsoft 365 connection successful. The test does not read mail, create a subscription, or prove webhook delivery. It also does not verify Graph's Data Sender assignment. Mailbox access and delivery are checked when an automation is enabled.

The notice reads: “A mailbox scope (RBAC for Applications) assigned less than 2 hours ago may not have applied yet. Mailbox access itself is checked when an automation is enabled.” Save the connection after checking it.

Create the email automation​

On the environment's Automations tab, select Add Automation. Under Trigger, choose When an email arrives (Microsoft 365).

FieldWhat to choose
Name, DescriptionA name for the automation and an optional explanation.
ConnectionA Microsoft 365 connection in this environment. If none exists, Add one in Connections opens the connection setup.
MailboxThe SMTP address of a user or shared mailbox covered by the app's Exchange scope.
FolderInbox (the default), or a slash-separated path such as Inbox/Support for mail routed by an Outlook rule. Paths can be up to 512 characters; empty, . and .. segments are refused.
Allowed sendersOptional addresses or @domain entries, up to 100. Enter one per line, or separate them with commas or semicolons. Empty means anyone. Matching ignores case; @contoso.com matches that domain, not its subdomains.
Run TargetCustom instructions or Task template. Deployment, publishing and import targets are unavailable for email.
AgentThe agent and any available model or effort settings for the task.
Run ConfigurationComplete Task Name Template, then Instructions, or Task Template, its parameters and optional Additional Instructions. Email task names are generated from the subject even though the editor requires Task Name Template.

Only one automation can watch the same mailbox and folder on a connection. This trigger is available for environment automations only. It has no schedule, SCM poll or Run Now action; test it by sending an allowed email after delivery is verified.

The default Instructions are:

Work on what the email asks within this environment, or summarize and stop.

Replace them with your intake rules, or select a template. An environment skill can hold shared conventions for handling incoming mail.

Untrusted input and Launch tasks pinned are shown checked and locked for this trigger; neither can be turned off. Leave Enabled off while preparing the automation; turn it on and select Save when ready. Enabling establishes a baseline of existing mail, creates the subscription and verifies delivery. Existing mail in the initial baseline does not start tasks.

Limits​

Limits apply to each automation. The daily limits use rolling 24-hour windows, not a midnight reset.

FieldDefaultRangeWhen reached
Running tasks21–10Email needing a new task waits until capacity is available.
Tasks per day201–100Email needing a new task waits until an earlier launch leaves the 24-hour window.
Follow-ups per task per day101–50Further replies are Recorded only; they do not start a turn or wait to be sent later.

How emails become tasks​

Skipped mail​

CoderFlow avoids duplicate work by tracking message IDs, including the internet message ID. Duplicate notifications do not start another task. It also skips recognized auto-replies and bounces, mail sent by the watched mailbox itself, CoderFlow's own notification email, and senders outside Allowed senders. A message deleted before CoderFlow can read it is skipped.

Sender matching uses the email's From address. An allowlist narrows intake; it does not replace your tenant's mail authentication and anti-spoofing controls.

Waiting mail and replies​

Mail over the new-task caps stays queued; it is not dropped. A reply also waits while its conversation's task is being created. If the existing task is busy, the follow-up is queued until its current turn ends.

A reply starts a new task after approval, rejection, deletion, or a gap of more than 30 days since the last email. It can also start a replacement if the earlier task is no longer available for follow-up. When available, the earlier task's name and link are included as context. Follow-ups keep the same untrusted-input restrictions.

Task files​

The task receives the automation's instructions, the email's sender, recipients, date, subject and readable body, plus these files:

FileContents
email.mdThe complete readable email and attachment inclusion notes.
email-original.htmlThe original HTML body, or email-original.txt for a plain-text body.
email.emlThe original message, when it fits the limits.
Individual attachmentsSupported file attachments, including inline images, with safe filenames.

The size limits match the Outlook add-in: 20 attachments, 50 MiB per file, a 10 MiB body, and 150 MiB total for the body, original message and included attachments. Oversized attachments or an oversized .eml are omitted with a reason; an oversized body prevents processing. Cloud file links are not downloaded. Attached Outlook items, such as attached emails or calendar items, are not extracted as separate files by mailbox intake.

The prompt includes up to 40,000 characters of the readable body; the rest remains in email.md. Hidden HTML elements are omitted from the readable copy, white text that may be hidden is flagged, and remote image links are removed. The original body remains untrusted.

How the task runs​

Tasks and follow-ups run as the automation's creator, with that person's current permissions. New tasks are private, pinned and marked as untrusted input. The creator must retain permission to use automations and create tasks in the environment; follow-ups also require permission to execute tasks. Review the task in CoderFlow, then reply to the sender from Outlook if appropriate.

Moving or deleting mail in Outlook does not remove tasks already started. CoderFlow does not write processing markers back to the mailbox.

Read the status view​

Select History on the automation and find Microsoft 365 mail. Select Refresh to update the status.

Subscription stateMeaning
OffThe automation is disabled. Check for remaining subscription details while cleanup finishes.
No subscriptionAn enabled automation has no subscription status yet.
Creating subscriptionCoderFlow is preparing or creating the subscription.
Verifying deliveryCoderFlow is waiting for Microsoft's validation to arrive.
ActiveDelivery has been verified.
Needs attentionRead the accompanying error and check credentials, scope or delivery settings.
orphanedA subscription is waiting for credentials or expiry before it can be cleaned up.

The view shows Delivery, Subscription ID, Expires, Last renewal, Delivery verified and Last notification. Webhook verification means Graph's validation request reached CoderFlow. Event Hubs verification means Graph's validation message arrived through the hub within 60 seconds. A successful connection test alone does not mean delivery is working.

Catch-up shows Requested, the reason and request time while recovery is pending, or None pending. Last catch-up shows the most recent completed or failed catch-up's time, reason and number of emails added to the queue, with a separate Error: line if it failed. It shows None yet until a result is recorded. Counts appear as No emails added, 1 email added, or, for example, 3 emails added. These count queued emails, not tasks started; check Recent emails for their processing outcomes. A failed attempt can have added some emails before the error, and a catch-up in progress can still show the previous result.

The reason labels are:

Reason shownWhat requested recovery
after the subscription was createdSubscription creation, including recreation after delivery settings change.
after the subscription was recreatedMicrosoft removed the subscription and CoderFlow recreated it.
after missed notificationsMicrosoft reported missed notifications.
daily check (Event Hubs)Renewal in Event Hubs mode without lifecycle delivery.
after the event hub's retention was exceededNotifications may have fallen outside the hub's retention.
after the automation was enabled againThe automation was re-enabled with a saved change position.
after a restartStartup recovery for an enabled mail automation.

For Event Hubs, Event Hubs consumer shows Stopped, Connecting, Connected or Error, plus Transport, Last connected and Last event. It starts when the first automation using the connection is enabled. A connected consumer and verified subscription are separate checks.

Usage shows Running tasks, Tasks today, Waiting and Follow-ups per task per day. Despite its label, Tasks today counts the preceding 24 hours.

Recent emails lists Time, Outcome, Email and Task, with a reason and task link where available. Subjects and senders are visible only to people allowed to configure the automation.

OutcomeMeaning
New taskA new task was created.
Follow-upThe email was delivered to the conversation's task.
Recorded onlyThe follow-up cap was reached; no turn was started.
WaitingThe email is waiting for capacity, its conversation's task launch, or a retry. It also covers replies with the reason Queued until the task's current turn ends, Waiting for the conversation's task approval, or automation or environment is disabled.
SkippedNo task or follow-up was needed; the reason explains the filter or duplicate.
ErrorProcessing failed; inspect the reason before deciding what to do next.

Recovery and catch-up​

Normal delivery is push-based. CoderFlow renews subscriptions about once a day; renewal is not a poll for mail. Catch-up runs only when recovery is requested for subscription creation, subscription removal, missed notifications, the daily Event Hubs check, exceeded Event Hubs retention, an automation being re-enabled, or a server restart. It does not poll the folder between these requests.

Catch-up reads the folder's changes since the last saved position and queues only new mail that has not already been handled. It ignores deleted entries and mail before the initial baseline, and stays within the 45-day duplicate-memory window. Duplicate tracking prevents overlap with push delivery from starting the same work again. Creation catch-up closes the gap between the initial baseline and subscription creation.

Large backlogs are processed in slices, with progress saved so later slices can resume. The new-task limits still apply: adding mail to the queue does not bypass Running tasks or Tasks per day, and excess mail waits. Failed catch-ups retain their request and retry with increasing delays; Last catch-up shows the error.

If Microsoft expires the saved change position, CoderFlow rebuilds it and considers mail received since the start of the last successful catch-up, with a two-minute overlap. If no successful catch-up is recorded, it uses the initial baseline. Recovery never goes before that baseline or beyond the 45-day duplicate memory; a small safety margin keeps it inside that window. An older email outside this window is not queued by catch-up.

At startup, CoderFlow checks each enabled mail automation's subscription, recreates it if Microsoft reports it missing, and requests catch-up. A failed subscription check is retried. Disabled automations do not start catch-ups.

In the default Event Hubs configuration, a daily catch-up follows renewal because lifecycle events are not delivered through the hub. This is the routine recovery check in that mode; other catch-ups require one of the events above.

Microsoft lists message-notification latency as under one minute on average and up to three minutes; task startup, queue limits and retries add time. See Microsoft's subscription latency table. Webhook delivery retries can continue for up to four hours, including delayed retries after the server returns. See webhook retry behavior.

An Event Hubs setup without lifecycle delivery may not discover missed mail until the daily catch-up. Recovery is not immediate: allow time for reconnects, Microsoft throttling and the task limits. Mail deleted before it can be fetched cannot become a task.

Event Hubs lifecycle setting​

Set CODERFLOW_M365_EVENTHUB_LIFECYCLE in the CoderFlow server process environment:

ValueBehavior
none (default)No lifecycle notification URL for Event Hubs. A daily catch-up follows renewal.
eventhubRequests lifecycle notifications through the event hub, so missed or removed subscriptions can trigger recovery without the daily fallback.

Microsoft support for an Event Hubs lifecycle notification URL is pending confirmation. Keep none unless support has been confirmed for your deployment. This setting does not change webhook mode.

Disable mail before renaming an environment​

An environment cannot be renamed while it has an enabled Microsoft 365 mail automation, a subscription record (including one pending deletion), or a managed mail webhook.

Disable all its email automations, then wait for subscription removal and managed-webhook cleanup. Use History → Refresh until no subscription remains; the disabled view says “The automation is disabled, so there is no subscription. Enabling it creates one.” An Off badge alone is not proof that cleanup has finished. If cleanup fails, correct the reported access or connection problem and allow the retry to complete before renaming.

The refusal begins “Microsoft 365 mail is active in this environment”, lists the blockers, and ends “Disable the Microsoft 365 mail automations and wait until their status shows no subscription, then rename.” While a rename is in progress, enabling mail or saving a Microsoft 365 connection is refused with “Microsoft 365 mail cannot be changed while this environment is being reset or renamed.”

Security and data handling​

  • Untrusted input — Always on, including follow-ups. Email is framed as information from its sender. CoderFlow MCP tools remain read-only, apart from renaming the task itself. This does not remove the environment's repository, mount or network access; give the intake environment only what it needs.
  • Allowed senders — Restrict who can start work, and retain tenant anti-spoofing controls. Leaving this empty accepts mail from anyone.
  • Limits — Bound task launches and reply loops. Start with the defaults and review usage before raising them.

Use an automation owner with only the permissions needed for intake. CoderFlow rechecks that owner's access before launching work or sending a follow-up. The mailbox integration has no outbound-mail permission or reply action.

The client secret is encrypted on the server. Microsoft 365 connection credentials and subscription authentication secrets never reach task containers. Notifications are checked against the subscription, tenant and a subscription-specific secret before they enter the durable queue. Event Hubs roles separate Graph's sending access from CoderFlow's receiving access.

Email content goes to the task's configured AI provider as part of its instructions and files. Subjects, the template title and the start of the automation's instructions can also go to the server's Utility AI to generate task names; the email body is not sent for naming. Ensure the watched mailboxes are appropriate for that data flow.

Troubleshooting​

Connection checks fail​

Use the message in Connection checks to identify the next step:

MessageAction
The client secret is invalid. Enter the secret value, not the secret ID.Enter the app's secret value.
The client secret has expired. Create a new secret and enter its value.Create and save a replacement secret.
The Microsoft tenant was not found. Check the tenant ID or verified domain.Correct Tenant ID.
The app was not found in this tenant. Check the tenant ID and client ID.Check that the app belongs to the selected tenant.
Enter the client secret. A saved secret can only be used with its saved tenant and client and a valid credential binding.Re-enter the secret for the current tenant and application.
Event Hubs access was denied. Give the CoderFlow app Azure Event Hubs Data Receiver on the hub.Assign the receiving role to the CoderFlow app on the configured hub.
The Event Hubs namespace or event hub was not found. Check the namespace and event hub name.Check Namespace and Event hub.
Event Hubs could not be reached. Allow outbound AMQP on port 5671 or WebSockets on port 443.Check outbound firewall, DNS and proxy rules.
The Microsoft 365 connection test timed out. Try again and check outbound network access.Restore outbound access and retry Test connection.
Microsoft authentication failed. Check the tenant, app credentials and outbound network access.Check credentials and access to Microsoft's sign-in and Graph endpoints.

Delivery is not verified​

“Graph's validation message did not arrive through the event hub within 60 seconds” means CoderFlow did not observe Graph's validation through the configured hub. Check the Microsoft Graph Change Tracking Data Sender assignment, the hub, the dedicated consumer group, and Event Hubs consumer status. A token or properties test does not prove Graph can send.

“Graph created the subscription without a webhook validation handshake” means the webhook handshake was not observed. Check Public base URL, public HTTPS, and proxy access to /api/webhooks/inbound/* on the main server or webhook-only listener.

“Another server uses this app registration” means a conflicting subscription could not be matched to this server's delivery URL. Give each server its own app registration; do not reuse production's app on a test server.

Mailbox access or folder lookup fails​

“Microsoft 365 denied access to the mailbox (check RBAC for Applications)” calls for checking the Exchange service principal, Application Mail.Read assignment and mailbox scope with Test-ServicePrincipalAuthorization. Allow up to two hours after changing the scope; do not fix this by granting tenant-wide Entra Mail.Read.

For “Mailbox not found”, check Mailbox. For “Configured mail folder was not found” or “Mail folder path is ambiguous”, check Folder and use an unambiguous path such as Inbox/Support.

“Another automation already watches this mail folder” means the resolved folder is already in use. Keep one watcher for that mailbox and folder on the connection.

Port 5671 does not respond​

“Port 5671 did not respond; using WebSockets on 443. Restart the server to retry port 5671.” explains the automatic fallback after three silent native attempts. If the consumer is Connected over 443, it can continue receiving mail. Restore outbound 5671 access before restarting if you want to use that transport again.

Mail arrived but no task started​

Check Delivery verified, Recent emails and Usage. Mail may be Skipped, Waiting, a Follow-up on an existing task, or Recorded only after the follow-up cap. The initial baseline deliberately ignores existing mail. Check the automation creator's current access and the selected folder before resending; duplicate tracking prevents a second task for the same message.

For an environment rename refusal, follow Disable mail before renaming an environment.