public/entra/Send-EntraUserMfaStatusReport.ps1
function Send-EntraUserMfaStatusReport { <# .SYNOPSIS Send Entra user MFA status report. .DESCRIPTION Collects Entra user MFA status and sends a report to the specified e-mail address. .PARAMETER EmailAddress E-mail address to send the report. .EXAMPLE Send-EntraUserMfaStatusReport -EmailAddress 'abc@contoso.com'; #> [cmdletbinding()] [OutputType([void])] [ValidateScript({ $_ -match '' })] param ( # E-mail address to send the report. [Parameter(Mandatory = $false)] [ValidateScript({ Test-EmailAddress -InputObject $_ })] [string]$EmailAddress = ((Get-EntraContext).Account) ) BEGIN { # Write to log. $customProgress = Write-CustomProgress -Activity $MyInvocation.MyCommand.Name -CurrentOperation 'Sending Entra user MFA status report'; # Write to log. Write-CustomLog -Message ('Microsoft Entra User MFA Status Report') -Level Console; Write-CustomLog -Message ('Gathering information from Microsoft Entra, this might take a while (be patient)') -Level Console -IndentLevel 1; # Get Entra user MFA status. $entraUserMfaStatus = Get-EntraUserMfaStatus; # Import header and footer. $header = Get-Content -Path (Join-Path -Path $Script:scriptPath -ChildPath 'private\assets\email\send-entrausermfastatusreport\header.html'); $footer = Get-Content -Path (Join-Path -Path $Script:scriptPath -ChildPath 'private\assets\email\send-entrausermfastatusreport\footer.html'); # HTML. [string]$html = ''; # Update header with date. $header = $header -replace '##DATE##', (Get-Date -Format 'yyyy-MM-dd HH:mm:ss'); # Add header. $html = $header | Out-String; # Temporary folder path. [string]$tempFolderPath = [System.IO.Path]::GetTempPath(); # File name. [string]$outputFileName = ('Microsoft 365 User MFA Status Report - {0}.csv' -f (Get-Date -Format 'yyyy-MM-dd')); # Output file path. [string]$outputFilePath = Join-Path -Path $tempFolderPath -ChildPath $outputFileName; # User object array. $users = @(); } PROCESS { # Foreach user. foreach ($user in $entraUserMfaStatus) { # If user is protected by MFA. if ($user.FullMfa -eq $true) { # Skip to next user. continue; } # If user is disabled. if ($false -eq $user.AccountEnabled) { # Skip to next user. continue; } # If user is external. if ($user.UserPrincipalName -like '*#EXT#@*') { # Skip to next user. continue; } # Add to object array. $users += $user; # Add user to HTML. $html += '<tr>' | Out-String; $html += "<td>$($user.DisplayName)</td>" | Out-String; $html += "<td>$($user.UserPrincipalName)</td>" | Out-String; $html += "<td>$($user.IsAdmin)</td>" | Out-String; $html += "<td>$($user.Apps -join ',<br>')</td>" | Out-String; $html += "<td>$($user.IsMfaCapable)</td>" | Out-String; $html += '</tr>' | Out-String; } # Add footer. $html += $footer | Out-String; # Write to log. Write-CustomLog -Message ('Found {0} MFA users for the MFA status report' -f $users.Count) -Level 'Verbose'; Write-CustomLog -Message ("Exporting report to '{0}'" -f $outputFilePath) -Level 'Verbose'; Write-CustomLog -Message ("Exporting report to '{0}'" -f $outputFilePath) -Level Console -IndentLevel 1; # Save status report as CSV. $null = $users | Select-Object -Property DisplayName, UserPrincipalName, IsAdmin, @{ Name = 'Apps'; Expression = { $_.Apps -join ', ' } }, IsMfaCapable | Export-Csv -Path $outputFilePath -UseQuotes Always -Encoding utf8 -Delimiter ';' -Force; # Convert CSV to Base64. $attachment = [Convert]::ToBase64String([System.IO.File]::ReadAllBytes($outputFilePath)); # Create parameters for sending the e-mail. $params = @{ message = @{ subject = ('Microsoft 365 User MFA Status Report - {0}' -f (Get-Date -Format 'yyyy-MM-dd')); body = @{ contentType = 'HTML'; content = $html; }; toRecipients = @( @{ emailAddress = @{ address = $EmailAddress; }; } ); attachments = @( @{ '@odata.type' = '#microsoft.graph.fileAttachment'; name = $outputFileName; contentType = 'text/plain'; contentBytes = $attachment; } ); }; saveToSentItems = 'true'; }; # Write to log. Write-CustomLog -Message ('Sending MFA status report to {0}' -f $EmailAddress) -Level Console -IndentLevel 1; # A UPN can also be used as -UserId. Send-MgUserMail -UserId (Get-EntraContext).Account -BodyParameter $params -ErrorAction Stop; } END { # Write to log. Write-CustomProgress @customProgress; } } |