A team lead asked me for something simpler than daily reminders: on the first day of each month, every person on her team should get one email listing all of their tasks due that month. No flood of emails, just one tidy summary per person they could plan the month around.
In this tutorial, I’ll show you how to build that monthly reminder with Power Automate and a SharePoint list. The flow runs on the 1st of each month, finds the tasks due that month, groups them by the person they’re assigned to, and sends each person a single email with an HTML table of their tasks.
Quick answer: Create a Scheduled cloud flow that repeats every 1 Month starting on the 1st. Use Get items to get this month’s tasks, collect the unique Assigned To emails with union(), then for each person use Filter array to get their tasks, Create HTML table to list them, and Send an email (V2) to send one summary.
Set up the SharePoint list
My list, Task Tracker, has a TaskID, TaskName, Description, an AssignedTo person column and an ExpiryDate date column:

If one person has three tasks due in November, they get one email on November 1 listing all three. If you want a reminder for each task a few days before it’s due, see how to send 7 or 14 day due date reminders instead.
Create the monthly scheduled flow
In Power Automate, select Create > Scheduled cloud flow and set:
- Starting: the 1st of the next month, such as November 1, 2026.
- At: the time to send, such as 10:00 AM.
- Repeat every: 1 Month.

Open the Recurrence trigger and set the Time zone to your own, for example (UTC-05:00) Eastern Time, so the flow runs on the 1st in your time zone rather than in UTC.
Prepare the email style and dates
Add a Compose action, rename it Compose | CSS, and paste this CSS. It styles the HTML table in the email:
<style>
table { border: 1px solid #1C6EA4; background-color: #EEEEEE; width: 100%; text-align: left; border-collapse: collapse; }
table td, table th { border: 1px solid #AAAAAA; padding: 3px 2px; }
table tbody td { font-size: 13px; }
table thead { background: #0602e1; border-bottom: 2px solid #444444; }
table thead th { font-size: 15px; font-weight: bold; color: #FFFFFF; border-left: 2px solid #D0E4F5; }
table thead th:first-child { border-left: none; }
</style>

Add two Initialize variable actions of type String to hold the current month and year:
| Name | Value |
|---|---|
| varCurrentMonth | formatDateTime(utcNow(), 'MM') |
| varCurrentYear | formatDateTime(utcNow(), 'yyyy') |


Then add an Initialize variable of type Array named varAssignedTo with no value. It will collect the email addresses of everyone who has a task this month.

Get this month’s tasks
Add Get items, select your site and list, and enter this Filter Query so you only get tasks that haven’t expired yet:
ExpiryDate ge '@{utcNow()}'

Because the flow runs on the 1st, that returns everything due this month and later. Add two Filter array actions to keep only this month’s tasks:
- The first uses
outputs('Get_items')?['body/value']as From, and keeps items whereformatDateTime(item()?['ExpiryDate'], 'yyyy')is equal tovariables('varCurrentYear'). - The second uses
body('Filter_array')as From, and keeps items whereformatDateTime(item()?['ExpiryDate'], 'MM')is equal tovariables('varCurrentMonth').


A simpler filter for the whole month
You can skip both Filter array actions and the two date variables by asking SharePoint for this month’s tasks directly. Use this filter query in Get items instead:
ExpiryDate ge '@{startOfMonth(utcNow(), 'yyyy-MM-dd')}' and ExpiryDate lt '@{addToTime(startOfMonth(utcNow()), 1, 'Month', 'yyyy-MM-dd')}'
It returns tasks from the first day of this month up to, but not including, the first day of next month, and it works whatever day the flow runs. Get items returns only 100 items by default, so turn on Pagination in the action’s settings for large lists; see how to get more than 100 SharePoint items.
Collect the people who have tasks
Add an Apply to each over the output of the second Filter array, body('Filter_array_1'). Inside it, add Append to array variable for varAssignedTo with the person’s email:
item()?['AssignedTo/Email']

Someone with three tasks is now in the array three times. Add a Compose action with this expression to remove the duplicates; union() of an array with itself returns each value once:
union(variables('varAssignedTo'), variables('varAssignedTo'))

Send one email to each person
Add another Apply to each over outputs('Compose'). Each loop is one person. Inside it:

Get that person’s tasks
Add a Filter array with From set to body('Filter_array_1'), keeping items where item()?['AssignedTo/Email'] is equal to items('Apply_to_each_1').

Build the HTML table
Add Create HTML table with From set to body('Filter_array_2'). Select Show all, set Columns to Custom, and add these columns:
| Header | Value |
|---|---|
| Task ID | item()?['TaskID'] |
| Task Name | item()?['TaskName'] |
| Description | item()?['Description'] |
| Expiry Date | formatDateTime(item()?['ExpiryDate'], 'MM/dd/yyyy') |

The MM/dd/yyyy format shows dates the way US readers expect, such as 11/18/2026.
Send the email
Add Send an email (V2). Set To to items('Apply_to_each_1'), and use a subject like:
Your tasks due in @{formatDateTime(utcNow(), 'MMMM yyyy')}
For the body, switch to the code view (</>) so the CSS and the table are sent as HTML:
Hi,@{outputs('Compose_|_CSS')}
These are the tasks assigned to you that are due in @{formatDateTime(utcNow(), 'MMMM yyyy')}:
@{body('Create_HTML_table')}

Run the flow
Save the flow and select Test > Manually to try it right away. Everyone who has a task due this month gets one email listing all of their tasks, with the table styled by your CSS:

Tips
- Leave out completed tasks by adding
and Status ne 'Completed'to the filter query, using your own status column name. - To also remind people about overdue tasks, change the start of the date range to a date in the past, or add a second table for items with ExpiryDate before today.
- Send from a shared mailbox with Send an email from a shared mailbox (V2) so replies go to the team, not to you.
- Need a personal greeting? Add Get user profile (V2) with the email to get the person’s display name. For more on email formatting, see how to use Send an email (V2).
These Power Automate tutorials go well with this flow:
- Send 7 or 14 Day Task Due Reminder Emails in Power Automate
- Power Automate Approval Reminder: 3 Ways to Remind Approvers
- How to Use Power Automate Get Items Filter Query + 8 Examples
- How to Use the Send an Email (V2) Action in Power Automate (With Examples)
- How to Get Current Date in Power Automate + 7 Examples
- How to Get More Than 100 Items with Get Items in Power Automate (and Past 5,000)
Frequently Asked Questions
How do I send a monthly reminder email in Power Automate?
Create a scheduled cloud flow that repeats every 1 month, starting on the 1st. Microsoft explains the schedule options in its guide to running flows on a schedule.
How do I get only this month’s items from a SharePoint list?
Use a Get items filter query with startOfMonth(utcNow()) as the start and addToTime(startOfMonth(utcNow()), 1, ‘Month’) as the end.
How do I send one email per person instead of one per task?
Collect the assigned emails in an array, remove duplicates with union(), then loop through the unique emails and filter the tasks for each person.
Why does the date in my email show in the wrong format?
Format it in the Create HTML table column with formatDateTime(), for example ‘MM/dd/yyyy’ for US dates.

I have worked with Microsoft technologies for more than 18 years, including SharePoint, Microsoft 365 and the Power Platform (Power Apps, Power Automate and Power BI), at companies like HP, TCS and KPIT. I started EnjoySharePoint in 2011 to share the solutions I build in real projects with readers in the United States, Canada, the United Kingdom, Australia, New Zealand and beyond. Microsoft has recognized this work with the Microsoft MVP award 13 times since 2014.