The following script can be used to upload files from the file system to a named folder in Exchange Public Folders. Each file will be uploaded in turn, and if successful, the source file deleted. Any files that fail to be uploaded are listed when the script completes, and remain in the file system.
Other parameters to change are highlighted in green.
In this case the file failed to upload because the file size exceeded that allowed by Exchange. Note that the warm up time for this script adds to the average value you see of 4.3 seconds. Uploading batches of 5,000 items, 1-2GB in size in total typically takes 0.5 seconds per file in my production environment.
The Script
The Public Folders store name highlighted in yellow must be changed to the value you see in Outlook when browsing Public Folders:Other parameters to change are highlighted in green.
# Get Start Time Write-Host "-----------------------------" $start = (Get-Date) Write-Host ("Start time: " + $start) Write-Host "-----------------------------" # 0 Setup source and target (leave no trailing \) $source = "C:\Apps\Upload to PF\Batch 1" $targetFolder = "All Public Folders\Test\Batch 1" $failArray = @() # 1 Initiate connection to Outlook $outlook = new-object -comobject Outlook.Application $mapi = $outlook.GetNamespace("MAPI") # 2 Connect to PF $pfStore = $mapi.Session.Stores.Item("Public Folders - Jonny.Trees@youremailaddress.com") # 3 Connect to folder in PF $currentFolder = $pfStore.GetRootFolder() $folderPathSplit = $targetFolder.Split("\") for ($x = 0; $x -lt $folderPathSplit.Length; $x++) { $currentFolder = $currentFolder.Folders.Item($folderPathSplit[$x]) } if ($currentFolder -eq $null) { ("Could not find folder: " + $folderPath) return } Write-Host "" ("Found folder: " + $currentFolder.FolderPath) Write-Host "" # 4 Get the source files and volume $volume = ("{0:N2}" -f ((Get-ChildItem -path $source -recurse | Measure-Object -property length -sum ).sum /1GB) + " GB") $volumeMB = ("{0:N2}" -f ((Get-ChildItem -path $source -recurse | Measure-Object -property length -sum ).sum /1MB) + " MB") ("Volume to be moved: " + $volume + ", " + $volumeMB) Write-Host "" $source = $source + "\*" $sourceFiles = Get-ChildItem -path $source -include *.msg # 5 Copy the files $counter = 1 $failCounter = 0 foreach($file in $sourceFiles) { try { $item = $mapi.OpenSharedItem($file) Write-Host -nonewline ("Moving file " + $counter + " of " + $sourceFiles.Count + " ") [void]$item.Move($currentFolder) Remove-Item -literalpath $file Write-Host "Success" } catch { $failArray += $file $failCounter = $failCounter + 1 Write-Host "Fail" } finally { $counter = $counter + 1 } } [System.Media.SystemSounds]::Exclamation.Play(); # Get End Time $end = (Get-Date) $scriptExecutionTime = $end - $start # Print results Write-Host "" Write-Host "-----------------------------" Write-Host ("End time: " + $end) Write-Host "-----------------------------" Write-Host "" Write-Host ("Fail count: " + $failCounter) Foreach ($file in $failArray) { Write-Host $file } Write-Host "" Write-Host ("" + ($counter - $failArray.Count -1 ) + " of " + ($counter - 1) + " files totalling " + $volume + " were uploaded successfully") Write-Host ("Script execution time: " + $scriptExecutionTime.hours + " hours, " + $scriptExecutionTime.minutes + " minutes and " + $scriptExecutionTime.seconds + " seconds") Write-Host ("Average time per file: " + [math]::Round($scriptExecutionTime.totalseconds/$sourceFiles.Count,1) + " seconds") |
Output
The output of the script is as follows.----------------------------- Start time: 06/30/2015 11:32:32 ----------------------------- Found folder: \\Public Folders\All Public Folders\Test\Batch 1 Volume to be moved: 0.02 GB, 20.03 MB Moving file 1 of 3 Success Moving file 2 of 3 Fail Moving file 3 of 3 Success ----------------------------- End time: 06/30/2015 11:32:45 ----------------------------- Fail count: 1 C:\Apps\Upload to PF\Batch1\Large file.msg 2 of 3 files totalling 0.02 GB were uploaded successfully Script execution time: 0 hours, 0 minutes and 13 seconds Average time per file: 4.3 seconds |