Prompt file imported from migoamigoea-star/ioi-docs-uploads (
.github/prompts/email-notification-workflow.prompt.md). Fill in{{CONTENT}},{{DEEP_LINK}},{{ACTION_LABEL}},{{ACTION_BUTTON}}before use. Copyright stays with the author.
Email Notification Workflow — End-to-End Execution
Goal: Live email notification system replacing Domino @MailSend for a specific form — HTML templates built, Power Automate flows deployed via FlowStudio MCP, deep links wired, Domino parity verified.
Paste the entire block for the current phase into Copilot Chat. Complete one phase before moving to the next.
Phase 1: Audit Domino Email Patterns
Phase 1 → @domino-migration-agent to audit @MailSend calls for {FormCode} form — extract recipients, CC/BCC, conditions, subject/body patterns from analysis/workflow-analysis.md
What to hand off: An audit file at docs/email-notifications/{FormCode}-email-audit.md with trigger stage, recipients, conditions, subject template, body template.
Phase 2: Design Email Type
Phase 2 → From the audit, decide which email types (E1-E8) this form needs — submitted, approved, rejected, returned, escalated, delegated, completed, reminder — map each Domino @MailSend to its type
Email Type Catalog
| # | Type | Trigger | Recipient | CC | Condition |
|---|---|---|---|---|---|
| E1 | Submitted | Draft → Submitted | Approver | Requestor | Always on submit |
| E2 | Approved | Status = "Accepted" | Requestor + Next Approver | Dept Head | Status changed to accepted |
| E3 | Rejected | Status = "Rejected" | Requestor | — | Status changed to rejected |
| E4 | Returned | Status = "Returned" | Requestor | — | Status changed to returned |
| E5 | Escalated | Due date exceeded | Manager | Original Approver | Past due with pending status |
| E6 | Delegated | Delegation flag set | Delegate | Original Approver | Delegation enabled |
| E7 | Completed | Final stage reached | Requestor | Initiator | Status = "Completed" |
| E8 | Reminder | Pending > N days | Approver | Manager | Overdue threshold |
Phase 3: Build HTML Email Templates
Phase 3 → Build HTML email templates for the types identified in Phase 2:
1. Create/update src/lib/email-templates/base-email.ts with the IOI branded HTML shell
2. Create per-type template files (submitted.ts, approved.ts, rejected.ts, etc.)
3. Use buildIoiDeepLink() for deep link buttons
4. Wire each template into notification-service.ts
HTML template reference and per-type variable table are in the reference section at the bottom of this file.
Phase 4: FlowStudio MCP — Discover Existing Flows
Phase 4 → FlowStudio MCP: list_live_flows to check if any existing flow can be bumped or reused for this form's email notifications
Search by form code:
results = mcp("list_live_flows", environmentName=ENV)
matches = [f for f in results["flows"] if "{FormCode}" in f["displayName"]]
Decision: matches found → bump via update_live_flow | no matches → Phase 5 build from scratch
Also get connections:
mcp("list_live_connections", environmentName=ENV)
Phase 5: FlowStudio MCP — Build or Update the Flow
Phase 5 → FlowStudio MCP: create_live_flow or update_live_flow to build the flow — SharePoint trigger → condition on Status → send email via Office 365 Outlook
Build flow JSON with:
- Trigger: "When an item is created or modified" on MainDB_{Dept} with condition
@equals(Status, 'Submitted') - Action: "Send an email (V2)" via shared_office365 → To: ApproverEmail, Subject:
[IOI] {FormCode} - {Title}, Body: (HTML), Importance: High - Multi-stage: Switch on Status → Submitted→HOD, HOD_Approved→COO/Director (conditional on isPCN)
mcp("create_live_flow", environmentName=ENV, flowPayload=json.dumps(flow_json))
Phase 6: Wire Deep Links
Phase 6 → Wire deep links via buildIoiDeepLink({ formCode, itemId, action }) — every email gets a View or Approve button back to the Power Apps app
Phase 7: Test Via FlowStudio MCP
Phase 7 → FlowStudio MCP: trigger_live_flow to test → get_live_flow_runs to verify → get_live_flow_run_error if failed. Then check: recipient parity vs Domino, HTML rendering, deep link navigation, mobile responsiveness
mcp("trigger_live_flow", environmentName=ENV, flowName=FLOW_ID)
runs = mcp("get_live_flow_runs", environmentName=ENV, flowName=FLOW_ID)
FlowStudio MCP Tool Reference
| Task | Tool | Key Params |
|---|---|---|
| List all flows | list_live_flows |
environmentName |
| Get flow definition | get_live_flow |
environmentName, flowName |
| Create new flow | create_live_flow |
environmentName, flowPayload |
| Update existing flow | update_live_flow |
environmentName, flowName, flowPayload |
| List connections | list_live_connections |
environmentName |
| Trigger a flow | trigger_live_flow |
environmentName, flowName |
| Get run history | get_live_flow_runs |
environmentName, flowName |
| Get run errors | get_live_flow_run_error |
environmentName, flowName, runName |
Output Files
| Artifact | Location |
|---|---|
| Email audit per form | docs/email-notifications/{formCode}-email-audit.md |
| HTML email templates | src/lib/email-templates/ |
| Graph email service | src/services/graph-email-service.ts |
| Power Automate flows | Provisioned via FlowStudio MCP |
| Deep link helper | src/hooks/use-app-params.ts (existing) |
Reference: HTML Email Shell & Per-Type Variables
Base HTML Shell (base-email.ts)
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"></head>
<body style="margin:0;padding:0;font-family:'Segoe UI',Arial,sans-serif;background:#f4f5f7;">
<table role="presentation" width="100%" cellpadding="0" cellspacing="0">
<tr>
<td align="center" style="padding:20px 10px;">
<table role="presentation" width="600" cellpadding="0" cellspacing="0" style="background:#ffffff;border-radius:8px;box-shadow:0 2px 8px rgba(0,0,0,0.08);">
<tr>
<td style="padding:32px 32px 16px;background:linear-gradient(135deg,#1a365d,#2c5282);border-radius:8px 8px 0 0;">
<h1 style="margin:0;color:#ffffff;font-size:20px;">IOI Enterprise Platform</h1>
<p style="margin:4px 0 0;color:#90cdf4;font-size:13px;">Notification from the Enterprise Application Framework</p>
</td>
</tr>
<tr><td style="padding:24px 32px;color:#2d3748;font-size:14px;line-height:1.6;">{{CONTENT}}</td></tr>
<tr>
<td style="padding:0 32px 24px;text-align:center;">
<a href="{{DEEP_LINK}}" style="display:inline-block;padding:12px 32px;background:#2b6cb0;color:#fff;text-decoration:none;border-radius:6px;font-size:14px;font-weight:600;">{{ACTION_LABEL}}</a>
</td>
</tr>
<tr>
<td style="padding:16px 32px;background:#f7fafc;border-radius:0 0 8px 8px;border-top:1px solid #e2e8f0;">
<p style="margin:0;color:#718096;font-size:12px;">This is an automated notification. Please do not reply directly.</p>
<p style="margin:4px 0 0;color:#a0aec0;font-size:11px;">IOI Group © 2026 • Powered by Microsoft Power Platform</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
Per-Type Subject, Button & Action
| Type | Subject | Action Label | Deep Link Action |
|---|---|---|---|
| Submitted | [IOI] Action Required: {FC} - {title} |
Review & Approve | approve |
| Approved | [IOI] {FC} - {title} - Approved |
View Submission | view |
| Rejected | [IOI] {FC} - {title} - Rejected |
View Details | view |
| Returned | [IOI] {FC} - {title} - Returned |
Revise & Resubmit | edit |
| Escalated | [IOI] ESCALATED: {FC} - {title} |
Take Action | approve |
| Delegated | [IOI] Delegated: {FC} - {title} |
Review | approve |
| Completed | [IOI] {FC} - {title} - Completed |
View Details | view |
| Reminder | [IOI] REMINDER: {FC} - {title} pending |
Approve Now | approve |
Architecture Options
Choose one based on your use case:
| Approach | Best For | How It Works |
|---|---|---|
| Power Automate Flow | Approval workflows triggered by SharePoint list changes | Triggered when an item is created/modified → Condition on status column → Send email via Office 365 Outlook connector |
| TypeScript Service + Graph API | Inline notifications from the Power Apps code-first app | Call Microsoft Graph API directly from the app for user-initiated notifications (e.g., "Send to Approver" button) |
| Hybrid | Complex routing with app-level actions | Power Automate handles approval-state emails; TS service handles ad-hoc notifications |
For IOI Platform, prefer Power Automate flows triggered by SharePoint list changes — this matches how Domino agents fired on state transitions.
Phase 1: Audit Existing Domino Email Patterns
Invoke @domino-migration-agent to analyze:
-
For each form, read the workflow analysis in
analysis/workflow-analysis.mdand extract:@MailSend(...)calls at each workflow stage- Recipients (who gets notified at each stage)
- CC/BCC patterns
- Conditions that gate email sending (e.g.,
@If(isPCN=1; ...)) - Email subject and body patterns (computed from Domino fields)
-
Output to
docs/email-notifications/{formCode}-email-audit.mdwith:- Trigger stage, recipients, conditions, subject template, body template
Phase 2: Design Email Type Catalog
Design a catalog of email notification types used across the app. Each type has a trigger, content template, and condition rule set.
Email Type Catalog
| # | Email Type | Trigger | Primary Recipient | CC | Condition |
|---|---|---|---|---|---|
| E1 | Submitted | Form submitted (Draft → Submitted) | Approver | Requestor | Always on submit |
| E2 | Approved | HOD/COO/Director approves | Requestor + Next Approver | Dept Head | Status = "Accepted" |
| E3 | Rejected | Any approver rejects | Requestor | — | Status = "Rejected" |
| E4 | Returned | Approver returns for revisions | Requestor | — | Status = "Returned" |
| E5 | Escalated | SLA threshold breached | Manager/Escalation | Original Approver | Due date exceeded |
| E6 | Delegated | Approver delegates | Delegate | Original Approver | Delegation flag set |
| E7 | Completed | Final stage reached | Requestor | Initiator | Status = "Completed" |
| E8 | Reminder | Pending approval > N days | Approver | Manager | Pending duration > threshold |
Trigger to Power Automate Mapping
| Domino Pattern | Power Automate Equivalent |
|---|---|
@MailSend(recipient; subject; body) |
Trigger: "When an item is created or modified" + Condition on CurrentAction/Status → "Send an email (V2)" |
@MailSend(depthead; "Subject"; body) |
Condition: @equals(triggerOutputs()?['body/Status'], 'Submitted') → Send email to field depthead email |
@If(isPCN=1; @MailSend(COO); @MailSend(Director)) |
Condition branch: @equals(triggerOutputs()?['body/isPCN'], '1') → Send to COO field OR Director field |
@DialogBox("EnterComments1") → then mail |
Power Apps: Collect comments in form → set Status → trigger Flow |
Phase 3: Design HTML Email Templates
Template Architecture
src/
lib/
email-templates/
base-email.ts # Base HTML wrapper (branding, footer, responsive shell)
submitted.ts # E1: Submitted notification
approved.ts # E2: Approved notification
rejected.ts # E3: Rejected notification
returned.ts # E4: Returned for revision
escalated.ts # E5: Escalated notification
delegated.ts # E6: Delegated notification
completed.ts # E7: Completed notification
reminder.ts # E8: Pending approval reminder
index.ts # Barrel export
email-templates.ts # Existing file — refactor to call new templates
HTML Email Shell (base-email.ts)
Every email must include:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body style="margin:0;padding:0;font-family:'Segoe UI',Arial,sans-serif;background:#f4f5f7;">
<table role="presentation" width="100%" cellpadding="0" cellspacing="0">
<tr>
<td align="center" style="padding:20px 10px;">
<table role="presentation" width="600" cellpadding="0" cellspacing="0" style="background:#ffffff;border-radius:8px;box-shadow:0 2px 8px rgba(0,0,0,0.08);">
<!-- Header: IOI Branding -->
<tr>
<td style="padding:32px 32px 16px;background:linear-gradient(135deg,#1a365d,#2c5282);border-radius:8px 8px 0 0;">
<h1 style="margin:0;color:#ffffff;font-size:20px;font-weight:600;">
IOI Enterprise Platform
</h1>
<p style="margin:4px 0 0;color:#90cdf4;font-size:13px;">
Notification from the Enterprise Application Framework
</p>
</td>
</tr>
<!-- Body: {{CONTENT}} -->
<tr>
<td style="padding:24px 32px;color:#2d3748;font-size:14px;line-height:1.6;">
{{CONTENT}}
</td>
</tr>
<!-- Action Button: {{ACTION_BUTTON}} -->
<tr>
<td style="padding:0 32px 24px;text-align:center;">
<a href="{{DEEP_LINK}}" style="display:inline-block;padding:12px 32px;background:#2b6cb0;color:#ffffff;text-decoration:none;border-radius:6px;font-size:14px;font-weight:600;">
{{ACTION_LABEL}}
</a>
</td>
</tr>
<!-- Footer -->
<tr>
<td style="padding:16px 32px;background:#f7fafc;border-radius:0 0 8px 8px;border-top:1px solid #e2e8f0;">
<p style="margin:0;color:#718096;font-size:12px;">
This is an automated notification from the IOI Enterprise Platform.
Please do not reply directly to this email.
</p>
<p style="margin:4px 0 0;color:#a0aec0;font-size:11px;">
IOI Group © 2026 • Powered by Microsoft Power Platform
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
Template Variables Per Email Type
| Email Type | Subject Pattern | Content Block | Action Button |
|---|---|---|---|
| Submitted | [IOI] Action Required: {formCode} - {title} |
Shows requester, form, submitted date, priority | "Review & Approve" → deep link |
| Approved | [IOI] {formCode} - {title} - Approved |
Shows approver, approval level, comments, next steps | "View Submission" → detail link |
| Rejected | [IOI] {formCode} - {title} - Rejected |
Shows rejector, reason, re-submission guidance | "View Details" → detail link |
| Returned | [IOI] {formCode} - {title} - Returned for Revision |
Shows reviewer, comments, what to revise, resubmit guidance | "Revise & Resubmit" → edit link |
| Escalated | [IOI] ESCALATED: {formCode} - {title} |
Shows original approver, days pending, SLA info | "Take Action" → approve link |
| Delegated | [IOI] Delegated: {formCode} - {title} |
Shows delegator, delegate, delegation duration | "Review" → approve link |
| Completed | [IOI] {formCode} - {title} - Completed |
Shows final status, completed date, summary | "View Details" → detail link |
| Reminder | [IOI] REMINDER: {formCode} - {title} pending |
Shows days pending, original submission, urgency | "Approve Now" → approve link |
Deep Link Strategy
Emails must contain deep links back to the Power Apps app:
https://apps.powerapps.com/play/e/{envId}/a/{appId}?formCode={FC}&itemId={id}&action={view|approve|edit}
Construct via buildIoiDeepLink() from @/hooks/use-app-params.
Phase 4: Flow Discovery — Check Existing Power Automate Flows
Before building anything new, use the FlowStudio MCP server to discover existing flows that can be reused or bumped.
4a. Connect to FlowStudio MCP
Requires a FlowStudio MCP subscription. Set up the helper:
import json, urllib.request
MCP_URL = "https://mcp.flowstudio.app/mcp"
MCP_TOKEN = "<YOUR_JWT_TOKEN>" # stored securely, never hardcoded
def mcp(tool, **kwargs):
payload = json.dumps({"jsonrpc": "2.0", "id": 1, "method": "tools/call",
"params": {"name": tool, "arguments": kwargs}}).encode()
req = urllib.request.Request(MCP_URL, data=payload,
headers={"x-api-key": MCP_TOKEN, "Content-Type": "application/json",
"User-Agent": "FlowStudio-MCP/1.0"})
resp = urllib.request.urlopen(req, timeout=120)
raw = json.loads(resp.read())
return json.loads(raw["result"]["content"][0]["text"])
ENV = "<your-power-platform-environment-id>"
4b. List All Existing Flows
# Discover ALL flows in the environment
results = mcp("list_live_flows", environmentName=ENV)
# Search for flows related to email notifications
email_flows = [
f for f in results["flows"]
if any(kw in f["displayName"].lower()
for kw in ["email", "mail", "notif", "approv", "ioi", f"{formCode}".lower()])
]
for f in email_flows:
print(f" • {f['displayName']} (ID: {f['id']}) State: {f.get('state','?')}")
4c. Decide: Bump, Clone, or Build New
| Scenario | Action | FlowStudio MCP Tool |
|---|---|---|
| Flow exists and matches spec (same status trigger, same send logic) | Bump — update actions/conditions | update_live_flow |
| Flow exists but needs different status triggers | Clone + modify — copy definition, change trigger conditions | get_live_flow → edit JSON → create_live_flow |
| No flow exists for this form/status | Build new from scratch | create_live_flow |
Bump example — check an existing flow's definition:
# Inspect a flow that already exists
flow_id = email_flows[0]["id"]
defn = mcp("get_live_flow", environmentName=ENV, flowName=flow_id)
# Print its trigger and actions summary
props = defn["properties"]
print(f"Trigger: {props.get('trigger','?')}")
for action_name, action in props.get("actions", {}).items():
print(f" Action '{action_name}': {action.get('type')} → {action.get('inputs',{}).get('host',{}).get('connectionName','?')}")
4d. Obtain Connection References
Before building or modifying, get live connections:
connections = mcp("list_live_connections", environmentName=ENV)
for conn in connections.get("connections", []):
print(f" • {conn['name']} ({conn.get('connectorName','?')})")
Key connectors needed: shared_sharepointonline (SharePoint trigger), shared_office365 (Office 365 Outlook send).
4e. Get Dynamic Schema for SharePoint Trigger
For the form/dept you're targeting, fetch the expected trigger schema:
# Use tool_search to find the right tool for dynamic properties
tools = mcp("tool_search", query="get_live_dynamic_properties")
# Or call directly:
schema = mcp("get_live_dynamic_properties",
environmentName=ENV,
connectorName="shared_sharepointonline",
operationId="OnNewOrUpdatedFile")
Phase 5: Build the Power Automate Flows (via FlowStudio MCP)
For each email type (E1-E8), build or update the flow using FlowStudio MCP tools.
5a. Build Flow Definition JSON Structure
Each flow must have:
{
"properties": {
"displayName": "IOI - {Dept} - {EmailType} - {FormCode}",
"definition": {
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
"triggers": {
"When_an_item_is_created_or_modified": {
"type": "ApiConnectionWebhook",
"inputs": {
"host": {
"connectionName": "shared_sharepointonline"
},
"body": {
"dataset": "https://ioioi.sharepoint.com/sites/ioi-portal-{dept}",
"table": "MainDB_{Dept}",
"triggerCondition": "@equals(triggerOutputs()?['body/Status'], 'Submitted')"
}
}
}
},
"actions": {
"Send_an_email": {
"type": "ApiConnection",
"inputs": {
"host": {
"connectionName": "shared_office365"
},
"method": "post",
"path": "/v2/Mail",
"body": {
"to": "@{triggerOutputs()?['body/ApproverEmail']}",
"subject": "[IOI] @{triggerOutputs()?['body/FormCode']} - @{triggerOutputs()?['body/Title']} - Action Required",
"body": "<HTML template content>",
"importance": "High"
}
}
}
}
},
"connectionReferences": {
"shared_sharepointonline": { "connectionName": "shared_sharepointonline" },
"shared_office365": { "connectionName": "shared_office365" }
}
}
}
5b. Create or Update the Flow
flow_payload = { ... } # JSON from step 5a
if FLOW_ID:
# BUMP existing flow
result = mcp("update_live_flow",
environmentName=ENV,
flowName=FLOW_ID,
flowPayload=json.dumps(flow_payload))
print(f"Updated flow: {flow_payload['properties']['displayName']}")
else:
# CREATE new flow
result = mcp("create_live_flow",
environmentName=ENV,
flowPayload=json.dumps(flow_payload))
print(f"Created flow: {result.get('name','?')}")
5c. Flow Templates by Email Type
Template: Approval Status Email (E1/E2)
Trigger: When an item is created or modified (SharePoint - MainDB_{Dept})
→ Trigger condition: @equals(triggerOutputs()?['body/Status'], 'Submitted')
Action: Condition - Has CC?
→ IF: @equals(triggerOutputs()?['body/Level'], '2')
→ True: Send email to ApproverEmail + CC ManagerEmail
→ False: Send email to ApproverEmail only
Action: Send an email (V2) [Office 365 Outlook]
→ Importance: High
→ Body: (HTML from Phase 3 template with deep link)
Template: Multi-Stage Approval Routing (E2-E4)
Trigger: When an item is modified (SharePoint)
→ Trigger condition: @or(
@equals(triggerOutputs()?['body/Status'], 'Submitted'),
@equals(triggerOutputs()?['body/Status'], 'HOD_Approved')
)
Switch(Status):
Case 'Submitted':
→ Send email to HOD email field
Case 'HOD_Approved':
→ Condition: isPCN == '1'
→ True: Send email to COO email field
→ False: Send email to Director email field
Case 'COO_Approved':
→ Send "Completed" to requestor email field
Default:
→ Send "Rejected" to requestor email field
Template: Escalation Timer (E5)
Trigger: When an item is modified (SharePoint)
→ Trigger condition: @equals(triggerOutputs()?['body/Status'], 'Submitted')
Action: Delay until (DueDate)
→ Configured run after: DueDate field value
Action: Condition - Status still pending?
→ IF: @equals(triggerOutputs()?['body/Status'], 'Submitted')
→ Send escalation email to ManagerEmail
5d. Required Configuration Per Form
| Config | Source | Example |
|---|---|---|
| SharePoint Site | Per-department site | https://ioioi.sharepoint.com/sites/ioi-portal-it |
| SharePoint List | Per-department MainDB | MainDB_IT |
| Status Column | Status or CurrentAction |
Submitted, HOD_Approved |
| Approver Email Field | Person/Group column | HODEmail, COOEmail |
| CC Email Field | Person/Group or text | ManagerEmail |
| Deep Link FormCode | From FormCode column |
EAF, ITSSR |
| FlowStudio MCP Environment | Power Platform env ID | Default-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx |
5e. Quick Build Reference (FlowStudio MCP)
| Task | MCP Tool | Key Parameters |
|---|---|---|
| List all flows | list_live_flows |
environmentName |
| Get flow definition | get_live_flow |
environmentName, flowName |
| Create new flow | create_live_flow |
environmentName, flowPayload (JSON string) |
| Update existing flow | update_live_flow |
environmentName, flowName, flowPayload (JSON string) |
| List connections | list_live_connections |
environmentName |
| Get dynamic schema | get_live_dynamic_properties |
environmentName, connectorName, operationId |
| Trigger a flow | trigger_live_flow |
environmentName, flowName |
| Get run history | get_live_flow_runs |
environmentName, flowName |
| Get run errors | get_live_flow_run_error |
environmentName, flowName, runName |
Phase 6: Implement the Email Templates in TypeScript
Implementation Steps
- Create
src/lib/email-templates/base-email.ts— HTML wrapper with IOI branding - Create template files for each email type (E1-E8)
- Update
src/lib/email-templates.tsto call new HTML templates - Update
src/services/notification-service.tsto use Microsoft Graph API
Graph API Call Pattern (for TypeScript service)
// src/services/graph-email-service.ts
import { Client } from '@microsoft/microsoft-graph-client';
import { AuthCodeMSALBrowserAuthenticationProvider } from '@microsoft/microsoft-graph-client/authProviders/authCodeMSALBrowser';
export async function sendGraphEmail(notification: EmailNotification): Promise<void> {
const client = Client.initWithMiddleware({
authProvider: /* MSAL auth provider */,
});
const message = {
subject: notification.subject,
body: {
contentType: 'HTML',
content: notification.body,
},
toRecipients: notification.to.map(email => ({
emailAddress: { address: email },
})),
ccRecipients: (notification.cc ?? []).map(email => ({
emailAddress: { address: email },
})),
importance: notification.importance ?? 'Normal',
};
await client.api('/me/sendMail').post({ message });
}
Phase 7: Test & Verify
- Unit tests: Test each HTML template renders correctly with sample data
- Flow tests (via FlowStudio MCP): Trigger each flow and check run history
# Trigger flow manually result = mcp("trigger_live_flow", environmentName=ENV, flowName=FLOW_ID) # Wait a few seconds, then check run history runs = mcp("get_live_flow_runs", environmentName=ENV, flowName=FLOW_ID) for run in runs.get("runs", []): print(f" Run {run['name']}: {run['status']}") # If failed, get errors if run['status'] == 'Failed': error = mcp("get_live_flow_run_error", environmentName=ENV, flowName=FLOW_ID, runName=run['name']) print(json.dumps(error, indent=2)) - Integration: Verify deep links navigate to correct form with correct state
- Mobile rendering: Test HTML emails on Outlook mobile, Gmail, iOS Mail
- Domino parity: Compare recipient lists and conditions against original
@MailSendcalls
Output Files
| Artifact | Location |
|---|---|
| Email audit per form | docs/email-notifications/{formCode}-email-audit.md |
| HTML email base template | ioicodeapp/powerapps-mirror/apps/ioi-platform/src/lib/email-templates/base-email.ts |
| Per-type templates | ioicodeapp/powerapps-mirror/apps/ioi-platform/src/lib/email-templates/{type}.ts |
| Graph email service | ioicodeapp/powerapps-mirror/apps/ioi-platform/src/services/graph-email-service.ts |
| FlowStudio MCP build/debug outputs | (via FlowStudio MCP tools) |
| Power Automate flows | Provisioned via FlowStudio MCP create_live_flow / update_live_flow |
| Deep link helper | ioicodeapp/powerapps-mirror/apps/ioi-platform/src/hooks/use-app-params.ts (existing) |
Design Principles
- HTML not plain text — All notification emails use responsive HTML with IOI branding
- Deep links in every email — Every notification has a "View" or "Approve" button linking into the Power Apps app
- Conditional routing — Email routing mirrors Domino
@Iflogic exactly - One trigger per status — Each Power Automate flow or flow branch covers one status transition
- Don't hardcode emails — All recipient addresses come from SharePoint list person/group columns or calculated fields
- Log all sends — Every email dispatch is logged for audit (via notification-service.ts)