PowerShell: Stop Outlook from Junking Legit Messages

Outlook often struggles with erroneous junk mail classifications. It seems that some messages can pass through the SMTP perimeter scanning and email authentication, but still end up in Outlook’s junk folder.

The internal workings of Outlook’s built-in message filters aren’t fully documented anywhere that I know of. This can lead to some perplexing situations. Last week my own company’s newsletter was being routed to the junk folder. This was out of the blue, the monthly messages had never been considered SPAM before?

I went to some drastic lengths trying to determine why an internal message was triggering Outlook’s junk filter. I enabled logging, reviewed mail traces, and all the rest to no avail. The only way I could get the message to stay in the inbox was to add the entire sending domain to the safe list.

To run the script below you need the Exchange Online Management module installed. You also need access to credentials with the appropriate permissions in Microsoft 365 and Exchange Online. If the script is going to be your permanent solution, I suggest adding it to your onboarding processes.

Import-Module ExchangeOnlineManagement
Connect-ExchangeOnline

$trustedDomain = ” sender domain.com”

$mailboxes = Get-Mailbox -ResultSize Unlimited

Foreach ($mailbox in $mailboxes) {
    $currentTrustedSenders = Get-MailboxJunkEmailConfiguration -Identity $mailbox.UserPrincipalName | Select-Object -ExpandProperty TrustedSendersAndDomains
    if ($currentTrustedSenders -notcontains $trustedDomain) {
        $newTrustedSenders = $currentTrustedSenders + $trustedDomain
        Set-MailboxJunkEmailConfiguration -Identity $mailbox.UserPrincipalName -TrustedSendersAndDomains $newTrustedSenders
        Write-Output “Added $trustedDomain to trusted senders list for $($mailbox.UserPrincipalName)”
    } else {
        Write-Output “$trustedDomain is already in the trusted senders list for $($mailbox.UserPrincipalName)”
    }
}

PowerShell: Report To Avoid Hidden Exchange Mailbox Quota Violations

There are two separate quotas for a Microsoft 365 mailbox. One is for the size of the mailbox. The other lesser-known limit is on the recoverable items database.

It is the recoverable items that frequently catch people off-guard. This quota isn’t shown in the admin portal dashboards. Furthermore, the limit is usually only an issue if you have a mailbox on legal hold.

These two things combine to make a frustrating situation. A user’s mailbox can stop due to a quota violation when it isn’t shown as being full on the portal. Here is a link to Microsoft’s documentation on the subject if you would like to know more.

Import-Module ExchangeOnlineManagement
Connect-ExchangeOnline
$Report = @()
$UserMailboxes = (Get-ExoMailbox -ResultSize unlimited -Filter {(RecipientType -eq ‘UserMailbox’)}).UserPrincipalName
Foreach ($Mailbox in $UserMailboxes){
    $MailboxTotalSize = [PSCustomObject]@{
        Name = $Mailbox
        Mailbox = Get-ExoMailboxStatistics -Identity $Mailbox | Select-Object TotalItemSize -ExpandProperty TotalItemSize
        RecoverableItems = Get-ExoMailboxFolderStatistics -Identity $Mailbox -FolderScope RecoverableItems | Select-Object Name,FolderAndSubfolderSize -ExpandProperty FolderAndSubfolderSize |Where-Object {$_.Name -like “*Recoverable*”}
    }
    $Report += $MailboxTotalSize
}
$Report |Export-Csv -Path
“C\Temp\MailboxTrueSizeReport.csv” -NoTypeInformation

I use the report to help prevent quota lockouts at my employer. You will need to run the script from a machine that has the Exchange Online Management Powershell module installed. Executing the script also requires an account with Exchange Online mailbox administrator permissions.

The output is an easy-to-read three-column report. The headers are Name (the user’s UPN), Mailbox, and RecoverableItems. The script takes around one hour per thousand mailboxes on average. This time can vary wildly,  the point is that it’s slow. Don’t let the computer running it go to sleep.

PowerShell: Restore Soft Deleted Exchange On-line Mailbox To New Microsoft 365 User

Recently, I encountered a situation in which a Microsoft 365 account had been deleted. Then, a new account with the same name was created and synchronized from the local domain. The user’s local profile and other software were linked to the new account and everything was working. The only issue was the mailbox missing all of its content.

Believe it or not, this isn’t an uncommon situation in my line of work. I looked online for a script and found lots of examples. Much to my surprise, I struggled to get any of them to work. Rather than try to troubleshoot and fix one , I opted to write my own. While writing it, I believe I discovered the issue. Exchange Online does not except the ExchangeGUID as a name/value pair. It has to be plain text.

Below is what I came up with. You will need to have the Exchange Online PowerShell Module installed on your computer. Open an Admin PowerShell Session and run the one-liner below to install it. You may also be prompted to update PowerShell itself if your computer has fallen behind in updates.

Install-Module ExchangeOnlineManagement

Save and run the script below. First, it will prompt for the tenant’s modern authentication global admin credentials. Next, it will prompt you for the account your are working with’s identity. You should be able to use the first and last name, UPN, or alias address. The script will use that data to locate the Exchange GUID for the source and target mailboxes. Finally, it will create and run a mailbox restore request and show the status.

# Restore Soft Deleted Mailbox to a new Matching Account in Exchange Online
# Assumes the Alias for both accounts is the same

#Sign in to Microsoft 365 Exchange.
#Requires Microsoft Exchang Online PowerShell 
$GlobalAdminUPN = Read-Host "Enter Global Admin UPN account"
Connect-ExchangeOnline -UserPrincipalName $GlobalAdminUPN

#Aquire the ExchangeGUID attribute for the source and target mailboxes
$UserAlisas = Read-Host "Enter mailbox identifier"
$SourceMailboxGuid = [string](Get-Mailbox -SoftDeletedMailbox $UserAlisas).ExchangeGuid
$TargetMailboxGuid = [string](Get-Mailbox -Identity $UserAlisas).ExchangeGuid

#Restore Softdeleted mailbox over the new Account's mailbox

New-MailboxRestoreRequest -SourceMailbox $SourceMailboxGuid -TargetMailbox $TargetMailboxGuid -AllowLegacyDNMismatch

#Check the restore job status
Get-MailboxRestoreRequest | Get-MailboxRestoreRequestStatistics