Automatically email yourself tomorrow’s calendar
I sometimes have early meetings and it is nice to check while still in bed. This uses a PowerShell script to send an email containing tomorrow’s calendar events to a specified email address.
Create the PowerShell script: Send-OutlookCalendarEmail.ps1:
param (
[Parameter(Mandatory = $true)]
[string]$RecipientEmail,
[string]$EmailSubjectPrefix = "Calendar Events for"
)
# -----------------------------
# LOG START
# -----------------------------
$log = "$env:TEMP\calendar_task.log"
Add-Content $log "$(Get-Date) - Script started"
# -----------------------------
# TARGET DATE (TOMORROW)
# -----------------------------
$Date = (Get-Date).Date.AddDays(1)
# -----------------------------
# ENSURE OUTLOOK IS RUNNING
# -----------------------------
$outlookProcess = Get-Process OUTLOOK -ErrorAction SilentlyContinue
if (-not $outlookProcess) {
Start-Process "outlook.exe"
}
# Wait for Outlook MAPI session to be ready
$maxWait = 30
$waited = 0
do {
Start-Sleep -Seconds 1
try {
$outlook = New-Object -ComObject Outlook.Application
$namespace = $outlook.GetNamespace("MAPI")
$null = $namespace.Folders.Count
$ready = $true
} catch {
$ready = $false
}
$waited++
} until ($ready -or $waited -ge $maxWait)
if (-not $ready) {
Add-Content $log "$(Get-Date) - Outlook MAPI not ready, exiting"
exit
}
# -----------------------------
# ACCESS CALENDAR
# -----------------------------
$calendar = $namespace.GetDefaultFolder(9)
$items = $calendar.Items
$items.Sort("[Start]")
$items.IncludeRecurrences = $true
$startOfDay = $Date
$endOfDay = $startOfDay.AddDays(1)
$filter = "[Start] >= '" + $startOfDay.ToString("g") +
"' AND [Start] < '" + $endOfDay.ToString("g") + "'"
$appointments = $items.Restrict($filter)
# -----------------------------
# BUILD EMAIL BODY
# -----------------------------
$body = "Calendar events for " +
$Date.ToString("dddd, MMMM dd, yyyy") + "`r`n`r`n"
if ($appointments.Count -eq 0) {
$body += "No events scheduled.`r`n"
} else {
foreach ($appt in $appointments) {
$body += "- " + $appt.Subject + "`r`n"
$body += " Time: " +
$appt.Start.ToString("hh:mm tt") +
" - " +
$appt.End.ToString("hh:mm tt") + "`r`n"
if ($appt.Location) {
$body += " Location: " + $appt.Location + "`r`n"
}
$body += "`r`n"
}
}
# -----------------------------
# SEND EMAIL
# -----------------------------
$mail = $outlook.CreateItem(0)
$mail.To = $RecipientEmail
$mail.Subject = "$EmailSubjectPrefix $($Date.ToString('MMMM dd, yyyy'))"
$mail.Body = $body
$mail.Send()
Add-Content $log "$(Get-Date) - Mail.Send() called"
# -----------------------------
# CLEANUP
# -----------------------------
[System.Runtime.InteropServices.Marshal]::ReleaseComObject($mail) | Out-Null
[System.Runtime.InteropServices.Marshal]::ReleaseComObject($items) | Out-Null
[System.Runtime.InteropServices.Marshal]::ReleaseComObject($calendar) | Out-Null
[System.Runtime.InteropServices.Marshal]::ReleaseComObject($namespace) | Out-Null
[System.Runtime.InteropServices.Marshal]::ReleaseComObject($outlook) | Out-Null
[GC]::Collect()
[GC]::WaitForPendingFinalizers()Enable it:
Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSignedRun it to check - you should get an email:
.\Send-OutlookCalendarEmail.ps1 -RecipientEmail "name@domain.tld"You can add this to Task Scheduler.
- Open Task Scheduler
- Create Task
- General
- Give task a descriptive name
- Run whether user is logged on or not
- Triggers
- Weekly, select Monday to Thursday, 5pm, enabled
- Actions
- Start a program
- Program/script:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe - Add arguments:
-NoProfile -ExecutionPolicy Bypass -File "C:\Users\your.name\full\path\to\folder\Send-OutlookCalendarEmail.ps1" -RecipientEmail "name@domain.tld" - Start in:
C:\Users\your.name\full path\Desktop
- Conditions: Wake the computer to run this task
- Settings: tick all except one about deleting it