Public/New-PSUOutlookMeeting.ps1
|
function New-PSUOutlookMeeting { <# .SYNOPSIS Creates a new meeting in Microsoft Graph/Outlook using Graph PowerShell SDK. .DESCRIPTION This function creates a new calendar meeting for a specified user with attendees, handling all necessary Microsoft Graph API calls. It supports both regular timed meetings and all-day events. An existed Microsoft Graph PowerShell SDK module is required. Make sure you have the Microsoft.Graph.Calendar module installed and imported. You can install it using: Install-Module Microsoft.Graph.Calendar Connect-Mggraph -Scopes "Calendars.ReadWrite", "User.Read.All" is required before running this function. .PARAMETER Subject The subject/title of the meeting. .PARAMETER StartTime The start date and time for the meeting. For timed meetings, use format like "2025-10-21 10:00". For all-day events, use date format like "2025-10-21". .PARAMETER EndTime The end date and time for the meeting. For timed meetings, use format like "2025-10-21 10:30". For all-day events (single day), use the next day like "2025-10-22". .PARAMETER User The email address of the user whose calendar will host the meeting. .PARAMETER Attendees Array of email addresses for meeting attendees. .PARAMETER Description Optional description/body of the meeting. .PARAMETER Location Optional location for the meeting. .PARAMETER TimeZone The time zone for the meeting. Default is "India Standard Time". Not used for all-day events (they use UTC). .PARAMETER AttendeeType The type of attendees. Valid values: "required", "optional", "resource". Default is "required". .PARAMETER IsOnlineMeeting If specified, creates the meeting as a Teams online meeting. .PARAMETER ShowAs How the meeting time should appear on the calendar. Valid values: "free", "tentative", "busy", "oof", "workingElsewhere". Default is "busy". .PARAMETER Reminder When to send a reminder before the meeting. Valid values: "None", "5 minutes", "15 minutes", "30 minutes", "1 hour", "2 hours", "1 day", "1 week". Default is "15 minutes". .PARAMETER IsAllDay If specified, creates an all-day event. When this is used, start and end times should be dates only (e.g., "2025-10-21") and will be set to midnight UTC. .EXAMPLE New-PSUOutlookMeeting -Subject "Team Standup" -StartTime "2025-10-21 10:00" -EndTime "2025-10-21 10:30" -User "user@domain.com" -Attendees @("attendee1@domain.com", "attendee2@domain.com") -Description "Daily standup meeting" Creates a basic meeting with required parameters. .EXAMPLE New-PSUOutlookMeeting -Subject "Holiday" -StartTime "2025-12-25" -EndTime "2025-12-26" -User "user@domain.com" -IsAllDay -Description "Christmas Day" Creates an all-day event for Christmas Day. .EXAMPLE $description = "<div style='font-family: Calibri; font-size: 10.5pt;'>Test-Meeting scheduled by <span style='background-color: #FFFF00;'>PowerShell</span></div>" $subject = "Test-Meeting scheduled by PowerShell" $meetingParams = @{ Subject = $subject StartTime = "2025-10-20" EndTime = "2025-10-21" User = $env:MY_EMAIL Attendees = $env:MEETING_ATTENDEES.Split(",") Description = $description ShowAs = "free" Reminder = "None" IsAllDay = $true } New-PSUOutlookMeeting @meetingParams .NOTES Requires Microsoft.Graph.Calendar module and appropriate permissions. For all-day events, times are automatically set to midnight UTC as required by Microsoft Graph. #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string]$Subject, [Parameter(Mandatory = $true)] [string]$StartTime, [Parameter(Mandatory = $true)] [string]$EndTime, [Parameter(Mandatory = $true)] [string]$User, [Parameter(Mandatory = $false)] [string[]]$Attendees = @(), [Parameter(Mandatory = $false)] [string]$Description = "", [Parameter(Mandatory = $false)] [string]$Location = "", [Parameter(Mandatory = $false)] [string]$TimeZone = "India Standard Time", [Parameter(Mandatory = $false)] [ValidateSet("required", "optional", "resource")] [string]$AttendeeType = "required", [Parameter(Mandatory = $false)] [switch]$IsOnlineMeeting, [Parameter(Mandatory = $false)] [ValidateSet("free", "tentative", "busy", "oof", "workingElsewhere")] [string]$ShowAs = "busy", [Parameter(Mandatory = $false)] [ValidateSet("None", "5 minutes", "15 minutes", "30 minutes", "1 hour", "2 hours", "1 day", "1 week")] [string]$Reminder = "15 minutes", [Parameter(Mandatory = $false)] [switch]$IsAllDay ) begin { Write-Verbose "Starting New-PSUOutlookMeeting function" Write-Verbose "Subject: $Subject" Write-Verbose "User: $User" Write-Verbose "IsAllDay: $IsAllDay" Write-Verbose "StartTime: $StartTime" Write-Verbose "EndTime: $EndTime" # Check if Microsoft.Graph.Calendar module is available if (-not (Get-Module -ListAvailable -Name Microsoft.Graph.Calendar)) { throw "Microsoft.Graph.Calendar module is not installed. Please install it using: Install-Module Microsoft.Graph.Calendar" } # Import the module if not already loaded if (-not (Get-Module -Name Microsoft.Graph.Calendar)) { Import-Module Microsoft.Graph.Calendar } } process { try { # Convert reminder string to minutes $reminderMinutes = switch ($Reminder) { "None" { 0 } "5 minutes" { 5 } "15 minutes" { 15 } "30 minutes" { 30 } "1 hour" { 60 } "2 hours" { 120 } "1 day" { 1440 } "1 week" { 10080 } default { 15 } } # Build attendees array $attendeeList = @() foreach ($attendeeEmail in $Attendees) { $attendeeList += @{ emailAddress = @{ address = $attendeeEmail name = $attendeeEmail } type = $AttendeeType } } # Build the meeting body based on whether it's all-day or not if ($IsAllDay) { Write-Verbose "Creating all-day event with midnight UTC times" # For all-day events, Microsoft Graph requires midnight times in the same timezone $EventBody = @{ subject = $Subject start = @{ dateTime = "${StartTime}T00:00:00.0000000" timeZone = "UTC" } end = @{ dateTime = "${EndTime}T00:00:00.0000000" timeZone = "UTC" } isAllDay = $true showAs = $ShowAs } } else { Write-Verbose "Creating regular timed event" $EventBody = @{ subject = $Subject start = @{ dateTime = $StartTime timeZone = $TimeZone } end = @{ dateTime = $EndTime timeZone = $TimeZone } isAllDay = $false showAs = $ShowAs } } # Add optional fields if provided if ($Description) { # Check if description contains HTML tags if ($Description -match '<[^>]+>') { $EventBody.body = @{ contentType = "HTML" content = $Description } } else { $EventBody.body = @{ contentType = "text" content = $Description } } } if ($Location) { $EventBody.location = @{ displayName = $Location } } if ($attendeeList.Count -gt 0) { $EventBody.attendees = $attendeeList } if ($reminderMinutes -gt 0) { $EventBody.isReminderOn = $true $EventBody.reminderMinutesBeforeStart = $reminderMinutes } else { $EventBody.isReminderOn = $false } if ($IsOnlineMeeting) { $EventBody.isOnlineMeeting = $true $EventBody.onlineMeetingProvider = "teamsForBusiness" } # Convert to JSON for debugging $jsonBody = $EventBody | ConvertTo-Json -Depth 10 Write-Verbose "Event body JSON:" Write-Verbose $jsonBody # Create the meeting Write-Verbose "Creating meeting via Microsoft Graph API..." $result = New-MgUserEvent -UserId $User -BodyParameter $EventBody if ($result) { Write-Host "Meeting created successfully!" -ForegroundColor Green Write-Host "Meeting ID: $($result.Id)" -ForegroundColor Cyan Write-Host "Subject: $($result.Subject)" -ForegroundColor Cyan Write-Host "Start: $($result.Start.DateTime) ($($result.Start.TimeZone))" -ForegroundColor Cyan Write-Host "End: $($result.End.DateTime) ($($result.End.TimeZone))" -ForegroundColor Cyan Write-Host "Is All Day: $($result.IsAllDay)" -ForegroundColor Cyan if ($result.WebLink) { Write-Host "Web Link: $($result.WebLink)" -ForegroundColor Yellow } return $result } else { Write-Error "Failed to create meeting - no result returned" } } catch { Write-Error "Error creating meeting: $($_.Exception.Message)" Write-Error "Full error details: $_" # If there's a specific HTTP response, show it if ($_.Exception.Response) { Write-Error "HTTP Status: $($_.Exception.Response.StatusCode)" } throw } } } |