PowerShell and EWS Managed API

Here is a script that lets you download mail objects with attachments from an Exchange mailbox (works with Office 365). First, install Exchange Web Services Managed API 2.2.

# Destination folder
$destinationFolder = "C:\Users\marius\Downloads\Attachment Downloader"

# replace with your email address
$email    = "username@mytenant.onmicrosoft.com"
$username = "username@mytenant.onmicrosoft.com"
$password = "Password123!"

# File extensions to download
$extensions = "pdf","pdfa","doc","docx","dot","dotx","xls","xlsx","ppt","pptx"

# load the assembly
Add-Type -Path "C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll"

# Create Exchange Service object
$s = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2013_SP1)
$s.Credentials = New-Object Net.NetworkCredential($username, $password)
# $s.TraceEnabled = $true
Write-Host "Trying AutoDiscover... "
$s.AutodiscoverUrl($email, {$true})

if(!$s.Url) {
    Write-Error "AutoDiscover failed"
} else {
    Write-Host -ForegroundColor Green "AutoDiscover succeeded - $($s.Url)"

# Create destination folder
$destinationFolder = "{0}\{1}" -f $destinationFolder, (Get-Date -Format "yyyyMMdd HHmmss")
mkdir $destinationFolder | Out-Null

# get a handle to the inbox
$inbox = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($s,[Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox)

#create a property set (to let us access the body & other details not available from the FindItems call)
$psPropertySet = new-object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties)
$psPropertySet.RequestedBodyType = [Microsoft.Exchange.WebServices.Data.BodyType]::Text;

# Find the items
$inc = 0;
$maxRepeat = 50;
do {
    $maxRepeat -= 1;

    Write-Host "Searching for items in mailbox... " -NoNewline
    $items = $inbox.FindItems(100)
    Write-Host -ForegroundColor Green "found $($items.items.Count)"

    foreach ($item in $items.Items)
        # Create mail folder
        $inc += 1
        $mailFolder = "{0}\{1}" -f $destinationFolder, $inc;
        mkdir $mailFolder | Out-Null

        # load the property set to allow us to get to the body
        try {
            Write-Host ("$inc - $($item.Subject)") -ForegroundColor Yellow

            # save the metadata to a file
            $item | Export-Clixml ("{0}\metadata.xml" -f $mailFolder)

            # save all attachments
            foreach($attachment in $item.Attachments) {
                if(($attachment.Name -split "\." | select -last 1) -in $extensions) {
                    Write-Host " - $($attachment.Name) - $([Math]::Round($attachment.Size / 1024))KB"
                    $fileName = ("{0}\{1}" -f $mailFolder, $attachment.Name) -replace "/",""

            # delete the mail item
            $item.Delete([Microsoft.Exchange.WebServices.Data.DeleteMode]::HardDelete, $true)
        } catch [Exception] {
            Write-Error "Unable to load item: $($_)"
} while($items.MoreAvailable -and $maxRepeat -ge 0)

6 thoughts on “PowerShell and EWS Managed API

    1. Hi Leo, actually, I WAS running on Drupal, however now I am actually running om wordpress.com. Reason for change was simply that I didn’t want to bother running anything on my own, just pay for a service.

  1. I don’t even know how I finished up right here, but I
    assumed this submit was once great. I do not recognize who you are however definitely you are going to a well-known blogger for those who are not
    already. Cheers!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s