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_FinalEmailHtmlin 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=#ffffffor#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
| Step | What you do in the Flow | Output | Key technical notes |
|---|---|---|---|
| 1 | Build each <tr>...</tr> with inline-styled <td> and <a> | Array of row strings | Inline CSS is most Outlook-safe |
| 2 | Join the row array with '' | One big HTML rows string | Prevents broken tables and spacing issues |
| 3 | Wrap rows with a full template (<thead> + <tbody>) | Complete email HTML | Add header row + fixed widths for readability |
| 4 | Send email with HTML body | Rendered table in Outlook | Outlook connector supports HTML; avoid advanced CSS |
