Welcome fellow Sys Admins.
After spending all day trawling through the internet for a way to easily read through the mail in a O365 mailbox using PowerShell and gathering code from all over the place to do it I thought it would be good to upload my code to for everyone to share and hopefully you end up here at the start of your quest and not at the end 🙂
This code will allow you to read email directly from O365 without the need to install Outlook. All you need is the .dll file from the Microsoft Exchange Web Services Managed API 2.2 which you can download here. Ensure that you update the file path to the dll file if it is different to what is defined in the code.
Credit goes to the following post from ‘Steve Goodman’s Exchange & Office 365 Blog’ for the majority of the code,
How to export Email Headers from Exchange using Powershell
Credit also to Exchange Managed API autodiscover with Powershell resolving the issue with the security error when trying to autodiscover to O365 by adding the $TestUrlCallback function. While you could simply just call autodiscover with the second variable as $true you are basically trusting any redirections that may happen.
# Written by Ben Penney https://sysadminben.wordpress.com $mail="username@domain.com" $password="password" # Set the path to your copy of EWS Managed API $dllpath = "C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll" # Load the Assemply [void][Reflection.Assembly]::LoadFile($dllpath) # Create a new Exchange service object $service = new-object Microsoft.Exchange.WebServices.Data.ExchangeService #These are your O365 credentials $Service.Credentials = New-Object Microsoft.Exchange.WebServices.Data.WebCredentials($mail,$password) # this TestUrlCallback is purely a security check $TestUrlCallback = { param ([string] $url) if ($url -eq "https://autodiscover-s.outlook.com/autodiscover/autodiscover.xml") {$true} else {$false} } # Autodiscover using the mail address set above $service.AutodiscoverUrl($mail,$TestUrlCallback) # create Property Set to include body and header of email $PropertySet = New-Object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties) # set email body to text $PropertySet.RequestedBodyType = [Microsoft.Exchange.WebServices.Data.BodyType]::Text; # Set how many emails we want to read at a time $numOfEmailsToRead = 100 # Index to keep track of where we are up to. Set to 0 initially. $index = 0 # Do/while loop for paging through the folder do { # Set what we want to retrieve from the folder. This will grab the first $pagesize emails $view = New-Object Microsoft.Exchange.WebServices.Data.ItemView($numOfEmailsToRead,$index) # Retrieve the data from the folder $findResults = $service.FindItems([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox,$view) foreach ($item in $findResults.Items) { # load the additional properties for the item $item.Load($propertySet) # Output the results "From: $($item.From.Name)" "Subject: $($item.Subject)" "Body: $($Item.Body.Text)" "References: $($item.References)" "InternetMessageID: $($item.InternetMessageID)" "InternetMessageHeaders:" # Display the headers - using a little foreach loop $item.InternetMessageHeaders|foreach{"$($_.Name): $($_.Value)"} "" } # Increment $index to next block of emails $index += $numOfEmailsToRead } while ($findResults.MoreAvailable) # Do/While there are more emails to retrieve
Update: I just found another blog where someone has done similar with some additional coding for filtering mail based on subject and read status,
Check/Read Messages Exchange/Office365 Inbox with Powershell
So check that out as well!
Hi Ben,
Can you please put a license for this code please ?
LikeLike
I guess you mean usage license? Feel free to use any of my code and give credit where credit is due.
LikeLike
Hi Ben,
I’m testing the script, but it seems to hang at this line:
$service.AutodiscoverUrl($mail,$TestUrlCallback)
I even tried accessing the URL in $TestUrlCallback from a browser, but this yields a 456 error. I’ll keep looking, but has the URL changed since this post?
Thanks.
LikeLike
The error is actually occurring at: $findResults = $service.FindItems([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox,$view)
The message reads:
“The Url property on the ExchangeService object must be set.”
LikeLike
Hi Ron. Thanks for the feedback.
This script was used quite a while ago and the back end system has probably changed significantly. Unfortunately I no longer administer an O365 system to do any work on this code.
LikeLike
This blog,
https://geekdudes.wordpress.com/2019/04/23/powershell-extract-email-body-stored-in-custom-folder-using-ews-office-365/
has just done some work using this code so maybe take a look at what he has done with it.
Good luck!
LikeLike