Guide
Automated Email Reports with PowerShell
Build automated email reporting workflows entirely from PowerShell. Use Nylas CLI to query your inbox, aggregate data with native PowerShell cmdlets like Group-Object and Measure-Object, generate styled HTML reports, and send them on a schedule using Windows Task Scheduler. Works with Gmail, Outlook, Office 365, and any provider.
Prerequisites
# Install Nylas CLI (one-liner for PowerShell)
irm https://cli.nylas.com/install.ps1 | iex
# Or install with Go (requires Go 1.21+)
# go install github.com/nylas/cli/cmd/nylas@latest
# Authenticate your email account
nylas auth login
# Verify access
nylas email list --limit 1 --jsonQuery emails as JSON
Every Nylas CLI command accepts --json to output structured data. PowerShell's ConvertFrom-Json turns that into native objects you can filter, group, and measure.
# List the last 50 emails as PowerShell objects
$emails = nylas email list --json --limit 50 | ConvertFrom-Json
# Inspect the first email
$emails[0] | Format-List subject, date, from
# Filter to unread only
$unread = nylas email list --json --unread --limit 100 | ConvertFrom-Json
Write-Host "Unread count: $($unread.Count)"Search for specific emails using nylas email search:
# Search for emails about invoices
$invoices = nylas email search "invoice" --json --limit 50 | ConvertFrom-Json
Write-Host "Found $($invoices.Count) invoice-related emails"
# Search for emails from a specific sender
$fromBoss = nylas email search "from:boss@company.com" --json --limit 20 | ConvertFrom-JsonDaily inbox summary
This script builds a daily summary of your inbox: total emails, unread count, top senders, and the most recent subjects.
# daily-inbox-summary.ps1
# Fetch today's emails
$allEmails = nylas email list --json --limit 200 | ConvertFrom-Json
$unreadEmails = nylas email list --json --unread --limit 200 | ConvertFrom-Json
# Top senders by volume
$topSenders = $allEmails |
Group-Object -Property { $_.from[0].email } |
Sort-Object Count -Descending |
Select-Object -First 10 Name, Count
# Recent subjects
$recentSubjects = $allEmails |
Select-Object -First 10 |
ForEach-Object { "$($_.from[0].name): $($_.subject)" }
# Build summary
$summary = @"
Inbox Summary — $(Get-Date -Format 'yyyy-MM-dd')
================================================
Total emails (last 200): $($allEmails.Count)
Unread: $($unreadEmails.Count)
Top Senders:
$($topSenders | ForEach-Object { " $($_.Count) — $($_.Name)" } | Out-String)
Recent Emails:
$($recentSubjects | ForEach-Object { " • $_" } | Out-String)
"@
Write-Host $summaryWeekly sender breakdown
Group emails by sender domain and count them. Useful for identifying which services flood your inbox.
# sender-breakdown.ps1
$emails = nylas email list --json --limit 500 | ConvertFrom-Json
# Group by sender domain
$domainBreakdown = $emails |
Group-Object -Property { ($_.from[0].email -split '@')[1] } |
Sort-Object Count -Descending |
Select-Object -First 20 Name, Count
# Calculate percentages
$total = ($domainBreakdown | Measure-Object -Property Count -Sum).Sum
$domainBreakdown | ForEach-Object {
$pct = [math]::Round(($_.Count / $total) * 100, 1)
Write-Host ("{0,5} ({1,5}%) — {2}" -f $_.Count, $pct, $_.Name)
}Generate HTML reports
Build a styled HTML email report and send it with nylas email send --body-html.
# html-email-report.ps1
$emails = nylas email list --json --limit 100 | ConvertFrom-Json
$unread = nylas email list --json --unread --limit 100 | ConvertFrom-Json
# Top senders
$topSenders = $emails |
Group-Object -Property { $_.from[0].email } |
Sort-Object Count -Descending |
Select-Object -First 10 Name, Count
# Build sender rows
$senderRows = $topSenders | ForEach-Object {
"<tr><td style='padding:6px 12px;border-bottom:1px solid #333'>$($_.Name)</td>" +
"<td style='padding:6px 12px;border-bottom:1px solid #333;text-align:right'>$($_.Count)</td></tr>"
}
# Build HTML
$html = @"
<html>
<body style="font-family:system-ui,sans-serif;background:#1a1a2e;color:#e0e0e0;padding:24px">
<h1 style="color:#4ade80">Inbox Report — $(Get-Date -Format 'yyyy-MM-dd')</h1>
<div style="display:flex;gap:24px;margin:16px 0">
<div style="background:#16213e;padding:16px 24px;border-radius:8px">
<div style="font-size:28px;font-weight:bold;color:#4ade80">$($emails.Count)</div>
<div style="font-size:14px;color:#888">Total Emails</div>
</div>
<div style="background:#16213e;padding:16px 24px;border-radius:8px">
<div style="font-size:28px;font-weight:bold;color:#f59e0b">$($unread.Count)</div>
<div style="font-size:14px;color:#888">Unread</div>
</div>
</div>
<h2 style="color:#4ade80;margin-top:24px">Top Senders</h2>
<table style="border-collapse:collapse;width:100%;max-width:500px">
<tr style="background:#16213e">
<th style="padding:8px 12px;text-align:left">Sender</th>
<th style="padding:8px 12px;text-align:right">Count</th>
</tr>
$($senderRows -join "`n ")
</table>
<p style="color:#666;font-size:12px;margin-top:24px">
Generated by Nylas CLI + PowerShell at $(Get-Date -Format 'HH:mm:ss')
</p>
</body>
</html>
"@
# Save HTML to a temp file for debugging
$htmlPath = "$env:TEMPinbox-report.html"
$html | Out-File -FilePath $htmlPath -Encoding utf8
# Send the report via email
nylas email send `
--to "you@company.com" `
--subject "Daily Inbox Report — $(Get-Date -Format 'yyyy-MM-dd')" `
--body-html $html `
--yes
Write-Host "Report sent and saved to $htmlPath"Attachment size report
Find which emails have the largest attachments. Useful for managing mailbox size.
# attachment-report.ps1
$emails = nylas email list --json --has-attachment --limit 100 | ConvertFrom-Json
# Summarize attachment sizes
$attachmentData = $emails | ForEach-Object {
$totalSize = ($_.attachments | Measure-Object -Property size -Sum).Sum
[PSCustomObject]@{
Subject = $_.subject
From = $_.from[0].email
Attachments = $_.attachments.Count
TotalSizeKB = [math]::Round($totalSize / 1024, 1)
}
}
# Top 10 largest
$attachmentData |
Sort-Object TotalSizeKB -Descending |
Select-Object -First 10 |
Format-Table -AutoSize
# Total storage used by attachments
$totalMB = [math]::Round(
($attachmentData | Measure-Object -Property TotalSizeKB -Sum).Sum / 1024, 2
)
Write-Host "Total attachment storage: $($totalMB) MB across $($attachmentData.Count) emails"Email volume trends
Track email volume over time by grouping messages by date.
# email-volume-trends.ps1
$emails = nylas email list --json --limit 500 | ConvertFrom-Json
# Group by date
$byDate = $emails |
Group-Object -Property { (Get-Date $_.date).ToString('yyyy-MM-dd') } |
Sort-Object Name
# ASCII bar chart
$maxCount = ($byDate | Measure-Object -Property Count -Maximum).Maximum
foreach ($day in $byDate) {
$barLength = [math]::Round(($day.Count / $maxCount) * 40)
$bar = '#' * $barLength
Write-Host ("{0} {1,3} {2}" -f $day.Name, $day.Count, $bar)
}Unread count alert
Send yourself an alert email when unread messages exceed a threshold. Useful for shared mailboxes or support queues.
# unread-alert.ps1
param(
[int]$Threshold = 50,
[string]$AlertTo = "you@company.com"
)
$unread = nylas email list --json --unread --limit 200 | ConvertFrom-Json
$count = $unread.Count
if ($count -ge $Threshold) {
# Top senders contributing to the backlog
$topSenders = $unread |
Group-Object -Property { $_.from[0].email } |
Sort-Object Count -Descending |
Select-Object -First 5
$senderList = $topSenders |
ForEach-Object { " $($_.Count) from $($_.Name)" }
$body = @"
Unread email alert: $count messages exceed threshold of $Threshold.
Top senders:
$($senderList -join "`n")
Oldest unread: $($unread[-1].subject) ($($unread[-1].date))
"@
nylas email send `
--to $AlertTo `
--subject "Alert: $count unread emails" `
--body $body `
--yes
Write-Host "Alert sent: $count unread emails"
} else {
Write-Host "OK: $count unread (below threshold of $Threshold)"
}Folder distribution report
See how email is distributed across folders.
# folder-distribution.ps1
$folders = @("inbox", "sent", "drafts", "trash", "spam")
foreach ($folder in $folders) {
$emails = nylas email list --json --folder $folder --limit 200 | ConvertFrom-Json
$count = $emails.Count
$bar = '#' * [math]::Min($count, 40)
Write-Host ("{0,-10} {1,4} {2}" -f $folder, $count, $bar)
}Schedule with Windows Task Scheduler
Automate any of these scripts to run daily, weekly, or at any interval using Windows Task Scheduler.
# Create a scheduled task to run the daily report at 8 AM every weekday
schtasks /create `
/tn "NylasInboxReport" `
/tr "powershell.exe -ExecutionPolicy Bypass -File C:Scriptsdaily-inbox-summary.ps1" `
/sc weekly `
/d MON,TUE,WED,THU,FRI `
/st 08:00 `
/ru "%USERNAME%"
# Verify the task was created
schtasks /query /tn "NylasInboxReport" /fo LISTYou can also create the task through the Task Scheduler GUI:
- Open Task Scheduler (
taskschd.msc) - Click Create Basic Task
- Set the trigger (daily, weekly, etc.)
- Action: Start a program
- Program:
powershell.exe - Arguments:
-ExecutionPolicy Bypass -File C:\Scripts\daily-inbox-summary.ps1
Logging task output
# Wrapper script that logs output — schedule-with-logging.ps1
$logDir = "$env:USERPROFILENylasReports"
if (-not (Test-Path $logDir)) { New-Item -ItemType Directory -Path $logDir }
$logFile = "$logDir
eport-$(Get-Date -Format 'yyyy-MM-dd-HHmmss').log"
try {
& "C:Scriptshtml-email-report.ps1" *>&1 | Tee-Object -FilePath $logFile
Write-Output "SUCCESS at $(Get-Date)" | Add-Content $logFile
} catch {
Write-Output "ERROR: $_" | Add-Content $logFile
exit 1
}
# Clean up logs older than 30 days
Get-ChildItem $logDir -Filter "report-*.log" |
Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-30) } |
Remove-ItemFull reporting module
Combine everything into a single reusable script with parameters.
# nylas-report.ps1
param(
[ValidateSet("summary", "senders", "attachments", "volume", "folders", "all")]
[string]$Report = "summary",
[int]$Limit = 200,
[string]$SendTo = ""
)
function Get-InboxSummary {
$emails = nylas email list --json --limit $Limit | ConvertFrom-Json
$unread = nylas email list --json --unread --limit $Limit | ConvertFrom-Json
Write-Host "Total: $($emails.Count) | Unread: $($unread.Count)"
return $emails
}
function Get-SenderBreakdown($emails) {
$emails |
Group-Object -Property { $_.from[0].email } |
Sort-Object Count -Descending |
Select-Object -First 15 Name, Count |
Format-Table -AutoSize
}
function Get-AttachmentReport {
$emails = nylas email list --json --has-attachment --limit $Limit |
ConvertFrom-Json
$emails | ForEach-Object {
$size = ($_.attachments | Measure-Object -Property size -Sum).Sum
[PSCustomObject]@{
Subject = $_.subject.Substring(0, [math]::Min(50, $_.subject.Length))
SizeKB = [math]::Round($size / 1024, 1)
}
} | Sort-Object SizeKB -Descending | Select-Object -First 10 | Format-Table -AutoSize
}
function Get-VolumeChart($emails) {
$byDate = $emails |
Group-Object -Property { (Get-Date $_.date).ToString('yyyy-MM-dd') } |
Sort-Object Name
$max = ($byDate | Measure-Object -Property Count -Maximum).Maximum
foreach ($d in $byDate) {
$bar = '#' * [math]::Round(($d.Count / $max) * 30)
Write-Host ("{0} {1,3} {2}" -f $d.Name, $d.Count, $bar)
}
}
function Get-FolderDistribution {
foreach ($f in @("inbox", "sent", "drafts", "trash")) {
$e = nylas email list --json --folder $f --limit $Limit | ConvertFrom-Json
Write-Host ("{0,-10} {1}" -f $f, $e.Count)
}
}
# Run selected report
$emails = Get-InboxSummary
switch ($Report) {
"senders" { Get-SenderBreakdown $emails }
"attachments" { Get-AttachmentReport }
"volume" { Get-VolumeChart $emails }
"folders" { Get-FolderDistribution }
"all" {
Get-SenderBreakdown $emails
Get-AttachmentReport
Get-VolumeChart $emails
Get-FolderDistribution
}
}# Usage examples
.
ylas-report.ps1 -Report summary
.
ylas-report.ps1 -Report senders -Limit 500
.
ylas-report.ps1 -Report all -Limit 300Frequently asked questions
Can I schedule Nylas CLI email reports on Windows?
Yes. Use Windows Task Scheduler to run a PowerShell script that calls Nylas CLI commands. Create a scheduled task with schtasks /create or through the Task Scheduler GUI, pointing to your .ps1 script. The task runs under your user account so it has access to your Nylas CLI authentication tokens.
How do I aggregate email data with PowerShell?
Pipe Nylas CLI JSON output to ConvertFrom-Json, then use Group-Object to group by sender or folder, Measure-Object to count or sum, and Sort-Object to rank results. PowerShell's pipeline makes it natural to chain these operations without any external dependencies.
Can Nylas CLI send HTML email reports from PowerShell?
Yes. Build an HTML string in PowerShell using here-strings (@"..."@), then pass it to nylas email send --body-html. You can generate tables, inline styles, and formatted summaries entirely in PowerShell before sending.
Does this work with Gmail, Outlook, and other providers?
Yes. Nylas CLI works with Gmail, Outlook, Office 365, Yahoo, iCloud, Exchange, and any IMAP provider. The same PowerShell scripts work regardless of which email provider you authenticated with. Authenticate once with nylas auth login and the CLI handles provider differences.
Next steps
- Office 365 email from PowerShell -- manage O365 email without Microsoft Graph
- Send email from the terminal -- the bash version of CLI email workflows
- Build an LLM agent with email tools -- automate email with AI agents
- Full command reference -- every flag and subcommand