Send email — Power Automate flow setup
Professional & EnterpriseWhen a form rule uses the Send email action to send mail via Power Automate (rather than from the logged-in user’s mailbox), Modern DFFS does not send the message itself. Instead it writes a row into a per-site list named ModernDFFSEmail. Two Power Automate flows watch that list and do the actual sending. This guide explains how the flows work and how to create them — either automatically with the Modern DFFS Admin tool, or by hand.
The Send email and Stop email rule actions require the Professional or Enterprise edition.
How it works
Every email queued by the Send email action becomes one item in the ModernDFFSEmail list on the current site. Two flows process that list:
- Send now — triggers on each new item and sends items that have no
SendDate, immediately. - Send later — runs every hour and sends items whose
SendDate(a UTC date/time) falls in the current hour.
Both flows delete each item once it has been processed, so the list does not grow unbounded (which would eventually throttle the query).
The ModernDFFSEmail list
Modern DFFS provisions this list on demand. The Admin tool’s Prepare email list button creates the same list (identical fields) if it doesn’t exist yet.
| Column | Type | Notes |
|---|---|---|
Title | text | "<emailRuleId>:<sourceItemId>" — set by DFFS. |
To | text | Semicolon-separated recipients. |
Cc | text | |
Bcc | text | |
Subject | text | |
Body | multiline (plain) | Newlines are converted to <br> by the flow. |
SendDate | date/time | Empty = send immediately; a value = send at that UTC date/time (the sender sets the hour in UTC). Stored as a full timestamp even though the column displays date-only. |
ListGuid | text | The source list the email came from (used by Send later to confirm the item still exists). |
ListItemId | text | The source item id. |
Active | Yes/No | true on creation; set to false to cancel a queued email. |
DFFS always creates the item with Active = true; the Stop email rule action sets it to false to cancel a not-yet-sent email.
Option A — generate the flows with the Admin tool (recommended)
In the Modern DFFS Admin web part → Email flow tab:
- Target site — current site, or pick another site.
- Prepare email list — ensures
ModernDFFSEmailexists and resolves its GUID. - Download the Send now and Send later packages (
.zip). - Import each at make.powerautomate.com → My flows → Import → Import Package (Legacy), selecting a SharePoint connection and an Office 365 Outlook connection during import.
- Open each imported flow and make sure it is turned on.
The site URL and list GUID are baked into the packages; the email is sent from the account that owns the Office 365 Outlook connection chosen at import.
Generate and import a set for each site that sends DFFS emails via Power Automate.
Option B — build the flows by hand
Two connections are needed in both flows: SharePoint and Office 365 Outlook. Throughout, <Site URL> is the site hosting ModernDFFSEmail and <List GUID> is that list’s id.
Flow 1 — “Send now”
Trigger — SharePoint · When an item is created
- Site Address:
<Site URL> - List Name:
ModernDFFSEmail - (Runs on the default 1-minute poll.)
Trigger — Settings → Trigger Conditions (only run for immediate, un-canceled emails). Add two conditions (all must be true = AND):
@empty(triggerBody()?['SendDate'])
@equals(triggerBody()?['Active'], true)
Using trigger conditions rather than a Condition action means a flow run is created only when an email is actually sent — dated items (Send later’s job) and canceled items (
Activeset tofalse) don’t start a run at all. TheActiveclause matters: without it, an email canceled before the 1-minute poll ran would still be sent.
Actions (no wrapping condition — the trigger already filtered):
- Office 365 Outlook · Send an email (V2)
- To:
@triggerBody()?['To'] - Subject:
@triggerBody()?['Subject'] - Body:
<p class="editor-paragraph">@{replace(triggerBody()?['Body'],decodeUriComponent('%0A'), '<br>')}</p> - Cc:
@triggerBody()?['Cc'] - Bcc:
@triggerBody()?['Bcc'] - Importance:
Normal
- To:
- SharePoint · Delete item (runs after the send succeeds)
- Site Address:
<Site URL> - List Name:
ModernDFFSEmail - Id:
@triggerBody()?['ID']
- Site Address:
Flow 2 — “Send later”
Trigger — Recurrence
- Frequency: Hour, Interval: 1 (no time zone — runs in UTC)
DFFS lets the sender set the hour of
SendDate, in UTC (see the field’s description in the email rule). SoSendDateis a UTC timestamp, and the flow runs hourly and matches items whoseSendDatefalls in the current UTC hour — an email set for 14:00 UTC goes out on the 14:00 run.
Action — Initialize variable ThisHourStart (string):
@formatDateTime(utcNow(),'yyyy-MM-ddTHH:00:00')
Action — Initialize variable ThisHourEnd (string):
@formatDateTime(utcNow(),'yyyy-MM-ddTHH:59:59')
These bound the current UTC hour:
[HH:00:00, HH:59:59].
Action — SharePoint · Get items
- Site Address:
<Site URL> - List Name:
ModernDFFSEmail - Filter Query:
Active eq 1 and SendDate le datetime'@{variables('ThisHourEnd')}' and SendDate ge datetime'@{variables('ThisHourStart')}' - Top Count:
5000 - Settings → Pagination: On, Threshold:
5000
Pagination + a high Top Count avoid silently dropping scheduled emails on a busy day (the default cap is ~100 items).
Action — Apply to each over @outputs('Get_items')?['body/value']:
- SharePoint · Send an HTTP request to SharePoint — Check if item exists (has the source item been deleted since it was queued?)
- Site Address:
<Site URL> - Method:
GET - Uri:
_api/web/lists/getById('@{item()?['ListGuid']}')/items?$select=Id&$filter=Id eq @{item()?['ListItemId']} - (
$select=Idreturns only the Id column, so source lists with many lookup/person columns don’t hit the “number of lookup columns exceeds the threshold” error.)
- Site Address:
- Condition — Found item:
If yes → Office 365 Outlook · Send an email (V2)@greater(length(body('Check_if_item_exists').d.results), 0)- To:
@item()?['To'] - Subject:
@item()?['Subject'] - Body:
<p class="editor-paragraph">@{replace(item()?['Body'],decodeUriComponent('%0A'), '<br>')}</p> - Cc:
@item()?['Cc'] - Bcc:
@item()?['Bcc'] - Importance:
Normal
- To:
- SharePoint · Delete item (runs after Found item succeeds)
- Site Address:
<Site URL> - List Name:
ModernDFFSEmail - Id:
@item()?['Id']
- Site Address:
Notes & gotchas
- Send from account — emails are sent from the mailbox that owns the Office 365 Outlook connection, not the form user. Use a shared/service mailbox if that matters.
- Both flows are required for full coverage: Send now handles immediate emails, Send later handles dated ones. A dated email is skipped by Send now (its
SendDateisn’t empty) and picked up by Send later. - Cancellation — the Stop email action sets
Active = false. Send now’sActiveguard and Send later’sActive eq 1filter both honor it, so a canceled email is never sent. - Processed items are deleted, not marked done — this is intentional (keeps the query fast).
- Per site — these flows target one site’s
ModernDFFSEmaillist. Deploy a set per site that sends DFFS emails via Power Automate. - Flows on your own lists fire on every DFFS save — this guide covers the
ModernDFFSEmailqueue, but if you build a flow on the form’s own list, remember that Quick save and Auto save also write the item. Add aDFFSSaveTypecolumn and gate the flow with a trigger condition —@equals(triggerOutputs()?['body/DFFSSaveType'], 'save')— so it only runs when the user actually finishes the form. See the System fields reference. SendDateis UTC — the send hour is whatever the sender put inSendDate, interpreted as UTC. Send later floors it to the top of that hour (aSendDateof 14:30 UTC goes out on the 14:00 run).
Differences from a plain flow export
The Admin tool’s generated packages differ from a raw “as-built” export in these deliberate ways (all reflected in the manual steps above):
- Send now filters with trigger conditions (
SendDateempty andActive == true), so a run is created only when an email is actually sent — rather than a Condition action that runs for every new item. - Send later queries with Top 5000 + pagination (default cap is ~100 items).
- Send later‘s existence check uses
$select=Idso source lists with many lookup/person columns don’t hit the lookup-column threshold.
The tool also strips source-tenant runtime metadata and generic-labels the connection resources; those are packaging details and don’t affect a hand-built flow.
