InfiniTec - Henning Krauses Blog

Don't adjust your mind - it's reality that is malfunctioning

How to get the number of unread mails from multiple mailboxes using the EWS Managed API and PowerShell

Interesting question in the Exchange development forum today: How do I get the number of unread messages in the inbox folder from a number of mailboxes? The questioner wants to send a text message to each owner of a mailbox notifying him of the number of unread mails in his inbox. The requirement was to do this with PowerShell. So, here is a quick solution for this problem:

param ([string] $inputFile, [System.Management.Automation.PSCredential] $credential)

$ErrorActionPreference = "Stop"

if (($inputFile -eq [String]::Empty) -or (Test-Path $inputFile) -eq $false) 
    throw "Invalid file specified ({0})." -f $inputFile

[Reflection.Assembly]::LoadFrom("C:\Program Files\Microsoft\Exchange\Web Services\1.1\Microsoft.Exchange.WebServices.dll")

$service =  New-Object Microsoft.Exchange.WebServices.Data.ExchangeService -ArgumentList([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010_SP1)

if ($credential -ne $null) 
    $service.Credentials = $credential.GetNetworkCredential()
    $service.UseDefaultCredentials = $true;

function GetUnreadInboxMails([string] $emailAddress) 
    $service.AutodiscoverUrl($emailAddress, {$true});
    $maibox = New-Object Microsoft.Exchange.WebServices.Data.Mailbox($emailAddress)
    $folderId = New-Object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox, $mailbox)
    $folder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service, $folderId);
    $result = New-Object PSObject -Property @{ 
        EmailAddress = $emailAddress
        UnreadMailCount=  $folder.UnreadCount;
    return $result;

function ProcessResult($entry) 
    "Mailbox: {0}" -f $entry.EmailAddress
    "Unread Mails: {0}" -f $entry.UnreadMailCount

$addresses = Import-Csv $inputFile

$addresses | % {GetUnreadInboxMails($_.MailAddress)}  | % {ProcessResult ($_)} 

Just paste this script into an editor and save it as ps1 file.

The script mainly consists of two function: GetUnreadInboxMails and ProcessResult. The former method retrieves the number of unread mails in the inbox of the mailbox of the specified user. The number of unread mails can be retrieved from a Folder instance: The UnreadCount property. The method returns the number of unread mails along with the mail address of the current mailbox. The other important function is the ProcessResult method. In this script it merely dumps the result to the console. The questioner in the post linked above can use this function to call his HTTP service to send a text message.

The script has two parameters:

  1. The name of a CSV file containing the list of mailboxes to process. The first line should contain the column name “MailAddress” somewhere. The following lines should contain the email address of the mailbox in this column.
  2. A PSCredential object containing valid credentials to use for the Exchange access.

The credential used for the script needs read access to the inbox folder of each mailbox specified in the file.

Posted by Henning Krause on Monday, July 25, 2011 7:56 PM, last modified on Monday, July 25, 2011 7:56 PM
Permalink | Post RSSRSS comment feed

Comments (10) -

On 8/12/2011 10:26:01 AM Vandewaetere wrote:


Just what I needed.
However, how does one create a PSCredential object?
And how do I return this as a paramater to the powershell script?

I never used powershell before, so any help would be very much appreciated!


On 8/12/2011 10:30:35 AM hkrause wrote:


You can use the Get-Crendential cmdlet.

On 8/16/2011 1:49:10 PM Vandewaetere wrote:


I've just noticed,
The line $maibox = ... doesn't seem to do anything.
I thought this variable should have been $mailbox, but then I get an error.

Thoughts about this anyone?

On 8/16/2011 1:53:45 PM Vandewaetere wrote:


Got it working, apperently it's all about the credentials.

On 12/23/2011 9:06:18 PM Jon Wiswell wrote:

Jon Wiswell

So I'm not sure what I'm doing wrong... when it does the results, it "shows" each individual mailbox, but it's returning the unread count for the provided credential for all mailboxes.

What I'm doing is:

> $credential = get-credential
> .\script.ps1 d:\test.csv $credential

We're running Exchange 2007 SP3, so I have modified line 12 to reflect "Exchange2007_SP1"

On 12/23/2011 10:09:41 PM Jon Wiswell wrote:

Jon Wiswell

Found the issue... line 28 has $maibox instead of $mailbox

On 3/20/2014 4:30:17 PM Ted wrote:


Thanks work great, how could i get this out to a properly formatted csv file..


On 4/17/2014 4:22:46 PM Luuk wrote:


I guess by adding >output.txt at the end.

On 4/17/2014 11:28:01 AM Luuk wrote:


On 2013 here and new to PS etc...
Installed EWS 2.0 and changed the EWS dll refering line accordingly. Also changed required Exchange version in the script. Not sure how to interpreter the credential attribute. I'm struggling with this error:
% : Exception calling "AutodiscoverUrl" with "2" argument(s): "A valid SMTP address must be specified."
At C:\root\GetUnreadInboxMails.ps1:47 char:14
+ $addresses | % {GetUnreadInboxMails($_.MailAddress)}  | % {ProcessResult ($_)}
+              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (Smile [ForEach-Object], MethodInvocationException
    + FullyQualifiedErrorId : ServiceValidationException,Microsoft.PowerShell.Commands.ForEachObjectCommand

On 12/11/2014 12:06:10 PM tony wrote:


Bonjour, j'ai un souci avec le script sur un Exchange 2013 CU6. En gros il fonctionne bien avec une adresse mail mais dès que je la change j'ai des erreurs. Avez-vous déjà eu ce type d'erreurs? Merci

 +Pingbacks and trackbacks (2)