Power Automate → “Pretty” HTML Email Table (Header Row + Grid) for Daily SharePoint Comment Capture

Right now your flow is producing valid HTML, but it’s unstyled, so Outlook renders it as plain text-like lines with minimal spacing. The fix is to wrap your rows with a proper email-safe table template and apply inline CSS (Outlook is picky—inline styles are the safest approach).

Below is a clean, email-friendly template with:

  • A title block
  • A header row
  • Grid borders
  • Zebra striping
  • Column widths (so “Comment” stays wide)
  • Safe fonts (Segoe UI fallback)
  • A clickable “Link to item” button-like link

Note: I’m replacing real tenant URLs with placeholders to keep the template reusable. Use your real URL dynamically in the flow.


Step-by-step (Power Automate approach that stays maintainable)

Step 1 — Keep your “row builder” (what you already do)

You are already building rows like:

<tr>
<td>...</td>
<td>...</td>
<td><a href='...'>Link to Item</a></td>
<td>...</td>
<td>...</td>
</tr>

That’s good. The only change is: add styles per <td> and style the <a> so Outlook respects it.

Use this improved row template inside your ComposeHTMLArray (the one inside your Select / Apply to each depending on your pattern):

<tr>
<td style="padding:10px; border:1px solid #e6e6e6; vertical-align:top; white-space:nowrap;">@{item()?['siteName']}</td>
<td style="padding:10px; border:1px solid #e6e6e6; vertical-align:top; width:55%;">@{item()?['comment']}</td>
<td style="padding:10px; border:1px solid #e6e6e6; vertical-align:top; white-space:nowrap;">
<a href="@{item()?['itemLink']}"
style="display:inline-block; padding:6px 10px; text-decoration:none; border:1px solid #cfd8e3; border-radius:6px; font-weight:600;">
Link to item
</a>
</td>
<td style="padding:10px; border:1px solid #e6e6e6; vertical-align:top; white-space:nowrap;">@{item()?['createdDate']}</td>
<td style="padding:10px; border:1px solid #e6e6e6; vertical-align:top; white-space:nowrap;">@{item()?['authorEmail']}</td>
</tr>

✅ This alone already makes it look like a real grid.

Microsoft Learn reference (data operations + sending HTML): (Microsoft Learn)


Step 2 — Join all <tr> rows into one string

If you are using Select, do:

  • Select → produces an array of <tr>...</tr>
  • Join → joins array into a single HTML string

Expression example (Join):

join(outputs('Select_Rows'), '')

Why this matters: it avoids broken tables and weird spacing.

Microsoft Learn reference (Select/Join guidance): (Microsoft Learn)


Step 3 — Wrap rows with a full HTML email template (header + table styling)

Create one final Compose named something like Compose_FinalEmailHtml and paste this template.

Replace @{outputs('Join_Rows')} with your actual output (whatever your Join action is named).

<div style="font-family:Segoe UI, Arial, sans-serif; font-size:14px; color:#1a1a1a; line-height:1.4;">
<div style="margin:0 0 12px 0;">
<div style="font-size:18px; font-weight:700; margin:0 0 4px 0;">Daily Comments Report</div>
<div style="color:#555;">Comments Digest</div>
</div>
<div style="border:1px solid #e6e6e6; border-radius:10px; padding:12px; background:#fafafa;">
<table role="presentation"
style="width:100%; border-collapse:collapse; background:#ffffff; border:1px solid #e6e6e6; border-radius:10px; overflow:hidden;">
<thead>
<tr>
<th style="text-align:left; padding:10px; background:#f3f6fb; border-bottom:1px solid #d9e2ef; color:#1f2a44; white-space:nowrap;">Site</th>
<th style="text-align:left; padding:10px; background:#f3f6fb; border-bottom:1px solid #d9e2ef; color:#1f2a44; width:55%;">Comment</th>
<th style="text-align:left; padding:10px; background:#f3f6fb; border-bottom:1px solid #d9e2ef; color:#1f2a44; white-space:nowrap;">Item</th>
<th style="text-align:left; padding:10px; background:#f3f6fb; border-bottom:1px solid #d9e2ef; color:#1f2a44; white-space:nowrap;">Created (UTC)</th>
<th style="text-align:left; padding:10px; background:#f3f6fb; border-bottom:1px solid #d9e2ef; color:#1f2a44; white-space:nowrap;">Author</th>
</tr>
</thead>
<tbody>
<!-- ROWS START -->
@{outputs('Join_Rows')}
<!-- ROWS END -->
</tbody>
</table>
<div style="margin-top:10px; font-size:12px; color:#666;">
Tip: If the table looks “tight” in Outlook desktop, keep styles inline and avoid external CSS.
</div>
</div>
</div>

Microsoft Learn reference (HTML email customization + data operations): (Microsoft Learn)


Step 4 — Send Email (V2): ensure HTML is enabled

In Office 365 Outlook – Send an email (V2):

  • Put the output of Compose_FinalEmailHtml in the Body
  • Ensure the body is treated as HTML (the connector supports HTML formatting)

Microsoft Learn reference (Outlook connector HTML behavior): (Microsoft Learn)


(Optional but recommended) Zebra striping in Outlook-safe way

Outlook desktop can ignore CSS selectors like tbody tr:nth-child(even), so the safest zebra approach is:

  • Add a property in your array like rowBg = #ffffff or #fcfcff
  • Then set <tr style="background:@{item()?['rowBg']};">

If you want, you can compute that with an index counter in the flow, but the template above already gives a strong “grid” look without it.


Why Outlook was rendering it “ugly”

  • <table> without borders/padding collapses visually
  • <td> has no spacing by default in Outlook
  • Outlook is strict about CSS; inline styles are the most reliable

Microsoft Learn notes on formatting emails: (Microsoft Learn)


Final “Steps + Technical Summary” Table

StepWhat you do in the FlowOutputKey technical notes
1Build each <tr>...</tr> with inline-styled <td> and <a>Array of row stringsInline CSS is most Outlook-safe
2Join the row array with ''One big HTML rows stringPrevents broken tables and spacing issues
3Wrap rows with a full template (<thead> + <tbody>)Complete email HTMLAdd header row + fixed widths for readability
4Send email with HTML bodyRendered table in OutlookOutlook connector supports HTML; avoid advanced CSS

Edvaldo Guimrães Filho Avatar

Published by