flowchart TD
%% One-time setup for hidden Exchange mailbox + Graph webhooks
subgraph Admin["Administrator"]
A1["Create Shared Mailbox: help@my-domain.com in Exchange Online"]
A2["Confirm external senders allowed"]
A3["Register Entra ID App
for Microsoft Graph"]
A4["Grant Graph permissions
(Application: Mail.Read, Mail.ReadWrite)
Grant admin consent"]
end
subgraph Webhook["Webhook App (Azure Function / App Service)"]
W1["Deploy HTTP endpoint"]
W2["Handle Graph validation (validationToken)"]
W3["Implement processing: fetch message, save attachments, call Support API"]
W4["Auth: Managed Identity or client secret in Key Vault"]
end
subgraph Graph["Microsoft Graph"]
G1["Create subscription on:
/users/{sharedMailboxId}/mailFolders('Inbox')/messages"]
end
subgraph SecOps["Security & Governance"]
S1["Optional transport rules (limit allowed senders)"]
S2["Defender for Office 365 policies"]
end
Admin --> A1 --> A2 --> A3 --> A4
A4 --> W4
W4 --> W1 --> W2 --> G1
G1 --> W3
W3 --> Support[(Support System API)]
Admin --> S1
Admin --> S2
sequenceDiagram
autonumber
actor S as External Sender
participant EOP as Exchange Online Protection/Defender
participant XO as Exchange Online
Shared Mailbox (help@)
participant G as Microsoft Graph
participant A as Entra App
(App Registration)
participant W as Webhook
(Azure Function/App Service)
participant KV as Key Vault / Managed Identity
participant ST as Azure Blob Storage
participant SYS as Support System API
S->>EOP: SMTP message to help@my-domain.com
EOP->>XO: Deliver if passed (AV/AS/phish)
Note right of XO: New message created in Inbox
rect rgb(245,245,245)
Note over G,W: Pre-existing Graph subscription
/users/{sharedMailboxId}/mailFolders('Inbox')/messages
G-->>W: Change notification (message created)
W-->>G: (initial validation was done at subscription create)
end
W->>KV: Acquire creds (secret/cert) or use Managed Identity
W->>G: GET /messages/{id}?$expand=attachments (as App A)
G-->>W: Message metadata, body, attachments
alt has attachments
loop each attachment
W->>ST: Upload attachment
ST-->>W: Return SAS URL
end
end
W->>SYS: POST /tickets {from,subject,bodyHtml,attachmentUrls[],internetMessageId}
SYS-->>W: 201 Created (ticketId)
par post-processing
W->>G: MOVE /messages/{id} -> "Processed" (or DELETE)
and
W->>G: PATCH /messages/{id} {singleValueExtendedProperties: ticketId}
end
W-->>G: 202 Accepted (notification handled)