Guide
Calendar Automation with PowerShell
According to Harvard Business Review, executives spend an average of 23 hours per week in meetings, up from 10 hours in the 1960s. Much of that time goes to scheduling logistics. This guide shows how to automate meeting invites, check participant availability, book conference rooms, and send calendar-driven emails from PowerShell using Nylas CLI. Works with Gmail, Outlook, Exchange, Yahoo, iCloud, and IMAP.
By Qasim Muhammad
Setup
Install Nylas CLI and authenticate. See the PowerShell email guide for install details.
irm https://cli.nylas.com/install.ps1 | iex
nylas auth config # paste your API key
# Verify calendar access
nylas calendar events list --json --limit 1 | ConvertFrom-JsonCheck participant availability
Before booking a meeting, check who's free. The availability check queries free/busy data across all participants in one call.
# check-availability.ps1 -- Find open slots for a group meeting
param(
[string[]]$Participants = @("alice@company.com", "bob@company.com"),
[string]$Date = (Get-Date).AddDays(1).ToString("yyyy-MM-dd"),
[int]$DurationMinutes = 30
)
$startTime = "$($Date)T09:00:00"
$endTime = "$($Date)T17:00:00"
$availability = nylas calendar availability check `
--start $startTime `
--end $endTime `
--participants ($Participants -join ',') `
--json | ConvertFrom-Json
$freeSlots = $availability.time_slots |
Where-Object { $_.status -eq "free" }
if ($freeSlots.Count -eq 0) {
Write-Host "No common availability on $Date" -ForegroundColor Red
exit 1
}
Write-Host "Available slots on $Date:" -ForegroundColor Green
$freeSlots | ForEach-Object {
$start = [DateTime]::Parse($_.start_time)
$end = [DateTime]::Parse($_.end_time)
Write-Host " $($start.ToString('h:mm tt')) - $($end.ToString('h:mm tt'))"
}
# First slot that fits the requested duration
$bestSlot = $freeSlots | Where-Object {
$s = [DateTime]::Parse($_.start_time); $e = [DateTime]::Parse($_.end_time)
($e - $s).TotalMinutes -ge $DurationMinutes
} | Select-Object -First 1
if ($bestSlot) {
Write-Host "Recommended: $([DateTime]::Parse($bestSlot.start_time).ToString('h:mm tt'))" -ForegroundColor Cyan
}Create meeting invites with participants
Create a calendar event with participants. Nylas sends the invite through the provider (Google Calendar, Outlook, Exchange) automatically.
# create-meeting.ps1 -- Book a meeting with availability check
param(
[string]$Title = "Team Sync",
[string[]]$Participants = @("alice@company.com", "bob@company.com"),
[string]$Date,
[string]$StartTime = "10:00",
[int]$Duration = 30,
[string]$Description = ""
)
if (-not $Date) { $Date = (Get-Date).AddDays(1).ToString("yyyy-MM-dd") }
$startDt = "$($Date)T$($StartTime):00"
$endDt = [DateTime]::Parse($startDt).AddMinutes($Duration).ToString("yyyy-MM-ddTHH:mm:ss")
# Check availability first
$avail = nylas calendar availability check `
--start $startDt --end $endDt `
--participants ($Participants -join ',') `
--json | ConvertFrom-Json
$conflicts = $avail.time_slots | Where-Object { $_.status -ne "free" }
if ($conflicts) {
Write-Host "WARNING: Not all participants are free" -ForegroundColor Yellow
}
# Create the event
$event = nylas calendar events create `
--title $Title `
--start $startDt --end $endDt `
--participants ($Participants -join ',') `
--description $Description `
--json | ConvertFrom-Json
Write-Host "Meeting created:" -ForegroundColor Green
Write-Host " Title: $($event.title)"
Write-Host " Time: $startDt to $endDt"
Write-Host " With: $($Participants -join ', ')"Conference room booking
Conference rooms in Google Workspace and Microsoft 365 have their own calendar resource. Check room availability and book in one script.
# book-room.ps1 -- Find a free room and book it
param(
[string[]]$Rooms = @("room-a@company.com", "room-b@company.com", "room-c@company.com"),
[string]$Date = (Get-Date).AddDays(1).ToString("yyyy-MM-dd"),
[string]$StartTime = "14:00",
[int]$DurationMinutes = 60,
[string]$Title = "Project Review",
[string[]]$Attendees = @("alice@company.com", "bob@company.com")
)
$startDt = "$($Date)T$($StartTime):00"
$endDt = [DateTime]::Parse($startDt).AddMinutes($DurationMinutes).ToString("yyyy-MM-ddTHH:mm:ss")
$availableRoom = $null
foreach ($room in $Rooms) {
Write-Host "Checking $room ..." -NoNewline
$avail = nylas calendar availability check `
--start $startDt --end $endDt `
--participants $room `
--json | ConvertFrom-Json
$free = $avail.time_slots | Where-Object { $_.status -eq "free" }
if ($free) {
Write-Host " FREE" -ForegroundColor Green
$availableRoom = $room
break
} else {
Write-Host " BUSY" -ForegroundColor Red
}
}
if (-not $availableRoom) {
Write-Host "No rooms available at $StartTime on $Date" -ForegroundColor Red
exit 1
}
$allParticipants = @($availableRoom) + $Attendees
$event = nylas calendar events create `
--title "$Title ($($availableRoom -replace '@.*', ''))" `
--start $startDt --end $endDt `
--participants ($allParticipants -join ',') `
--description "Room: $availableRoom" `
--json | ConvertFrom-Json
Write-Host "Booked $availableRoom for '$Title'" -ForegroundColor GreenSend meeting prep emails
Before each meeting, send yourself a prep email with the agenda and recent email history from each participant.
# meeting-prep.ps1 -- Prep email before upcoming meetings
param([int]$MinutesBefore = 30)
$events = nylas calendar events list --json | ConvertFrom-Json
$now = Get-Date
$prepWindow = $now.AddMinutes($MinutesBefore)
$upcoming = $events | Where-Object {
$start = [DateTime]::Parse($_.when.start_time)
$start -gt $now -and $start -le $prepWindow
}
foreach ($event in $upcoming) {
$participants = $event.participants | ForEach-Object { $_.email }
if ($participants.Count -eq 0) { continue }
$recentEmails = foreach ($p in $participants) {
$emails = nylas email search "from:$p" --json --limit 3 | ConvertFrom-Json
$emails | ForEach-Object { " - [$($_.date)] $($_.subject)" }
}
$body = @"
Meeting Prep: $($event.title)
Time: $($event.when.start_time)
Participants: $($participants -join ', ')
Recent emails from participants:
$($recentEmails -join "`n")
"@
nylas email send --to $env:MY_EMAIL `
--subject "Prep: $($event.title) in $MinutesBefore min" `
--body $body --yes
Write-Host "Sent prep for: $($event.title)" -ForegroundColor Green
}Daily schedule email
Send yourself a morning summary of today's meetings with times, participants, and locations.
# daily-schedule.ps1 -- Morning email with today's calendar
$today = Get-Date -Format "yyyy-MM-dd"
$events = nylas calendar events list --json | ConvertFrom-Json
if ($events.Count -eq 0) {
$body = "No meetings today. Focus day!"
} else {
$schedule = $events | ForEach-Object {
$start = [DateTime]::Parse($_.when.start_time).ToString('h:mm tt')
$end = [DateTime]::Parse($_.when.end_time).ToString('h:mm tt')
$who = ($_.participants | ForEach-Object { $_.email }) -join ', '
"$start - $end: $($_.title)`n With: $who"
}
$body = "Schedule for $today ($($events.Count) meetings)`n`n$($schedule -join "`n`n")"
}
nylas email send --to $env:MY_EMAIL `
--subject "Schedule: $today ($($events.Count) meetings)" `
--body $body --yesAutomate recurring meeting follow-ups
# standup-followup.ps1 -- Follow-up email after standup meetings
$events = nylas calendar events list --json | ConvertFrom-Json
$now = Get-Date
$recentStandups = $events | Where-Object {
$_.title -match 'standup|daily sync|scrum' -and
[DateTime]::Parse($_.when.end_time) -lt $now -and
[DateTime]::Parse($_.when.end_time) -gt $now.AddHours(-2)
}
foreach ($standup in $recentStandups) {
$participants = ($standup.participants | ForEach-Object { $_.email }) -join ','
$body = @"
Follow-up: $($standup.title) - $(Get-Date -Format 'MMM d')
Action items:
- [ ]
- [ ]
Reply with updates or additional items.
"@
nylas email send --to $participants `
--subject "Follow-up: $($standup.title) - $(Get-Date -Format 'MMM d')" `
--body $body --yes
}Schedule with Task Scheduler
# Morning schedule at 7:30 AM weekdays
schtasks /create /tn "DailySchedule" `
/tr "pwsh.exe -NoProfile -File C:\Scripts\daily-schedule.ps1" `
/sc weekly /d MON,TUE,WED,THU,FRI /st 07:30 /ru "%USERNAME%"
# Meeting prep every 15 minutes
schtasks /create /tn "MeetingPrep" `
/tr "pwsh.exe -NoProfile -File C:\Scripts\meeting-prep.ps1" `
/sc minute /mo 15 /ru "%USERNAME%"Frequently asked questions
How do I check meeting room availability from PowerShell?
Use nylas calendar availability check --participants room-a@company.com --start "..." --end "..." --json. Room calendars in Google Workspace and Microsoft 365 are treated as regular participants. Parse the result and filter for free slots.
Can I send meeting invites from a PowerShell script?
Yes. Use nylas calendar events create --title "Meeting" --start "..." --end "..." --participants "alice@company.com,bob@company.com". The CLI sends invites through the provider automatically.
How do I schedule emails based on calendar events?
List upcoming events with nylas calendar events list --json, find events starting within your window, and send emails with nylas email send. Run via Task Scheduler every 15 minutes.
Next steps
- Manage calendar from the terminal -- DST-aware events, timezone locking, AI scheduling
- Generate and email reports -- CSV attachments, HTML tables, weekly digests
- Send email from PowerShell -- the foundation guide for PowerShell email
- Full command reference -- every flag and subcommand