none
PowerShell Get-PublicFolder - but what about the items themselves?

    Question

  • OK, am I missing something, or is there no way to get the items in a Public Folder, using Get-PublicFolder?

    More detail:

    I've set up some reports that query AD (actually via SharePoint User Profiles, but essentially AD info), to provide information on who belongs to what Distribution Groups, along with department info, so that our Librarians can audit this information and look at who from what department might need to be subscribed to a particular distribution group.

    That works just fine.

    However I find out that the Library have more distribution groups in a Public Folder (so that they can add external people to the distribution groups, without polluting our GAL with external people).

    So I manage to get our Ops team to give me enough permissions to get Get-PublicFolder working, but low and behold, there doesn't seem to be a property or method for returning the items inside the public folder.

    So much googling later....

    There seem to be plenty of solutions around using Outlook (or add-ins to Outlook) to export contacts, etc to a CSV and then using them from there.  But the couple I tried wouldn't export Distribution Groups and anyway, I want to automate this process (and merge with my existing report), so doing the export manually in Outlook each time doesn't make sense.

    Can someone point me in the right direction?

    This is Exchange 2010 SP3 RU3

    Thanks
    Craig

    Wednesday, March 23, 2016 3:22 AM

Answers

All replies

  • When you say 'return the items inside the public folder', do you mean you want to get the individual items?  Or just the count of the items?  I don't believe there's any command to get individual items. The count of the items can be returned with Get-PublicFolderStatistics .

    OWA For SmartPhone

    Wednesday, March 23, 2016 10:07 AM
  • Given that I want to report on who is a member of what, yes, I need the items (in this case distribution groups) themselves., so that I can enumerate the members.
    Wednesday, March 23, 2016 7:55 PM
  • Hi,

    We can use Get-PublicFolderItemStatistics to view the items of public folder, we can view the subject, message size, attachments and etc. More details about it, please refer to: https://technet.microsoft.com/en-us/library/aa997949(v=exchg.150).aspx

    However, the contacts (group) under public folder isn't same with distribution list in AD. We can't use Get-DistributionGroupMemberto list the members of DG. It's more easy to view and modify the items on Outlook or OWA.


    Please remember to mark the replies as answers if they help, and unmark the answers if they provide no help. If you have feedback for TechNet Support, contact tnmff@microsoft.com.

    Allen Wang
    TechNet Community Support

    Thursday, March 24, 2016 2:49 AM
    Moderator
  • Thanks for that Allen.  So how would I use PowerShell to pull the Contact Groups from a Public Folder via OWA?

    I've found a reference on one way to connect/login, but is there a proper (RESTful?) API that I can get PowerShell to query?

    https://blogs.technet.microsoft.com/meamcs/2015/03/06/powershell-script-to-simulate-outlook-web-access-url-user-logon/

    Thursday, March 24, 2016 3:24 AM
  • Hello again Craig - sorry I haven't been able to get back to this thread for a while. Yes, there is an API you can use for this. I don't have time to create a new script today, but I wrote this a while back, and it shows how you can get at Public Folder contents and Contact items. It might be enough to get you started

    http://blog.leederbyshire.com/2015/05/06/a-powershell-script-to-copy-the-contacts-from-an-exchange-public-folder-to-a-mailbox-contacts-folder/


    OWA For SmartPhone

    • Marked as answer by Craig Humphrey Thursday, March 31, 2016 12:16 AM
    Tuesday, March 29, 2016 12:32 PM
  • Thanks Lee, that looks like a good start.  I'll give it a go and post a follow-up.
    Tuesday, March 29, 2016 8:05 PM
  • OK, gave that a try, but the Members object is coming back empty on the Contact Groups (IPM.DistList).  Any ideas?
    Tuesday, March 29, 2016 11:50 PM
  • EWS tries to make things easier by only returning basic properties by default. To get the members of a Contact Group, use

    $ews.ExpandGroup($item.Id)

    I've used the same identifiers as in my own script - if yours are different, show me what you have so far, and I'll help you make the change.

    Note that this function will produce an error for items that aren't Contact Groups - if you want to handle that, rather than ignore it, again, you'll need to show me what you have so far.


    OWA For SmartPhone

    • Marked as answer by Craig Humphrey Thursday, March 31, 2016 12:16 AM
    Wednesday, March 30, 2016 9:42 AM
  • Thenks Lee!  Worked a treat, or at least got me heading in the right direction.

    I ended up with this:

    param([Parameter(Position=0,Mandatory=$True,HelpMessage="The path of the folder to copy")]
          [string]$folderPath,
          [Parameter(Position=1,Mandatory=$True,HelpMessage="Email Address of the target Mailbox")]
          [string]$mailbox
    )
    
    # Add the snapin in case we're in the plain (i.e. non-Exchange Management) Shell
    
    # Try the E2007 snapin first
    Add-PSSnapin Microsoft.Exchange.Management.PowerShell.Admin -ErrorAction SilentlyContinue
    # Then try the E2010 snapin
    Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010 -ErrorAction SilentlyContinue
    # This assumes you have v2.0 of the EWS Managed API
    Add-Type -Path "C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll"
    
    # Supply the folder path, then try to locate it
    
    $script:ews = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService("Exchange2007_SP1")
    # $ews.ImpersonatedUserId = New-Object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $mailbox)
    $script:ews.AutodiscoverUrl($mailbox)
    $rootFolderId = new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::PublicFoldersRoot)
    $folder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($script:ews, $rootFolderId)
    $arrPath = $folderPath.Split("\")
    for ($i = 1; $i -lt $arrPath.length; $i++)
    {
      $folderView = New-Object Microsoft.Exchange.WebServices.Data.FolderView(1)
      $searchFilter = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.FolderSchema]::DisplayName, $arrPath[$i])
      $findFolderResults = $script:ews.FindFolders($folder.Id, $searchFilter, $folderView)
      if ($findFolderResults.TotalCount -gt 0)
      {
        $folder = $findFolderResults.Folders[0]
      }
      else
      {
        "$folderPath Not Found"
        exit
      }
    }
    
    function appendName($current, $additional)
    {
        if ($current -eq "")
        {
            return $additional
        } 
        else 
        {
            return $currentSource + '|' + $member.Name
        }
    }
    
    function getGroupMembers($aGroup, [string]$currentGroup, [string]$currentSource)
    {
        switch ($aGroup.MailBoxType) {
            "publicgroup"  { 
                $expandGroup = $script:ews.ExpandGroup($aGroup.Address) 
            }
    
            Default {
                # contactgroup and IPM.DistList
                 $expandGroup = $script:ews.ExpandGroup($aGroup.id)
                 }
        }
        
        
         $groupMembers = $expandGroup.Members
         foreach ($member in $groupMembers)
         {
            switch ($member.MailBoxType) {
                "mailbox" { 
                    if ($member.Address -like '/o=*')
                    {
                        Write-Output ('"{0}","{1}","Former Internal User","{2}"' -f $currentGroup.Trim(), $member.Address, $currentSource)
                    }
                    else {
                         Write-Output ('"{0}","{1}","Internal User","{2}"' -f $currentGroup.Trim(), $member.Address, $currentSource)
                    }
                   
                }
                "contact" { 
                    Write-Output ('"{0}","{1}","External User","{2}"'  -f $currentGroup.Trim(), $member.Address, $currentSource)
                }
                "publicgroup" { 
                    $temp = appendName $currentSource $member.Name
                    getGroupMembers $member  $currentGroup  $temp
                }
                "contactgroup" {
                    $temp = appendName $currentSource $member.Name
                    getGroupMembers $member  $currentGroup  $temp
                }
                default { 
                    Write-Output ('"{0}","{1}","Unknown User({2})","{3}"' -f $currentGroup.Trim(), $member.Address, $member.MailBoxType, $currentSource)
                 }
            }
         }
    }
    
    Write-Output '"Group","Email","Type","Source"'
    
    $itemView = New-Object Microsoft.Exchange.WebServices.Data.ItemView(1000)
    do
    {
      $findItemResults = $script:ews.FindItems($folder.Id, $itemView)
      foreach ($item in $findItemResults.Items)
      {
          if ($item.ItemClass -eq "IPM.DistList")
          {
            getGroupMembers $item  $item.DisplayName  ""
           }
      }
    }
    while ($findItemResults.MoreAvailable)

    Which spits out a nice CSV format.  If the client is happy, I'll push it straight into SQL and include it in the overnight processing for the reports.

    Thanks again!
    Craig

    Thursday, March 31, 2016 12:15 AM
  • Thanks for sharing the script - it looks like you've done plenty of research :-)

    OWA For SmartPhone

    Thursday, March 31, 2016 12:07 PM
  • Yeah, had to dig around a bit and as usual, you don't know what to look for until someone (you) points in the right direction.  Pointing me a ExpandGroup finally gave me something that returned decent MSDN search results....

    Teach me to prefix all my searching with PowerShell...

    Thanks again!

    Thursday, March 31, 2016 8:10 PM
  • Sadly - That URL of Lee's returns a 404...

    Thomas Lee <DoctorDNS@Gmail.Com>

    Wednesday, May 02, 2018 4:01 PM
  • Hello Thomas. I brought the page back up again temporarily. I don't have as much time for Exchange as I used to (I now have a young son :-)), so I've lost my MVP status. That also means I don't get free copies of the new versions to play with any more, so I can't keep my scripts updated.

    OWA For SmartPhone

    Thursday, May 03, 2018 9:38 AM