Thursday, February 25, 2010

Create a folder under the Inbox if one doesn't existing using Powershell and the EWS Managed API

I've covered this one before using other Exchange API's and versions but here's a potentially useful script if you want to create a folder in a Mailbox with a powershell/EWS script. To avoid any errors it does a search of the target folder where your going to create the subfolder first. Although this isn't 100% needed as the error you will get if it does exist is pretty self explanatory its good practice to do this anyway

The script like many others I've posted uses the currently logged on user to then access another mailbox using Delegate access. I've included two versions one is feed via the Get-Mailbox cmdlet so this could potentially be used to add a folder for every mailbox on a particular server (as long as you have rights). I've put a download of the script here the script which if feed via get-mailbox looks like

function CreateFolder($MailboxName) {
"Mailbox Name : " + $MailboxName
$folderid = new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox,$MailboxName)
$ibInboxFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderid)
$fvFolderView = new-object Microsoft.Exchange.WebServices.Data.FolderView(1)
$SfSearchFilter = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.FolderSchema]::DisplayName,$newFolderName)
$findFolderResults = $service.FindFolders($ibInboxFolder.Id,$SfSearchFilter,$fvFolderView)
if ($findFolderResults.TotalCount -eq 0){
"Doesn't Exist"
$NewFolder = new-object Microsoft.Exchange.WebServices.Data.Folder($service)
$NewFolder.DisplayName = $newFolderName
# $NewFolder.Save($ibInboxFolder.Id.UniqueId)
"Folder Created"
}
else{
"Folder Already Exist - Do Nothing"
}
}


$newFolderName = "mynewfolder123"

$dllpath = "C:\Program Files\Microsoft\Exchange\Web Services\1.0\Microsoft.Exchange.WebServices.dll"
[void][Reflection.Assembly]::LoadFile($dllpath)
$service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2007_SP1)
$frun = $true


Get-mailbox | foreach-object {
$WindowsEmailAddress = $_.WindowsEmailAddress.ToString()
if ($frun -eq $true) {
$frun = $false
$service.AutodiscoverUrl($WindowsEmailAddress)
}
CreateFolder($WindowsEmailAddress)

22 comments:

Anonymous said...

Can I pipe multiple users to this script ?
I see $MailboxName = $args[0], but still the Script takes the logged on user even after I run it with an email address as a parameter.

Anonymous said...

oops, the comment was meant to be for "Digging a little deeper to look to see if a mailbox is being used with the EWS Managed API and Powershell " script.

Eric Twitchell said...

Great script. Is there a way to set the home page address for this new folder and make it the default view?

Clayton said...

I would also be very interested in setting a home page address and setting it as default

Anonymous said...

When attempting to run this, I get "Could not establish trust relationship for the SSL/TLS secure channel." Request failed.

Glen said...

This means you using a Self Signed Certificate. If you have a look at http://gsexdev.blogspot.com/2009/04/using-ews-managed-api-with-powershell.html this has an example of code you can add to get around this problem. Another option is to use the following powershell module http://www.messageops.com/downloads/MessageOps-Exchange-Module.zip and then use

New-MessageOps.MailboxFolder -p $ewsprofile -FolderPath "\\Inbox" -FolderName "newFolder123"

Cheers
Glen

Jon said...

Glen - I have tried the script but cannot get it to work. I am using EWS 1.1 on Exchange 2010. I have amended the path to EWS but the script replies "Doesn't exist" "Folder created" without creating the folder? There are no error messages. Am I missing something?

Glen said...

It sounds like you maybe targeting the wrong mailbox. What if you run the script multiple times does it say the folder exists on the second run? Have you tried using the module instead ?

Cheers
Glen

Jon said...

I've got it working...

The folder wasn't created until this line:-

#$NewFolder.Save($ibInboxFolder.Id.UniqueId)

was uncommented and then it errored - I amended the line to:-

$NewFolder.Save($ibInboxFolder.Id)

... and it seems happy! And so am I!

Thanks for your time. Jon.

Clayton said...

Jon, could you post your code? I'm close, but can't get mine to run.

Anonymous said...

Is there a way to search and, respectively, create sub-sub-folders in one go?

E.g. for searching I've tried using "Parent\Child", "Parent/Child" etc., but no joy, no search results are returned. (The folders do exist and I can find them with FindFolders() when used individually).

Glen said...

Not 100% sure i understand you can do a deep traversal search will will find all folders under one particular root. In regards to creating folders you need to create the parent first and obtain the EWSID to allow you to then create subs of that folder so you couldn't create parent and child in one go you would need multiple requests.

Cheers
Glen

Bernat Soler said...

Is there any way to make this script run in a Exchange 2010 server? Seems that in a Exchnage 2010 CAS the "Microsoft.Exchange.WebServices.dll" does not exist ... any idea? Thanks in advance

Pat said...

Glen, is there anyway after a folder has been created under the Inbox that you can extract the date / time of when it was created?

Getting the Deep FolderTraversal will show you the folders, but no date / time info exists there.
Thanks,

Glen said...

You need to use the PR_CREATION_TIME extended property which you should be able to include via a propertySet in you Deep Traversal.

Cheers
Glen

Unknown said...

Thanks for the script Glen!

I'm having trouble with 1.1 and Exchange 2010 SP1 as well. At first I was using my own email address and it kept erroring on the BIND command telling me my "object" doesn't exist. I finally took a break from that and moved on to automating it thinking maybe I was formatting the email wrong or something dumb like that. After implementing a TRY/CATCH so it would continue without error I noticed that the script was adding the folder for about 1/3 of my users.

Why would it error and say object not found on the other 2/3's of my users?

Any idea?

Exception calling "Bind" with "2" argument(s): "The specified object was not found in the store."
At line:4 char:72
+ $ibInboxFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind <<<< ($service,$folderid)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException

Anonymous said...

Just FYI:

You can also change the type of folder by modifying this line:

$NewFolder = new-object Microsoft.Exchange.WebServices.Data.Folder($service)

Change .Folder($service) to .ContactsFolder($service) or .CalendarFolder($service)

If you do this you should also update the line that tells it to go in the inbox.

I used this script with 2010 SP1 to create contacts folders and calendars for each user that we synch with a 3rd party solution. This gives us fully synched contacts.

Aaron Grussner said...
This comment has been removed by the author.
Anonymous said...

Hi Glen, once a folder like this is created is it possible to apply a different retention policy to the new folder than what is applied to the rest of the Inbox? This is on Exchange 2010. Thanks

Glen Scales said...

Yes have a look at http://blogs.msdn.com/b/akashb/archive/2011/08/11/stamping-retention-policy-tag-using-ews-managed-api-1-1-from-powershell-exchange-2010.aspx

Cheers
Glen

Anonymous said...

Can EWS be used to create a folder in a user's archive mailbox? Thanks.

Glen Scales said...

Yes all long as you get the Parent Archive folder EWSid

eg

Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::ArchiveMSGFolderRoot

http://msdn.microsoft.com/en-us/library/microsoft.exchange.webservices.data.wellknownfoldername%28v=exchg.80%29.aspx

Cheers
Glen