← Documentation

Send email — Power Automate flow setup

Professional & Enterprise

When 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.

ColumnTypeNotes
Titletext"<emailRuleId>:<sourceItemId>" — set by DFFS.
TotextSemicolon-separated recipients.
Cctext
Bcctext
Subjecttext
Bodymultiline (plain)Newlines are converted to <br> by the flow.
SendDatedate/timeEmpty = 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.
ListGuidtextThe source list the email came from (used by Send later to confirm the item still exists).
ListItemIdtextThe source item id.
ActiveYes/Notrue 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:

  1. Target site — current site, or pick another site.
  2. Prepare email list — ensures ModernDFFSEmail exists and resolves its GUID.
  3. Download the Send now and Send later packages (.zip).
  4. Import each at make.powerautomate.com → My flows → Import → Import Package (Legacy), selecting a SharePoint connection and an Office 365 Outlook connection during import.
  5. Open each imported flow and make sure it is turned on.
The Email flow tab of the Modern DFFS Admin tool, in three numbered steps: Target site with Current site selected and a Prepare email list button; Download the flow packages, with the "Send now" and "Send later" download buttons grayed out and a note reading "Prepare the email list first to enable the downloads"; and Import into Power Automate, listing the four import steps.

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 (Active set to false) don’t start a run at all. The Active clause matters: without it, an email canceled before the 1-minute poll ran would still be sent.

Actions (no wrapping condition — the trigger already filtered):

  1. 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
  2. SharePoint · Delete item (runs after the send succeeds)
    • Site Address: <Site URL>
    • List Name: ModernDFFSEmail
    • Id: @triggerBody()?['ID']

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). So SendDate is a UTC timestamp, and the flow runs hourly and matches items whose SendDate falls 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']:

  1. 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=Id returns only the Id column, so source lists with many lookup/person columns don’t hit the “number of lookup columns exceeds the threshold” error.)
  2. Condition — Found item:
    @greater(length(body('Check_if_item_exists').d.results), 0)
    If yes → Office 365 Outlook · Send an email (V2)
    • 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
  3. SharePoint · Delete item (runs after Found item succeeds)
    • Site Address: <Site URL>
    • List Name: ModernDFFSEmail
    • Id: @item()?['Id']

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 SendDate isn’t empty) and picked up by Send later.
  • Cancellation — the Stop email action sets Active = false. Send now’s Active guard and Send later’s Active eq 1 filter 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 ModernDFFSEmail list. 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 ModernDFFSEmail queue, but if you build a flow on the form’s own list, remember that Quick save and Auto save also write the item. Add a DFFSSaveType column 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.
  • SendDate is UTC — the send hour is whatever the sender put in SendDate, interpreted as UTC. Send later floors it to the top of that hour (a SendDate of 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):

  1. Send now filters with trigger conditions (SendDate empty and Active == true), so a run is created only when an email is actually sent — rather than a Condition action that runs for every new item.
  2. Send later queries with Top 5000 + pagination (default cap is ~100 items).
  3. Send later‘s existence check uses $select=Id so 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.