Office 365 Groups – Office 365 for IT Pros https://office365itpros.com Mastering Office 365 and Microsoft 365 Mon, 08 Apr 2024 16:23:28 +0000 en-US hourly 1 https://i0.wp.com/office365itpros.com/wp-content/uploads/2024/06/cropped-Office-365-for-IT-Pros-2025-Edition-500-px.jpg?fit=32%2C32&ssl=1 Office 365 Groups – Office 365 for IT Pros https://office365itpros.com 32 32 150103932 How to Enable Users to Receive Copies of Email They Send to Microsoft 365 Groups https://office365itpros.com/2021/12/14/outlook-groups-receive-copies/?utm_source=rss&utm_medium=rss&utm_campaign=outlook-groups-receive-copies https://office365itpros.com/2021/12/14/outlook-groups-receive-copies/#comments Tue, 14 Dec 2021 01:00:00 +0000 https://office365itpros.com/?p=52704

Outlook Groups Still Popular

When Microsoft launched Office 365 Groups in November 2014, the plan was to use these objects to replace distribution groups. Like all plans, events took over and forced change. Distribution groups remain intact (and Microsoft is updating their functionality) and the role of Office 365 Groups (renamed Microsoft 365 Groups in April 2020) has evolved to become a membership and identity service for apps like Teams, Power BI, and Yammer. However, devotees of Outlook can still use Microsoft 365 Groups in Outlook and OWA (where they have the moniker “Outlook Groups”), complete with a dedicated menu bar, presence in Outlook favorites, and section in Outlook resources. Outlook mobile also supports Outlook Groups.

An Outlook group has the following characteristics:

Like other Microsoft 365 Groups, an Outlook group has a SharePoint Online team site, shared OneNote notebook, and can connect to Planner.

Subscribers and Copies

An Outlook groups distribute copies of messages sent to the group based on its subscriber list. The AutoSubscribeNewMembers group setting controls if Exchange adds new group members to the subscriber list automatically. Another setting called AlwaysSubscribeMembersToCalendarEvents controls if group members receive copies of calendar events (sometimes it’s necessary to update the groups used by Teams to change these settings).

Users can control if they want to be on a group’s subscriber list with the Follow in Inbox feature. Figure 1 shows the Outlook desktop settings; OWA presents the settings differently, but the same effect applies. In this instance, I am not a subscriber to the group because I don’t receive all email and events. However, I do receive copies of any replies posted to messages I send to the group.

Group settings in Outlook for Windows
Figure 1: Group settings in Outlook for Windows

Senders and Copies

In 2017, Microsoft changed the way Groups processed email when it delivered copies to subscribers to stop delivering a copy to the message sender for new messages and replies. On the surface, the change was reasonable because senders have copies of messages in their Sent Items folder and senders can always add themselves as a CC or BCC recipient if they want Exchange to deliver a copy of a specific message to their inbox. Well-intentioned as the change was, it upset many people who liked receiving a copy of anything they posted to groups.

InA few months ago, Microsoft introduced a way to allow users to receive copies of their messages posted to Outlook groups. The requirements are:

  • The user or an Exchange administrator must update their mailbox settings to set EchoGroupMessageBackToSubscribedSender to True. As the name implies, the setting controls if the Exchange transport service echoes messages sent to a group by a subscribed sender. By default, this setting is False.
  • The user must subscribe to each group for which they wish to receive copies of their posted messages.

I can’t find any message center notification covering the use of the EchoGroupMessageBackToSubscribedSender setting (it’s entirely possible that I missed it). However, from the “common tasks to manage Microsoft 365 groups” page, I can’t find any other Microsoft reference to the cmdlet except in an October 29 change in GitHub to a page covering Hybrid deployment. Other references exist elsewhere, such as this August 31 Stack Overflow discussion. It’s curious that Microsoft doesn’t document this capability more thoroughly.

User Updates

User can update their mailbox settings through OWA options. Go to the Groups section and set the Send me a copy of email I send to a group option (Figure 2).

OWA setting controlling if users receive copies of messages they post to Outlook groups
Figure 2: OWA setting controlling if users receive copies of messages they post to Outlook groups

Administrators can do the same by running the Set-MailboxMessageConfiguration cmdlet.

Set-MailboxMessageConfiguration -Identity Kim.Akers -EchoGroupMessageBackToSubscribedSender $True

In either case, the setting covers all Outlook groups and can take up to an hour before the change is effective and Exchange will deliver a copy of any message posted by the user to the groups they subscribe to.

Users can choose if they want to subscribe to group and now have control over if they receive copies of their own messages. I am loathe to recommend that administrators should step in to update subscriber settings on a group-wide basis because it means that you would overwrite the settings for people who have opted out of receiving copies of group email and events. However, a need might arise to make everyone a subscriber and update their mailbox settings to allow them to receive copies of their own messages. If so, this PowerShell works.

# Update group subscriber list with all members and set their mailboxes to receive copies of messages posted to Outlook groups
$Group = Read-Host "What group do you want to update?"
Write-Host "Checking" $Group "..."
$GroupId = (Get-UnifiedGroup -Identity $Group -ErrorAction SilentlyContinue).ExternalDirectoryObjectId
If (!($GroupId)) { Write-Host "Sorry... we can't find" $Group "... exiting" ; break}
[array]$GroupMembers = Get-UnifiedGroupLinks -Identity $GroupId -LinkType Member
Write-Host "Adding group members as subscribers to" $Group
Add-UnifiedGroupLinks -Identity $GroupId -LinkType Subscriber -Links $GroupMembers.PrimarySmtpAddress
Write-Host "Updating mailbox settings for group members to allow them to receive copies of their messages posted to the group"
$GroupMembers | ForEach-Object { Set-MailboxMessageConfiguration -Identity $_.ExternalDirectoryObjectId -EchoGroupMessageBackToSubscribedSender $True }

One interesting thing about this code is that you do not need to call Add-UnifiedGroupLinks to add each group member to the subscriber list. If you have an array of members, which we do after calling Get-UnifiedGroupLinks to fetch the member list, you can use that as the input and Add-UnifiedGroupLinks will multiple members with one call.

More Updates for Groups

In closing, let me note two other changes coming soon to Outlook Groups. First, MC302487 (December 8) says that users assigned the Send As permission for a group will no longer have to select the group name when sending messages from the group. This change applies to OWA only and roll-out begins in mid-January. Second, MC303512 (December 10) brings equally important news that instead of displaying a folder icon for an Outlook group, OWA will use the Groups icon from mid-December (this change hasn’t turned up in my targeted release tenant yet). I’m sure the new icon will make all the difference.


Learn more about how Office 365 really works on an ongoing basis by subscribing to the Office 365 for IT Pros eBook. Our monthly updates keep subscribers informed about what’s important across the Office 365 ecosystem.

]]>
https://office365itpros.com/2021/12/14/outlook-groups-receive-copies/feed/ 1 52704
Speeding Up the Groups and Teams Activity Report by Replacing PowerShell with Graph API Calls https://office365itpros.com/2021/06/09/speed-access-large-group-sets-graph/?utm_source=rss&utm_medium=rss&utm_campaign=speed-access-large-group-sets-graph https://office365itpros.com/2021/06/09/speed-access-large-group-sets-graph/#comments Wed, 09 Jun 2021 02:31:00 +0000 https://office365itpros.com/?p=50174

Grappling with PowerShell

Sometimes I hate PowerShell. Not the language itself, just my ineptitude, or my inability to remember how to do things, or the speed of some cmdlets which deal with objects like mailboxes and groups. It’s not that the cmdlets are inefficient. They do a lot of work to retrieve information about objects, so they are slow.

This is fine for ad-hoc queries or where you only need to process a couple of hundred mailboxes or groups. The problem is accentuated as numbers grow, and once the need exists to process thousands of objects, some significant time is spent waiting for cmdlets to complete, meaning that scripts can take hours to run.

Microsoft has made significant progress in the Exchange Online PowerShell module to introduce faster cmdlets like Get-ExoMailbox and Get-ExoMailboxStatistics. These REST-based cmdlets are faster and more robust than their remote PowerShell cousins and these improvements are ample justification for the work needed to revisit and upgrade scripts. The module also supports automatic renewal of sessions to Exchange Online and the Security and Compliance endpoints, so it’s all good.

The Sloth of Get-UnifiedGroup

Things aren’t so impressive with Get-UnifiedGroup, which retrieves details about Microsoft 365 Groups. Reflecting the use of Microsoft 365 groups, Get-UnifiedGroup is a complex cmdlet which assembles details from Azure AD, Exchange Online, and SharePoint Online to give a full picture of group settings. Running Get-UnifiedGroup to fetch details of 200 groups is a slow business; running the cmdlet to fetch details of 10,000 groups is a day-long task. The Get-Team cmdlet is no speedster either. In their defense, Microsoft designed these cmdlets for general-purpose interaction with Groups and Teams and not to be the foundation for reporting thousands of objects over a short period.

If you only need a list of Microsoft 365 Groups, it’s also possible to create the list using the Get-Recipient cmdlet.

Get-Recipient -RecipientTypeDetails GroupMailbox -ResultSize Unlimited

Creating a list of groups with Get-Recipient is usually much faster than creating it with Get-UnifiedGroup. However, although you end up with a list of groups, Get-Recipient doesn’t return any group-related properties, so you usually end up running Get-UnifiedGroup to retrieve settings for an individual group before you can process it. Still, that overhead can be spread out over the processing of a script and might only be needed for some but not all groups.

The Graph is Quicker

Which brings me to the Microsoft Graph API for Groups. As I’ve pointed out for some years, using Graph APIs with PowerShell is a nice way to leverage the approachability of PowerShell and the power of the Graph. The script to create a user activity report from Graph data covering Exchange, SharePoint, OneDrive, Teams, and Yammer is a good example of how accessible the Graph is when you get over the initial learning curve.

Three years ago, I wrote about a script to find obsolete Teams and Groups based on the amount of activity observed in a group across Exchange Online, SharePoint Online, and Teams. In turn, that script was based on an earlier script which processed only Office 365 Groups. Since then, I have tweaked the script in response to comments and feedback and everything worked well. Except that is, once the script ran in large environments supporting thousands of groups. The code worked, but it was slow, and prone to time-outs and failures.

Speeding Up the Report

The solution was to dump as many PowerShell cmdlets as possible and replace them with Graph calls. The script (downloadable from GitHub) now uses the Graph to retrieve:

  • SharePoint Online site usage data for the last 90 days.
  • A list of Microsoft 365 Groups and a list of team-enabled groups.
  • The owners of a group.
  • The display name of the owners (because the first call returns their Azure AD identifier).
  • Some extended properties of a group not fetched when the group list is returned.
  • Counts for group members and guests (easier to do since Microsoft added advanced queries for directory objects in October 2020).
  • Archived status for teams.

The result is that the script is much faster than before and can deal with thousands of groups in a reasonable period. Fetching the group list still takes time as does fetching all the bits that Get-UnifiedGroup returns automatically. On a good day when the service is lightly loaded, the script takes about six seconds per group. On a bad day, it could be eight seconds. Even so, the report (Figure 1) is generated about three times faster.

Results - Teams and Microsoft 365 Groups Activity Report V5.1
--------------------------------------------------------------   
Number of Microsoft 365 Groups scanned                          : 199    
Potentially obsolete groups (based on document library activity): 121    
Potentially obsolete groups (based on conversation activity)    : 130      
Number of Teams-enabled groups                                  : 72    
Percentage of Teams-enabled groups                              : 36.18%

Total Elapsed time:  1257.03 seconds
Summary report in c:\temp\GroupsActivityReport.html and CSV in c:\temp\GroupsActivityReport.csv
Sample output from the Teams and Groups activity report
Figure 1: Sample output from the Teams and Groups activity report

The only remaining use of an “expensive” cmdlet in the script is when Get-ExoMailboxFolderStatistics fetches information about compliance items for Teams stored in Exchange Online mailboxes. The need for this call might disappear soon when Microsoft eventually ships the Teams usage report described in message center notification MC234381 (no sign so far despite a promised delivery of late February). Hopefully, that report will include an update to the Teams usage report API to allow fetching of team activity data like the number of conversations over a period. If this happens, I can eliminate calling Get-ExoMailboxFolderStatistics and gain a further speed boost.

Some Extra Work but Not Onerous

The downsides of using the Graph with PowerShell are that you need to register an app in Azure Active Directory and make sure that the app has the required permissions to access the data. This soon becomes second nature, and once done, being able to process data faster than is possible using the general-purpose Get-UnifiedGroup and Get-Team cmdlets is a big benefit when the time comes to process more than a few groups at one time.

]]>
https://office365itpros.com/2021/06/09/speed-access-large-group-sets-graph/feed/ 9 50174
How to Create a Report About the Membership of Microsoft 365 Groups (and Teams) https://office365itpros.com/2021/02/23/report-teams-membership/?utm_source=rss&utm_medium=rss&utm_campaign=report-teams-membership https://office365itpros.com/2021/02/23/report-teams-membership/#comments Tue, 23 Feb 2021 01:45:00 +0000 https://office365itpros.com/?p=48387

Writing a Script to Report Microsoft 365 Group Memberships

Updated: 19 January 2023 – See this article for a new version of the script based on the Microsoft Graph PowerShell SDK.

Hot on the heels of the discussion about how to create a printable report listing the membership of a Microsoft 365 group (or team), the question is: “How can I create a report listing the members of all groups in my tenant?” Given the widespread use of Teams, the request is often to report teams membership.

A HTML report of all members in all Microsoft 365 Groups in a tenant

Report Teams membership
Figure 1: A HTML report detailing all members for all the Microsoft 365 Groups in a tenant

The Usual Approach Works, but It’s Slow

It’s a good question, and it’s one that is answered elsewhere, such as Steve Goodman’s take on the topic. However, all the approaches I have seen to date have attacked the problem as follows:

  • Run the Get-UnifiedGroup cmdlet to create a list of groups.
  • For each group, use the Get-UnifiedGroupLinks cmdlet to fetch the membership (and owners).
  • Export the results in a CSV file.

Apart from its slowness, there’s nothing wrong with this approach. The Get-UnifiedGroup cmdlet is a “fat” cmdlet. It fetches a lot of information to deliver the set of properties for each group. And the Get-UnifiedGroupLinks cmdlet is also pretty heavy. Put the two together, and things will be slow. This is fine if you have only a couple of hundred groups to process. It’s not so good when you have thousands.

Process Users, Not Groups

I decided to take a different tack. Instead of processing one group at a time, the script should process users. Basically:

  • Get a list of users from Azure Active Directory. This includes tenant and guest accounts.
  • Drop the accounts that belong to the tenant but aren’t licensed. These include accounts used for room and resource mailboxes, shared mailboxes, and service accounts, none of which will be in group membership.
  • Use Get-UnifiedGroup to return a list of team-enabled groups. Although expensive, at least the call uses a server-side filter, so Exchange Online does the processing to return the set. The set of teams is put into a hash table for quick lookup when we need to know if a group is team-enabled. As noted below, a Graph query is faster at retrieving groups and teams.
  • For each user, use the Get-Recipient cmdlet to fetch a list of Microsoft 365 groups the user belongs to. This sounds as if it should take a lot of processing, but it doesn’t because we can use a server-side filter based on the user’s distinguished name.
  • If some groups are returned, extract information for each group, check if it is team-enabled, and update a PowerShell list with the details.
  • Update another list with summary information about the user, such as how many groups they belong to and a list of the display names for those groups.
  • If the user doesn’t belong to any groups (many guest accounts are in this category), only output the summary data.
  • After processing all users, generate some statistics and create three output files:
    • A HTML report in two sections. First, a listing of group membership with a single line for each group a user belongs to. Second, a one-line summary for each user reporting how many groups they are in and the display names of those groups.
    • A CSV file of the group membership data.
    • A CSV file of the user membership summary data.

The script can be downloaded from GitHub. In testing, it took around a half-second per account (Figure 2), which isn’t too bad considering the amount of processing done.

Creating a Microsoft 365 Groups membership report with PowerShell
Figure 2: Creating a Microsoft 365 Groups membership report with PowerShell

Groups with no members are ignored by the script. These groups might have owners, but the lack of members mean that they are not picked up when checking group membership on a per-user basis.

Searching for Speed in a Teams Membership Report

A script powered by the Graph API will deliver faster results in places like fetching a list of team-enabled groups (using the list groups API). You can also use the Get-MgGroup cmdlet from the Microsoft Graph PowerShell SDK to return the list of team-enabled groups. The set of groups a user belongs to is found using the list user transitive member of API. For example, a call like https://graph.microsoft.com/v1.0/users/{GUID}/transitiveMemberOf returns the set of groups that the account with the object identifier (GUID) is a member of. Using the Microsoft Graph PowerShell SDK, the code to return the set of groups a user belongs to would be something like this:

$User = Get-MgUser -UserId James.Ryan@office365itpros.com
$Uri = "https://graph.microsoft.com/v1.0/users/" + $User.Id + "/transitiveMemberOf "
[array]$UserGroups = Invoke-MgGraphRequest -Uri $Uri -Method Get

I also wrote a Graph version of the script, which you can also find on GitHub. Remember that you must register an app in Azure AD, assign the app the necessary permissions, and create an app secret (or other credentials) before you can use this version. On the upside, the Graph version is faster and scales better for large tenants.


Learn much more about interacting with Microsoft 365 Groups and Teams through PowerShell by subscribing to the Office 365 for IT Pros eBook. Monthly updates keep you up to date with what’s happening across the Microsoft 365 ecosystem.

]]>
https://office365itpros.com/2021/02/23/report-teams-membership/feed/ 7 48387
Printing a Report of Microsoft 365 Group (Team) Membership https://office365itpros.com/2021/02/19/printing-microsoft365-group-membership/?utm_source=rss&utm_medium=rss&utm_campaign=printing-microsoft365-group-membership https://office365itpros.com/2021/02/19/printing-microsoft365-group-membership/#comments Fri, 19 Feb 2021 08:15:00 +0000 https://office365itpros.com/?p=48368

The Sad Decline of Printing

One of the most common requests I get is “how can I print off the membership of a group or team?” On one level, it’s a rather old-fashioned request. Much to the chagrin of printing companies, people don’t print as often as they used to. When I worked at HP, I sat through many presentations about the wonders of printer technology and how ink jets work, but all that business about super-heated injection through microscopic holes of ink configured to an exact chemical specification isn’t quite as popular (or exciting) anymore.

How Apps List Group Membership

Applications list the membership of a Microsoft 365 group in different ways. OWA has quite a nice way of displaying group membership (Figure 1) but misses out that all-important print option.

How OWA lists the membership of a Microsoft 365 Group
Figure 1: How OWA lists the membership of a Microsoft 365 Group

Teams takes much the same approach in its Manage team option (Figure 2) and also neglects to include a printing feature. It’s a little surprising that Teams doesn’t support printing off membership information seeing that so many education establishments use Teams for classes. Then again, Teams pretty well eschews printing everywhere (clearly a member of the anti-ink faction) and leaves it to other apps to print off files like meeting attendance reports.

How Teams lists the membership of a Microsoft 365 Group
Figure 2: How Teams lists the membership of a Microsoft 365 Group

Neither OWA nor Teams reveal much about the members. Some details are exposed, like title and location (Teams), but not a lot.

Code Needed

The solution is to write some code to create a report about group membership. You could do this using PowerShell or the Graph API. There are many examples of PowerShell scripts to attack the problem that can be found on the internet (like this mega-script by Vasil Michev), but there’s always room for another.

The things to remember about Microsoft 365 Groups are:

  • An owner must be a member.
  • Owners and members are stored in two lists. Each list is a set of links back to individual accounts. Dynamic Groups also have two lists; the sole difference is that Azure AD periodically calculates the membership of each list by querying the directory.
  • Microsoft 365 Groups support only tenant accounts and guest accounts as members. No nesting is allowed, probably because of the complexities it might introduce for applications which use Groups as a membership and identity service.

The setup of Microsoft 365 Groups mean that they are much easier to process than Exchange distribution groups. We need to:

  • Fetch all the members and fetch the properties of each member that we are interested in.
  • Do the same for the owners.
  • Generate a report.

In my case, I decided to generate a HTML format report (Figure 3) and a CSV file. The report is for printing, the CSV file is to analyze membership as needed. Because we’re using PowerShell, it’s easy to include or remove properties for each member. I chose to include name, user principal name, email, title, department, office, city, post code, country, type (tenant or guest account), and member type (owner or member). The bottom of the report contains some summary detail such as the number of members, owners, and guests, the description of the group, and when it was created.

HTML membership report for a Microsoft 365 group
Figure 3: HTML membership report for a Microsoft 365 group

You can download the script from GitHub. The code is very straightforward. Feel free to improve it as you wish. And if you want a report detailing all the Microsoft 365 Groups and Teams in your tenant, check out the Groups and Teams Activity Report.

And if you’d like to create a report of the membership of every group/team in your tenant, check out this article.


Want to understand how to use PowerShell with Microsoft 365 Groups and Teams? Read Chapter 13 of the Office 365 for IT Pros eBook!

]]>
https://office365itpros.com/2021/02/19/printing-microsoft365-group-membership/feed/ 2 48368
New URL Format for Incoming Webhook Used by Teams and Groups https://office365itpros.com/2021/02/03/incoming-webhook-connector-format/?utm_source=rss&utm_medium=rss&utm_campaign=incoming-webhook-connector-format https://office365itpros.com/2021/02/03/incoming-webhook-connector-format/#comments Wed, 03 Feb 2021 02:12:00 +0000 https://office365itpros.com/?p=41450

Connectors Must be Updated by April 11, 2021

Office 365 Notification MC234048 published on January 12 announces that Microsoft is improving the security of the “Microsoft Teams connector apps webhook.” That mouthful refers to the incoming webhook connector which can be attached to Microsoft 365 Groups or Teams channels to allow the posting of cards generated from information in network sources.

The webhook is a unique URL which applications use to address the channel where they wish to publish information. The change being made adds the tenant name to the webhook URL to make it more apparent than previous. According to Microsoft, security is improved through the presence of the tenant name because organizations can then use the information to filter traffic logs. Quite how this improves security is beyond me because the tenant identifier (a GUID) has always been present in the webhook URL.

The changeover to the new format started on January 11, 2021. Old format webhooks will continue working for three months. The webhooks must be updated to the new format by April 11, 2021 to ensure that information continues to flow.

Interpreting the Webhook URL

The new format webhook looks like this:

https://office365itpros.webhook.office.com/webhookb2/7aa49aa6-7840-443d-806c-08ebe8f59966@c662313f-14fc-43a2-9a7a-d2e27f4f3478/IncomingWebhook/8592f62b50cf41b9b93ba0c0a00a0b88/eff4cd58-1bb8-4899-94de-795f656b4a18

The component parts are of the webhook are:

  • Tenant name (taken from Azure AD): Office365itpros. This is the new piece added to the webhook URL.
  • Webhook root: webhook.office.com/webhookb2. Old webhook URLs use office.com/webhook.
  • Group identifier: The Azure AD identifier for the Microsoft 365 group. In the example, this is 7aa49aa6-7840-443d-806c-08ebe8f59966.
  • Tenant identifier: The Azure AD identifier for the tenant. In the example, this is c662313f-14fc-43a2-9a7a-d2e27f4f3478. The group and tenant identifiers are separated by an at sign.
  • Provider name: This is always “IncomingWebhook.”
  • Alternate identifier: Another GUID to make the URL unique because a group or channel can support multiple webhooks. In this case, it’s 8592f62b50cf41b9b93ba0c0a00a0b88.
  • Group owner: The Azure AD identifier (GUID) for the group owner. Or rather, the account of the owner who adds the webhook to the group.

The same connector is used to bring data in from external sources to both Teams (data is posted in a channel) and Microsoft 365 Groups (data is posted as topics in email conversations).

Updating a Connector

Updating a connector to use the new format webhook isn’t hard. The trick is to know where the connectors are currently configured. When you know that, a group owner can access the set of connectors and check the incoming webhook connector. If “Attention required” appears for the connector, the webhook must be updated (Figure 1). If not, the connector is using the new format.

Attention required for an incoming webhook connector in a Teams channel
Figure 1: Attention required for an incoming webhook connector in a Teams channel

Clicking Manage brings you to the connector settings (Figure 2). Click Update URL to generate a new format webhook URL and then Save to update the connector. Before you save, make sure that you copy the webhook URL as you’ll need this to update the applications which send data to Microsoft 365 Groups or Teams through the connector.

Updating the webhook URL for a connector
Figure 2: Updating the webhook URL for a connector

The applications might be as simple as a PowerShell script (here’s an example of posting Microsoft 365 roadmap items to Teams and another to post notifications about inactive mailboxes). In other cases, the webhook URL might be used to post information coming from an application.

Finding Teams Using the Incoming Webhook

If you have only a few teams configured with the incoming webhook it won’t be hard to find and update the URL. Things are a little more complex in large organizations where many webhooks might be in use for both Teams and Microsoft 365 Groups. In these circumstances, some help might be needed to find all the connectors.

Some time ago, I wrote a PowerShell script to show how to report the channels and tabs connected to Teams. The point of that post was to demonstrate the retrieval of large amounts of data from Teams. As each team has standard apps (like Calls)), can have up to 200 channels, and each channel can have multiple tabs (including standard tabs), the script collects a bunch of information. In this instance, we can use it to find which teams have connectors configured with the incoming webhook connector.

After running the script, we can query the output report to find instances of teams with the connector:

$Report | ?{$_.App -eq "incoming webhook"} | Format-Table Team

Team
----
Technology News and Views
Engineering Colleagues
Human Resources Group
PL Test
Industry News

The report doesn’t tell us for which channel the connector is configured, but that should be easily found.

In passing, if you want to get an insight into the number of standard apps installed by Teams, run this command to group the results in the report:

$Report | Group App | Sort Count -Descending | Format-Table Name, Count

As they say, the output is “interesting”!


Interpreting the real meaning of a Microsoft announcement takes experience and background knowledge. Learn from the best by subscribing to the Office 365 for IT Pros eBook. No bumpf, just knowledge.

]]>
https://office365itpros.com/2021/02/03/incoming-webhook-connector-format/feed/ 5 41450
Use the Graph API to Work with Azure AD Access Reviews https://office365itpros.com/2021/01/26/graph-api-azure-ad-access-reviews/?utm_source=rss&utm_medium=rss&utm_campaign=graph-api-azure-ad-access-reviews https://office365itpros.com/2021/01/26/graph-api-azure-ad-access-reviews/#comments Tue, 26 Jan 2021 01:19:00 +0000 https://office365itpros.com/?p=40660

Check that Guests are Really Wanted

Microsoft is previewing the ability to create an Azure AD Access Review to cover guest access to every group (and team) in a tenant. The idea is that group owners are asked to approve or deny the access granted to guest users to their groups. With the caveat that all previews come with rough edges, the review works well enough for organizations to assess if the feature is valuable for them.

A challenge facing every GUI is how to achieve the balance of usability for both large and small organizations. Getting an oversight of an access review for guests in 27 teams in a small tenant makes certain demands on the GUI to make the data comprehensible and enable administrators to figure out where the overall review is at. Doing the same for a large tenant where reviews might be ongoing for thousands of teams poses a different test. However, the Identity Governance section in the Azure AD admin center has just one interface to manage access reviews (Figure 1).

Details of an Azure AD Access Review for all groups in a tenant
Figure 1: Details of an Azure AD Access Review for all groups in a tenant

When an access review is viewed through the Azure AD admin center, you see10 groups at a time (it’s a preview), but even if the admin center showed a hundred groups, paging through large numbers of groups to find what’s happening in an individual review can be painful.

Using the Graph API for Access Reviews

Which brings us to the Graph API for Azure AD Access Reviews, the basis for DIY management of access reviews. To test how the API worked, I wrote a PowerShell script to find the review for all groups and create a report of the review decisions made to date.

The steps taken in the script are:

  • As usual when using PowerShell to interact with the Graph, create a registered app in Azure AD. Note the app identifier, tenant identifier, and app secret. The app must be assigned the AccessReview.ReadWrite.All permission. I also assigned the Group.ReadApp permission to allow the app to retrieve details of Azure AD groups.
  • Use the app identifier, tenant identifier, and app secret to get an access token.
  • Read the set of access reviews known in the tenant and find the one used for guest access to all groups. This will result in a review instance.
  • Find the groups within the scope of the review. These are called instances. In other words, an instance of the overall review applied to a specific group.
  • For each instance, retrieve the decisions made for the guests in the group. It’s here that I retrieved the group display name to make it easier to understand the output.
  • Store details of each decision (verdict). The verdict will be Deny, Approve, or NotReviewed. A verdict comes with the name of the person who decided and when they decided. If the policy dictates, a justification is also present.
  • Capture the details of the verdict out in a PowerShell list.
  • After processing all instances, write the verdict data out from the list to a CSV file and give an overall report on screen.

Figure 2 shows the output at the end of the script.

Figure 2: Overall statistics for an Azure AD Access Review for guest users

The script generates a CSV file to allow the decision data to be analyzed in whatever way you wish. Piping the data to the Out-GridView cmdlet is a good way to get a quick overview of the current state of reviews across all groups (Figure 3).

Figure 3: Reviewing the decision status for access reviews

Download the Script

The sample script can be downloaded from GitHub. It doesn’t exercise all the functionality available in the API. For example, to accelerate the process of completing the review, you could look for outstanding reviews of guests in groups and call the acceptRecommendations API to accept the automatic recommendations as made by Azure AD. However, as I explain here, accepting automatic recommendations is not always the wisest thing to do, especially when Azure AD makes decisions based on limited data.


You’ll find full details about Azure B2B collaboration (the basis of guest access to Teams and Groups) plus a ton of insight about how guest access works in the Office 365 for IT Pros eBook. And because we keep the book updated, new developments like the Azure AD Access Review for all guests in a tenant are mentioned there too.

]]>
https://office365itpros.com/2021/01/26/graph-api-azure-ad-access-reviews/feed/ 2 40660
Outlook’s Groups Menu Bar Now Includes Teams https://office365itpros.com/2020/11/20/outlooks-groups-menu-bar/?utm_source=rss&utm_medium=rss&utm_campaign=outlooks-groups-menu-bar https://office365itpros.com/2020/11/20/outlooks-groups-menu-bar/#comments Fri, 20 Nov 2020 08:53:49 +0000 https://office365itpros.com/?p=34889

Introducing the Teams Button

Today’s topic is an unannounced update that’s just turned up in Outlook for Windows version 2011 (click to run build 13426.20184). At least, I’ve just noticed the change, which adds a Teams button to the Groups menu bar displayed when a team-enabled Microsoft 365 group (aka an Office 365 group or even Outlook group) is accessed (Figure 1). The button is hidden when you open a Microsoft 365 group that doesn’t have an associated team.

The Teams button in Outlook's Groups menu bar
Figure 1: The Teams button in Outlook’s Groups menu bar

Clicking the Teams button opens the Teams client positioned in the General channel of the team. It can’t open any other channel.

I’m uncertain what value is delivered by the Teams button. If you use Outlook to open Microsoft 365 Groups, you’re likely using it to have email-based conversations instead of Teams chat-based conversations. It seems unreasonable to assume that you would want to switch between the two modalities in the same group. After all, Microsoft doesn’t support the Share to Teams functionality for group conversations that’s available for regular email. Apart from a manual cut and paste, the only way to get a group conversation from Outlook (or OWA) to Teams is to forward the message to the email address of a team channel.

Moving Easily Between Outlook and Teams

It could be argued that adding the Teams button is simply a case of Microsoft making it easier for customers to move between Outlook and Teams. It could be the case that the team has integrated apps that aren’t available to Outlook, like Planner, some SharePoint pages, and a couple of third-party apps. In that respect, it makes sense to have an easy way to jump from Outlook to Teams.

It seems more likely that the Teams button is Microsoft’s subtle way to convince people to move their conversations from Outlook to Teams. There’s logic underpinning that transition because Teams is a better place to hold many conversations, especially those involving multiple back-and-forth responses.

On the other hand, if email-based conversations are your thing and your group involves many external people (guests and non-guests), an Outlook-based group is a good way to get work done. Microsoft recently updated Outlook for Windows to make the unread count work like regular folders, so work is still being done to improve and smoothen Outlook groups. And that’s the way it should be. Although Teams has 115 million daily active users, a lot of email is still sent inside and out of Office 365.


We cover both Teams and Outlook Groups in the Office 365 for IT Pros eBook. And we use both to get real work done.

]]>
https://office365itpros.com/2020/11/20/outlooks-groups-menu-bar/feed/ 4 34889
Change to Outlook Groups Displays High Unread Counts https://office365itpros.com/2020/09/24/change-outlook-groups-displays-high-unread-counts/?utm_source=rss&utm_medium=rss&utm_campaign=change-outlook-groups-displays-high-unread-counts https://office365itpros.com/2020/09/24/change-outlook-groups-displays-high-unread-counts/#comments Thu, 24 Sep 2020 01:00:00 +0000 https://office365itpros.com/?p=28377

Wow! Where Did All Those Unread Items Come From?

Last Tuesday, I checked for updates for the Microsoft 365 apps for enterprise (Office click to run) and duly downloaded the available update to upgrade to version 2009 (build 13231.20200). Nothing strange happened and the upgrade proceeded without any issues. I was a happy camper.

That is, until I noticed that the unread count for my Outlook Groups suddenly displayed much higher numbers (Figure 1). Usually these groups have a very low number of unread items, especially those marked as favorites because I check them at least once daily.

Outlook for Windows displays some high unread counts for Groups
Figure 1: Outlook for Windows displays some high unread counts for Groups

The History of Groups

The reason why this happens is clouded in history. When Microsoft introduced Office 365 Groups (now Microsoft 365 Groups) in November 2014, they were characterized as a new way for email-centric collaboration. Teams didn’t exist at that point and although Microsoft’s marketing muscle was pushing Yammer (bought in June 2012) as the future for collaboration and a replacement for email (that strategy really worked out), the bulk of interpersonal electronic collaboration occurred over email.

In the on-premises world, many Exchange organizations combined distribution lists with public folders to give people an archive for discussions. Groups introduced a group mailbox to host discussions and a shared calendar and came with a SharePoint Online team site for document storage, including a shared group OneNote notebook. Given that the bulk of work that had been migrated to Office 365 at that point was email, Groups looked pretty good. In April 2017, Groups (now called Groups in Outlook) had 10 million active users, or roughly 10% of the Office 365 user count at the time. The latest figure for Office 365 is 258 paid seats (April 2020). It’s unlikely that Outlook Groups have kept pace and now has 25 million active users, but it’s possible.

The collaboration landscape within Office 365 changed upon the general availability of Teams in March 2017. Since then, Teams has taken the lead and Groups have concentrated on a new mission of delivering a membership and access service to applications like Teams. Usage of Outlook Groups as a fulcrum for email-based collaboration is much less important to Microsoft now, but Groups are still actively used in this way in many Office 365 tenants.

Choosing a Simpler Unread Count Model for Groups

When Groups were added to Outlook in 2015, the developers decided not to use the standard item read/unread model as used in other mailbox folders like the Inbox. This model depends on the unread status of items and operates on a per-user basis. In other words, in a shared resource like a group inbox or public folder, each user has a separate unread count generated by the number of items they have not read in the folder.

Instead, the group developers chose a “more simple triage model for the groups conversations list, where all the conversations would be marked as seen as you moved away from the group.” Apparently, the decision was based on user feedback that many groups contain conversations unimportant to some members, so you couldn’t expect them to read everything. As implemented in Outlook, the group seen/unseen model allowed users to scan a group for new items and then set the unread count to zero once the user moves from the group. The new item count for a group then becomes the number of items delivered to the group since the last access by the user.

By comparison, new messages delivered to an inbox are personal and the mailbox owner is expected to deal with them. The new item count for the inbox is therefore very important for the mailbox owner and is adjusted up and down as the unread status for messages change (you can mark a read item as unread).

OWA and Outlook Mobile Use Normal Unread Counts

At the time, the developers accepted that the difference in how folders reported unread counts caused user confusion and said that they were working on implementing an item read/unread model for Groups. That model was implemented by OWA in early 2019 and is in use today (Figure 2).

OWA has used the read/unread model since 2019
Figure 2: OWA has used the read/unread model since 2019

For whatever reason (prioritization, lack of resources, more pressing features, etc.), Outlook desktop is a long way behind OWA in moving to the item read/unread model. The latest builds of Outlook have switched to the item read/unread model, which is the reason why the unread counts for my groups suddenly exploded from their normal low levels. Outlook Mobile has also used item unread counts since early 2019.

Resetting the Unread Count for an Outlook Group

Another piece of good news is that the Outlook developers have included a Mark All as Read option to reset the unread count for a group. Select the group you want to reset, right-click, and select the option. Processing to reset the unread status for items occurs in a background thread, so it doesn’t stop you working while the unread count is reset. Depending on the number of unread items in the group, the option can take a little while to complete.

Outlook's Mark All as Read option
Figure 3: Outlook’s Mark All as Read option

Unhappily, Outlook’s Mark All as Read option might not be able to update the status for all unread items. At least, it didn’t for me. My solution was to open the group with OWA and use its version of Mark All as Read, which worked flawlessly.

The good news is that as you open unread items in in a group using one client, the read status for the item and unread count for the group is updated and shown correctly across all Outlook clients.

Hindsight Always Best

The benefit of hindsight tells us that the decision of the Groups developers to go with the simpler read/unread model for their Outlook implementation was flawed. The change made in the other clients in 2019 is now showing up in Outlook desktop. A little preparation and user communication should be enough to get everyone over the shock of seeing elevated unread counts for their groups.


This one-time change will probably warrant a line or two in the Office 365 for IT Pros eBook. It’s an example of a small change that’s important for some users for a period. Once the change is done, it’s done. But change persists inside Office 365, which is why we keep updating the book.

]]>
https://office365itpros.com/2020/09/24/change-outlook-groups-displays-high-unread-counts/feed/ 3 28377
How to Find Guests in Microsoft 365 Groups and Teams Where Guests are Prohibited https://office365itpros.com/2020/06/09/finding-guests-office-365-groups-prohibited/?utm_source=rss&utm_medium=rss&utm_campaign=finding-guests-office-365-groups-prohibited https://office365itpros.com/2020/06/09/finding-guests-office-365-groups-prohibited/#comments Tue, 09 Jun 2020 13:45:53 +0000 https://office365itpros.com/?p=8378

Newly Applied Label Doesn’t Remove Existing Guests

Let’s assume that you’ve decided to replace the text-only classifications defined in the Azure Active Directory policy for Groups with Office 365 Sensitivity Labels. All is well, and you might even have used the PowerShell code explained in this article to do the job and all your teams, groups, and sites are now labelled properly.

You then consider an issue that will be dealt with differently from tenant to tenant: Assigning a label to a container that limits guest members does not affect access for existing guests. In other words, assigning a label to block guest access to a team, group, or site does precisely zero to remove any existing guests. They remain in the group membership and their access to group resources continues unimpeded.

Checking for Existing Guests

If this is a concern and you want to be sure that containers marked with a high degree of sensitivity do not have guest members, you should check the membership of these groups and remove any guests. This is simple to do with PowerShell. In this example, we find the groups stamped with a specific sensitivity label that have guest members and report who those guests are.

The code is straightforward.

  • Fetch all Microsoft 365 Groups stamped with a label that prohibits guest access.
  • Check the membership of each group to see if any guests are present.
  • Report any guests that are found.
CLS; Write-Host "Finding confidential Microsoft 365 Groups..."
$Groups = Get-UnifiedGroup | ? {$_.SensitivityLabel -eq "1b070e6f-4b3c-4534-95c4-08335a5ca610" -and $_.GroupExternalMemberCount -gt 0} 
If (!$Groups.Count) { Write-Host "No Microsoft 365 Groups found with that label"}
  Else {
     $Report = [System.Collections.Generic.List[Object]]::new(); $NumberGuests = 0
     Write-Host "Now examining the membership of" $Groups.Count "groups to find guests..." 
     ForEach ($Group in $Groups) {
       Write-Host "Processing" $Group.DisplayName
       $Users = Get-UnifiedGroupLinks -Identity $Group.Alias -LinkType Members
       ForEach ($U in $Users) {
         If ($U.Name -Match "#EXT#" -and $U.Name -NotLike "*teams.ms*") {
## Remember to edit the string to make sure it’s your tenant name…
            $CheckName = $U.Name + "@EditMeTenantName.onmicrosoft.com"
            $User = (Get-AzureADUser -ObjectId $CheckName).DisplayName 
            $ReportLine = [PSCustomObject]@{
               Email           = $U.Name
               User            = $User
               Group           = $Group.DisplayName
               Site            = $Group.SharePointSiteURL }
            $Report.Add($ReportLine)
            $NumberGuests++ }         
}}}
Write-Host "All done." $NumberGuests "guests found in" $Groups.Count "groups"

$Report | Sort Email | Out-GridView

The output is in a PowerShell list that we can review through the Out-GridView cmdlet (Figure 1) or by writing to a CSV file. After finding guests in groups where they are now prohibited, you can make the decision to leave them in place or remove them from the membership.

Guest users found in groups assigned a sensitivity label that blocks guest access
Figure 1: Guest users found in groups assigned a sensitivity label that blocks guest access

A more developed version of the script would first figure out which labels block guest access and then loop through all groups with these labels to create a report for all such labels. We explain how in the Office 365 for IT Pros eBook.

It’s worth noting that, if necessary, a global administrator can add a guest to a group even when blocked by policy.


Thinking about problems like this is what drives the Office 365 for IT Pros writing team to continually improve and refine our text about different aspects of Office 365. It’s why we issue a completely new book to our subscribers every month. Join us by taking out a subscription.

]]>
https://office365itpros.com/2020/06/09/finding-guests-office-365-groups-prohibited/feed/ 2 8378
The Renaming of Office 365 Groups https://office365itpros.com/2020/04/29/office-365-groups-microsoft-365/?utm_source=rss&utm_medium=rss&utm_campaign=office-365-groups-microsoft-365 https://office365itpros.com/2020/04/29/office-365-groups-microsoft-365/#comments Wed, 29 Apr 2020 00:40:49 +0000 https://office365itpros.com/?p=8707

Microsoft 365 Groups Just Trips Off the Tongue

Who would be an author? The news that Microsoft wants to rename Office 365 Groups to become Microsoft 365 Groups wasn’t popular with the Office 365 for IT Pros eBook team. We have tons of references to Office 365 Groups in many chapters of the book, all of which now need to be checked along with screen captures as Microsoft makes the change “over time.” Oh well, it’s not like we had anything else to do.

Branding for Branding’s Sake

On a serious note, I wonder about why Microsoft bothers with changes like this. The folks in charge of Microsoft 365 marketing might be happy because yet another thing has been rebranded. But anyone outside Redmond will wonder why Office ProPlus absolutely had to become Microsoft 365 Apps. No added value is created, no new functionality launched, and customers gain no benefit.

In the case of Office 365 Groups, this is just another attempt to nail a name that sticks (Groups in Outlook – Figure 1 – is a particularly horrible example), often to reflect a changed position in Microsoft’s spectrum of collaboration products.

Groups in Outlook aka Office 365 Groups aka Microsoft 365 Groups aka Outlook Groups
Figure 1: Groups in Outlook aka Office 365 Groups aka Microsoft 365 Groups aka Outlook Groups

A Better Distribution List

Launched in November 2014, the original idea behind Groups was to create a better form of email distribution list which combined the best of Exchange Online and SharePoint Online to replace the ill-fated site mailbox initiative. And maybe persuade some customers to move away from Exchange public folders as their preferred repository for shared documents.

Office 365 Groups have never succeeded in being a better distribution list (no support for nested groups). Their progress as a collaboration platform was restricted by internal competition, first with Yammer and then with Teams. The desirability of Groups was also affected by the antics of the Azure Active Directory team, who demanded premium licenses for features like a naming policy (a free feature for distribution lists).

Membership Focus

What Office 365 Groups have succeeded in is delivering a membership service for Microsoft 365 applications like Teams, Yammer, and Planner. It would have been silly if each application had been allowed to develop its own approach to user management, and it made sense to use a common service, even if the lack of granularity in the owner/member model used by Groups has been decried by some.

If the long-term mission for Office 365 Groups is to be less of a threaded conversation application for Outlook and OWA to focus on being a management service for Microsoft 365, then the rename makes more sense. So perhaps I should stop worrying. Or complaining. Or both.

Frontline Users Can Continue Sending Urgent Teams Messages (for now)

On the good news front, Microsoft has halted plans to limit frontline users from sending more than five priority (urgent) Teams messages per month. The limit was originally supposed to come into force on January 1 but was bumped to April 1. Now the Covid-19 situation has caused Microsoft to sayTo assist our customers and community in their crisis response efforts, we’re extending the priority notifications promotion until the second half of 2020.”

It’s a good thing because urgent messages are often used in hospital situations. In fact, you’d wonder why urgent messages is a premium feature. Maybe it’s time for a rebranding.

]]>
https://office365itpros.com/2020/04/29/office-365-groups-microsoft-365/feed/ 4 8707
Using Microsoft Graph API Queries to Process Large Amounts of Data https://office365itpros.com/2020/02/17/microsoft-graph-queries-powershell/?utm_source=rss&utm_medium=rss&utm_campaign=microsoft-graph-queries-powershell https://office365itpros.com/2020/02/17/microsoft-graph-queries-powershell/#comments Mon, 17 Feb 2020 01:42:26 +0000 https://office365itpros.com/?p=7488

Creating a List of Teams

I’ve written a couple of articles about using Microsoft Graph queries with PowerShell to access data that you can’t normally get to with cmdlets. For instance, this example explains how to report the somewhat bizarre email addresses assigned to Teams channels. When a channel is email-enabled, people can post to the channel by sending email to the assigned address, which is a good way to introduce information into Teams. Apart from being posted as new topics in the channel, messages are captured in the channel’s folder in the SharePoint document library belonging to the team.

Limited Data Returned by Design

But as a comment to the article notes, when you use the Invoke-WebRequest cmdlet to send a Graph command to fetch information about the set of Teams in a tenant, the Graph responds with 100 teams. This is what the Graph intends to do because it doesn’t want the response to be too large. And the response is good enough to prove the principle of working with the Graph through PowerShell. However, once you get to production, you probably need to deal with more than 100 teams and need to be able to fetch all the teams in the tenant and process them.

Processing Four Thousand Teams

A few days ago, Mike Tilson posted a note in the Office 365 Facebook group asking if it is “possible to run a report (hopefully via PowerShell) to report on what Microsoft Teams apps (third party apps like Polly) are installed across your environment?” As it happens, the esteemed technical editor for the Office 365 for IT Pros eBook, Vasil Michev, had written a script to report on apps and tabs. I took his script and made (in my mind) some improvements, and I gave Mike a copy of the script.

Mike’s response was that the script worked great in a small environment but had 2,000+ teams (among 4,000-odd groups) to report on in production. The code needed to be upgraded to process larger numbers.

NextLink is the Key

The solution is a thing called a nextlink, available when Microsoft Graph queries have more data to provide to clients than is returned to the original request (server-side paging). A page is the set of data returned for a Graph call and several pages might need to be retrieved to fetch the full set of objects you want to process The documentation says “When a result set spans multiple pages, Microsoft Graph returns an @odata.nextLink property in the response that contains a URL to the next page of results.” In effect, the nextlink tells the Graph the next set of data to return if an application wishes to request it following its first call. To be sure that you get all data, you need to fetch it page by page until the nextlink is null. This is called pagination.

If you use the Graph Explorer to play with Microsoft Graph queries, you’ll see that a nextlink turns up in calls like “all groups in my organization.” You know it’s a nextlink because it includes the term “skiptoken” as in https://graph.microsoft.com/v1.0/groups?$skiptoken=X%274453707402 (a real nextlink is much longer). Microsoft Graph queries can generate nextlinks after fetching less than 100 items. For instance, the default number of folders retrieved from a mailbox is 10.

Solving the Problem

The uprated code:

  • Makes the original call to fetch teams and stores the object identifier and display name for each team in a hashtable. A hashtable is suitable when you only need to store two properties. If you need to store more, create and populate a generic list instead.
  • Checks if a nextlink is returned.
  • If a nextlink is found, make another call to the Graph to fetch another set (page) of data and store those items in the hashtable. This call uses the nextlink to tell the Graph where to start retrieving data.
  • Continue until the nextlink is null, meaning that no more data remains to be fetched.

Here’s the code, based on an original solution created by Mike Tilson.

$Uri = "https://graph.microsoft.com/V1.0/groups?`$filter=resourceProvisioningOptions/Any(x:x eq 'Team')"
[array]$Teams = Invoke-WebRequest -Method GET -Uri $Uri -ContentType "application/json" -Headers $Headers | ConvertFrom-Json
If ($Teams.Value.Count -eq 0) { Write-Host "No Teams found - exiting!"; break }
$Teams.Value.ForEach( {
   $TeamsHash.Add($_.Id, $_.DisplayName) } )
$NextLink = $Teams.'@Odata.NextLink'
While ($NextLink -ne $Null) {
   $Teams = Invoke-WebRequest -Method GET -Uri $NextLink -ContentType $ctype -Headers $headers | ConvertFrom-Json
   $Teams.Value.ForEach( {
      $TeamsHash.Add($_.Id, $_.DisplayName) } )
   $NextLink = $Teams.'@odata.NextLink' }

Get-Team Works Too

Another pragmatic solution to the problem of how to fetch all teams in a tenant is to use the Get-Team cmdlet. Using Get-Team is much slower than the code listed above (minutes instead of seconds), but the cmdlet handles the paging for you.

After fetching the set of teams, we can begin to process each team to discover what apps and tabs are installed in it. The Graph calls in the script to fetch channels, tabs, and apps don’t use paging. A team can have up to 200 channels, so I guess the call to fetch channels might need to change to handle such a well-endowed (and possibly confusing) team.

Still Work to Do

Although we can now fetch all the teams in a tenant, things aren’t perfect yet. I found a problem processing archived teams, where the attempt to retrieve app information fails. I can’t see how to identify an archived team from the information returned, so more research is needed. (Update: check the isArchived property in team settings to find archived teams).

Another issue is that the auth token expires after an hour and stops the script. A refresh token is needed at this point. (Update: the latest version of the Teams and Groups Report script illustrates how to renew an access token).

If you’d like to improve the code and make it even better, you can get the script from GitHub. In the meantime, enjoy using Microsoft Graph queries to process data with PowerShell.


Need help understand how to use PowerShell to manage Office 365 Groups and Teams? The Office 365 for IT Pros eBook contains a ton of examples to help you get going.

]]>
https://office365itpros.com/2020/02/17/microsoft-graph-queries-powershell/feed/ 6 7488
How to Report Microsoft 365 Groups Deletions Using the Audit Log https://office365itpros.com/2020/01/30/microsoft-365-groups-deletions/?utm_source=rss&utm_medium=rss&utm_campaign=microsoft-365-groups-deletions https://office365itpros.com/2020/01/30/microsoft-365-groups-deletions/#comments Thu, 30 Jan 2020 09:15:21 +0000 https://office365itpros.com/?p=7050

Deletions for Microsoft 365 Groups reported by PowerShell

Soft and Hard Deletions for Microsoft 365 Groups

Yesterday’s post addressed the topic of how to report the removals of Teams from an Office 365 tenant. This led to the logical question of how to know when Microsoft 365 Groups (and Teams) are removed because they expire due to the settings in the tenant group expiration policy.

The simple answer is that the Office 365 audit log captures details for all group deletions, including when the group expiration policy determines that a group is expired and puts the group into a soft-deleted state. Thirty days later, a background process permanently removes the soft-deleted group unless an administrator restores it beforehand. As is often the case with Office 365 technology, the simple answer hides some complexity, which we’ll dive into now.

Understanding Group Deletion Records

When you examine the records for group deletions stored in the Office 365 audit log, you find three conditions to handle:

  1. A user deletes a Microsoft 365 group, team, or team-enabled site.
  2. Microsoft background processes examine groups that come within the scope of the expiry policy and remove expired groups where no activity has occurred to force automatic renewal. These events are logged with a user identifier like ServicePrincipal_1342cefb-7a89-4ee2-af90-c8443053e1e8.
  3. Both 1 and 2 put groups into a soft-deleted state. After 30 days, another background process called the Microsoft Online services Garbage Collector permanently removes these groups and all attached resources.

With these conditions in mind, we can create a PowerShell script to extract records from the Office 365 audit log and parse the records to extract some useful information. Here’s the script I created. It looks similar to the one discussed yesterday with some extra processing to handle the three conditions.

CLS; Write-Host "Searching Office 365 Audit Records to find auto-expired group deletions"
$StartDate = (Get-Date).AddDays(-90); $EndDate = (Get-Date) 
$PolicySoftDeletes = 0; $HardDeletes = 0; $UserSoftDeletes = 0
$Records = (Search-UnifiedAuditLog -Operations "Delete Group" -StartDate $StartDate -EndDate $EndDate -ResultSize 1000)
If ($Records.Count -eq 0) {
    Write-Host "No audit records for group deletions found." }
Else {
    Write-Host "Processing" $Records.Count "team deletion audit records..."
    $Report = [System.Collections.Generic.List[Object]]::new() # Create output file 
    # Scan each audit record to extract information
    ForEach ($Rec in $Records) {
      $AuditData = ConvertFrom-Json $Rec.Auditdata
      $User = $AuditData.UserId.Split("_")[0]    
      $GroupName = $Auditdata.Target | ? {$_.Type -eq 1} | Select -ExpandProperty Id
          Switch ($User)
          {
            "Certificate"  { # Hard delete of a group 
                 $HardDeletes++ 
                 $Reason = "Group permanently removed" 
                 $User = $User + " (System Process)" }
            "ServicePrincipal" { #Soft delete - expiration policy 
                 $PolicySoftDeletes++
                 $Reason = "Group removed by expiration policy"
                 $User = $User + " (System Process)" }
            default { #Regular delete by a user 
                 $UserSoftDeletes++ 
                 $Reason = "User deleted group" }
          }       
          $ReportLine = [PSCustomObject] @{
           TimeStamp = Get-Date($AuditData.CreationTime) -format g
           User      = $User
           Group     = $GroupName 
           Reason    = $Reason
           Action    = $AuditData.Operation
           Status    = $AuditData.ResultStatus }        
      $Report.Add($ReportLine) }
}
Cls
Write-Host "All done - Group deletion records for the last 90 days"
Write-Host "User deletions:"     $UserSoftDeletes
Write-Host "Policy deletions:"   $PolicySoftDeletes
Write-Host "Group hard deletes:" $HardDeletes
Write-Host "----------------------"
$Report | Sort Group, Reason -Unique | Select-Object Timestamp, Group, Reason, User | Out-GridView

If you examine the results as piped through the Out-GridView cmdlet (Figure 1), you’ll see examples where a record captures a soft-delete by user or policy followed 30 days later by a permanent removal.

Deletion records for Microsoft 365 Groups extracted from the audit log
Figure 1: Out-GridView shows group deletion records

Once you’re happy with the data generated, it’s easy to include an extra line of code to output a CSV file using the Export-CSVFile cmdlet or use the ImportExcel module to export the data to an Excel worksheet. Once again, access to this kind of information proves that PowerShell and the audit log are a very flexible tool to understand what happens behind the scenes in Microsoft 365.


Need more insight into mining the valuable information stored the Office 365 audit log? We’ve got a complete chapter covering auditing and reporting in the Office 365 for IT Pros eBook.

]]>
https://office365itpros.com/2020/01/30/microsoft-365-groups-deletions/feed/ 1 7050
Reporting Team Deletion Events to Office 365 Administrators https://office365itpros.com/2020/01/29/report-the-deletion-of-teams/?utm_source=rss&utm_medium=rss&utm_campaign=report-the-deletion-of-teams https://office365itpros.com/2020/01/29/report-the-deletion-of-teams/#comments Wed, 29 Jan 2020 09:19:08 +0000 https://office365itpros.com/?p=6951

Use Office 365 Audit Log to Report the Deletion of Teams

Idly playing with PowerShell on a dull Friday afternoon in winter, I decided to respond to a question in the Office 365 Facebook group about how to be notified when someone deletes a team. Presumably the requirement exists to allow tenant administrators to leap into action to chastise people who delete teams without asking, or something like that.

My initial response was that this is the same problem as you have when someone deletes an Office 365 Group (each team is a group) and directed the questioner to this 2018 Petri article, which describes how to check groups in a soft-deleted state waiting for their 30-day retention period to expire. During this time, you can rescue a soft-deleted group and return it to full working order.

Office 365 Activity Alerts

The Office 365 Security and Compliance Center includes the ability to create activity alerts (in the Alerts section). These alerts fire when an Office 365 audit record is captured for specific events, like team deletions (Figure 1). When an alert happens, email notifications go to the people specified in the alert to tell them that something’s happened. It all sounds good.

An Office 365 Activity Alert for Team Deletions

Report the deletions of Teams
Figure 1: An Office 365 Activity Alert for Team Deletions

The Problems with Activity Alerts

When you access activity alerts in the Security and Compliance Center, you’ll see a banner saying that Microsoft has a better solution (activity policies). Activity alerts have some problems. First, they can fire some time after an event occurs. It all depends when the audit log ingests events from the workload responsible for the monitored activity. Usually the delay is between 15-30 minutes for most Office 365 workloads, but it can be longer. Second, whatever process is responsible for sending the email notifications seems to be asleep for most of the day as the arrival time of the notifications is very unpredictable. You might even say unreliable.

It’s easy to create your own version of activity alerts based on the same data as used by Office 365. First, we look in the Office 365 audit log for team deletion events. Then we distribute the information via email or Teams.

Script to Report Team Deletions

The PowerShell script below searches for team deletion events from the last seven days and stores the information in a list object.

<pre class="lang:ps">CLS; Write-Host "Searching Office 365 Audit Records to find Team deletions"
$StartDate = (Get-Date).AddDays(-7); $EndDate = (Get-Date) 
$Records = (Search-UnifiedAuditLog -Operations TeamDeleted -StartDate $StartDate -EndDate $EndDate -ResultSize 1000)
If ($Records.Count -eq 0) {
    Write-Host "No audit records for Team deletions found." }
Else {
    Write-Host "Processing" $Records.Count "team deletion audit records..."
    $Report = [System.Collections.Generic.List[Object]]::new() # Create output file 
    # Scan each audit record to extract information
    ForEach ($Rec in $Records) {
      $AuditData = ConvertFrom-Json $Rec.Auditdata
          $ReportLine = [PSCustomObject] @{
           TimeStamp = Get-Date($AuditData.CreationTime) -format g
           User      = $AuditData.UserId
           Action    = $AuditData.Operation
           Team      = $AuditData.TeamName }
      $Report.Add($ReportLine) }
}
Cls
Write-Host "All done - Team deletion records for the last 90 days"
$Report | Format-Table TimeStamp, Action, Team, User -AutoSize</pre>

Notifying Administrators About Team Deletions

After we know what teams were deleted in the last week, we can use the information stored in the $Report variable to create notifications for administrators that are posted via email or Teams.

Creating and sending email notifications in PowerShell is straightforward (an example is explained here). Remember that the account used to send the message must be enabled for SMTP authentication as otherwise the Send-Message cmdlet will fail.

Posting to a Teams channel can be done using the incoming webhook connector as described in this article. In some respects, it seems appropriate that notifications about deleted teams should be posted to Teams, but I will let you make your own mind up.


The Office 365 Audit log is stuffed full of interesting information to explain how and when things happen inside a tenant. The Office 365 for IT Pros eBook contains many examples of using the audit log to good effect. Subscribe to receive monthly updates full of Office 365 goodness.

]]>
https://office365itpros.com/2020/01/29/report-the-deletion-of-teams/feed/ 6 6951
Using the Groups Admin Role https://office365itpros.com/2020/01/22/using-groups-admin-role/?utm_source=rss&utm_medium=rss&utm_campaign=using-groups-admin-role https://office365itpros.com/2020/01/22/using-groups-admin-role/#comments Wed, 22 Jan 2020 00:10:22 +0000 https://office365itpros.com/?p=6789

The Problem of Day-to-Day Group Management

The GroupCreationAllowedGroupId setting in the Azure Active Directory policy for groups allows tenants to dictate which users can create new Office 365 Groups using clients like Outlook and OWA or apps like Teams, Planner, and Yammer. Tenant administrators and holders of administrative roles like Teams service administrator or User account administrator are not constrained by group creation restrictions imposed by the policy.

However, being allowed to create new groups by policy does nothing to allow the people who created groups to perform day-to-day management of the same groups thereafter, so this work had to be done by tenant administrators. The situation is acceptable in small tenants but becomes more problematic as the number of groups grows.

The Groups Admin Role

The Groups admin role is designed to solve the problem. Introduced in November 2019, this is a standard Office 365 administrative role which can be assigned to user accounts through the Microsoft 365 Admin Center, Azure Active Directory portal (where the role is called Groups Administrator), or PowerShell. To assign the role through the Microsoft 365 Admin Center, select an account, then Manage roles. The Groups Admin role is not one of the default roles shown, so click Show all by category and you’ll find the role under Collaboration (Figure 1).

 Assigning the Groups Admin role through the Microsoft 365 Admin Center
Figure 1: Assigning the Groups Admin role through the Microsoft 365 Admin Center

What The Groups Admin Role Does

When assigned, the Groups Admin role allows the holder to manage the following Office 365 Groups actions:

  • Create, edit, delete, and restore Office 365 groups and Azure Active Directory security groups.
  • Create, edit, and delete group creation, expiration, and naming policies.

Groups admins can manage groups and group policies through administrative interfaces such as the Microsoft 365 Admin Center or PowerShell. Holding the role does not allow groups admins to create new groups through client interfaces like OWA. If you want Groups admins to be able to create groups everywhere, you must add them to the group defined to control group creation in the Azure Active Directory Groups policy.

Matching Groups Creation with Groups Management

Because the Groups admin role is new, it’s possible that tenants who already control group creation by policy might want the same set of users to be members of the group allowed to create new groups and hold the Groups admin role. This is easily done with PowerShell. The script below:

  • Checks if group creation is controlled by policy.
  • If yes, fetches the members of the group allowed to create new groups.
  • Assigns the Groups admin role to each member.
  • Lists the current holders of the Groups admin role.
# Find the settings in the Azure AD Policy for Groups
$Settings = Get-AzureADDirectorySetting | ? {$_.DisplayName -eq "Group.Unified"}
If ($Settings["GroupCreationAllowedGroupId"] -ne $Null) { # We have a group defined to control group creation
   $Members = Get-AzureADGroupMember -ObjectId $Settings["GroupCreationAllowedGroupId"]
   $GroupAdminRole = Get-AzureADDirectoryRole | ? {$_.DisplayName -eq "Groups Administrator"} | Select ObjectId
   ForEach ($Member in $Members) { # Assign the Groups Admin role to each member
      Try {
        Add-AzureADDirectoryRoleMember -ObjectId $GroupAdminRole.ObjectId -RefObjectId $Member.ObjectId }
      Catch { 
        Write-Host "Groups Admin role already assigned to" $Member.DisplayName }}}
  Else {Write-Host "This tenant does not control group creation via policy"}

Write-Host "----------------------------------------"
Write-Host "Current holders of the Group Admins role"
Write-Host "----------------------------------------"
Get-AzureADDirectoryRoleMember -ObjectId $GroupAdminRole.ObjectId | Format-Table DisplayName, UserPrincipalName

Of course, you could also do the reverse and add the users who hold the Groups admin role to the group allowed to create new groups. All a matter of a few lines of PowerShell code.


The Office 365 for IT Pros eBook includes many suggestions for group management. It’s one of the areas we keep a close eye on.

]]>
https://office365itpros.com/2020/01/22/using-groups-admin-role/feed/ 2 6789
How to Generate an Activity Report for Microsoft 365 Groups and Teams https://office365itpros.com/2020/01/14/microsoft-365-groups-teams-report/?utm_source=rss&utm_medium=rss&utm_campaign=microsoft-365-groups-teams-report https://office365itpros.com/2020/01/14/microsoft-365-groups-teams-report/#comments Tue, 14 Jan 2020 09:54:37 +0000 https://office365itpros.com/?p=6653

Find Obsolete Microsoft 365 Groups and Teams

May 11: Microsoft is deprecating the TechNet Gallery in June 2020. The script can now be downloaded from GitHub.

Oct 14: Microsoft updated the location of the Teams compliance records used to check how active a team is. Version 4.7 or later of the script handles this issue.

I wrote the first version of a script to analyze the activity in Microsoft 365 Groups (then Office 365 Groups) and Teams to identify obsolete groups in 2017. The script is described in this Petri.com article and is reasonably popular. I keep an eye on the feedback from people who run the script and update the script as time goes by. You can download the latest version from GitHub. The latest version is V4.8 dated 16 December 2020.

Update: A Graph-based version of the script is available in GitHub (5.4). This version is much faster at processing Microsoft 365 Groups and Teams and is now the recommended code and the base for future development. See this post for details.

The basic idea is to analyze the Microsoft 365 Groups in a tenant to find underused groups or simply understand the level of activity across groups. The script looks at the level of activity in:

  • Conversations stored in the Inbox of group mailboxes (for Outlook Groups).
  • Documents (in SharePoint document libraries belonging to the groups)
  • Chats (for Teams-enabled Groups). In fact, the script checks the compliance records logged in the group mailbox for conversations in channels belonging to the Teams.

Checking different aspects of individual groups isn’t fast. One tenant tells me that it takes 17 hours to process 5,300 groups… but this isn’t a report that you’ll run daily. It’s more like a monthly or quarterly activity.

Script Outputs

The script records the data for each group in a PowerShell list. Eventually, after processing all the groups, the script outputs an HTML report and a CSV file. The script also assigns a status of Pass, Warning, or Fail to each group depending on the level of detected activity. The determination of the status is entirely arbitrary and should be adjusted to meet the needs of your organization.

The output from the Microsoft 365 Groups and Teams activity report
Figure 1: The output from the Microsoft 365 Groups and Teams activity report

At the bottom of the report you’ll see a summary like this:

Report created for: tenant.onmicrosoft.com
Number of groups scanned: 182
Number of potentially obsolete groups (based on document library activity): 120
Number of potentially obsolete groups (based on conversation activity): 129
Number of Teams-enabled groups : 65
Percentage of Teams-enabled groups: 35.71%

----------------------------------------------------------------------------

Reviewing the report should help you find the Microsoft 365 Groups and Teams that are not being used. These groups are candidates for removal or archival.

You can view a screen capture video showing how to run the script here.

Recent Improvements

Scripts that evolve over time can often do with a rewrite from scratch. However, I don’t have the time for that. but I do make changes that I think are useful. Here are some recent changes.

  • New tests to see if the SharePoint Online and Teams modules are loaded. In particular, the Teams check took far too long because the cmdlets in this module are slow. In fact, the Get-Team module is so slow that we don’t use it from V4.3 onwards. Using Get-UnifiedGroup with a filter is about twice as fast. We might revisit this point as new versions of the Teams PowerShell module appear. See note above about the Graph-based version of the script.
  • Use a PowerShell list object to store the report data. This is much faster than an array, especially when you might want to store data for thousands of groups. This was one of the performance tips received after publishing a post about how we write PowerShell and it makes a real difference.
  • Use Get-Recipient instead of Get-UnifiedGroup to create a set of group objects to process. Get-Recipient is much faster than Get-UnifiedGroup when you need to create a list of mail-enabled objects like Office 365 Groups. V5.0 and later replaces these calls with Graph API commands.
  • Output the storage consumed by the SharePoint site belonging to each group.
  • Handle groups that have no conversations in the group mailbox more elegantly. Groups used by Teams are often in this situation.

Test Before Deployment

As always, test any PowerShell code downloaded from the web, even from sources like GitHub, before introducing it to a production system. The code as written needs some extra error handling to make it as robust as it could be, but I’ve left that to the professionals as people tend to have their own way of approaching this issue.


The Office 365 for IT Pros eBook includes many valuable tips for writing PowerShell scripts to interact with Office 365 Groups and Teams. Subscribe to gain benefit from all that knowledge!

]]>
https://office365itpros.com/2020/01/14/microsoft-365-groups-teams-report/feed/ 140 6653
Office 365 Groups to Support Sensitivity Labels https://office365itpros.com/2019/11/05/office-365-groups-support-sensitivity-labels/?utm_source=rss&utm_medium=rss&utm_campaign=office-365-groups-support-sensitivity-labels https://office365itpros.com/2019/11/05/office-365-groups-support-sensitivity-labels/#comments Tue, 05 Nov 2019 11:31:09 +0000 https://office365itpros.com/?p=5539

Labels for Groups, Teams, SharePoint, and Planner

Microsoft announced at the Ignite 2019 conference that they were bringing Office 365 sensitivity labels to Office 365 Groups. The update will affect apps depending on groups like Teams, SharePoint Online, and Planner.

Today, sensitivity labels can apply visual markings and rights-management based encryption to documents and messages. Microsoft is expanding the set of properties managed for labels through the Security and Compliance Center to include a set specially for Groups. The new set includes the access type (private or public) for the group and if it supports guest users.

The Effect on Group Creation

Once published to users in a label policy, they can only create new groups based on the settings in the policy. If two or three labels are in the policy, users can select from those labels, and the settings for the selected label like access type are assigned to the new group.

It’s important to note that the classification property assigned to a group is unaffected by a sensitivity label. The classification for a group is a text-only visual marking to show the kind of content contained in the group. It has no affect on how the group works unless you write some PowerShell to apply settings based on the classification.

All the dependent apps, like Teams and SharePoint Online, are being updated to show when a sensitivity label is assigned to the underlying group. Teams already synchronizes the classification assigned to a group to any private channels and will also synchronize the sensitivity label to ensure that everything has the same label.

Labels Aren’t Stamped on Group Contents

Although Groups pick up settings from a sensitivity label, the data stored in a group are unaffected by the visual marking or protection settings in the label. In other words, if you create a new conversation in a group or add a new document to the SharePoint Online site belonging to the group, the sensitivity label is not assigned to the item, so it will not be marked with a header and/or footer or encrypted as defined in the label properties. That capability is likely to come in the future, but for now, sensitivity labels are being used as container markings rather than being applied to the individual items within the containers. Expect this to happen in the future.

No Retrospective Labels

It’s also the case that Office 365 only applies label settings to new groups. Microsoft says that they might provide some PowerShell scripts to retrospectively assign labels to old groups, but there’s no certainty on this point. Even if Microsoft doesn’t, the script is likely to be easily written as a call to Get-UnifiedGroup to find old groups (or, for better performance, to Get-Recipient) followed by running Set-UnifiedGroup to assign an available label to each group. Some care is needed in writing such a script to ensure that the right label is stamped on groups, but as they say, “it’s only a matter of programming.”

Public Preview Soon

The public preview of sensitivity labels for Office 365 Groups is likely to begin in about two weeks after the necessary updates roll out for Teams, Planner, SharePoint Online, and other affected apps. An update to the Exchange Online PowerShell module is also needed to allow labels to be manipulated for groups.

We’ll keep an eye on developments in this space and will report on what happens in due course.


For more information about the topics of Office 365 Groups and Sensitivity Labels, look no further than the comprehensive coverage in the Office 365 for IT Pros eBook. We really get this stuff!

]]>
https://office365itpros.com/2019/11/05/office-365-groups-support-sensitivity-labels/feed/ 1 5539
How to Report Old Guest Accounts and Their Membership of Microsoft 365 Groups (and Teams) https://office365itpros.com/2019/10/15/report-old-guest-accounts/?utm_source=rss&utm_medium=rss&utm_campaign=report-old-guest-accounts https://office365itpros.com/2019/10/15/report-old-guest-accounts/#comments Tue, 15 Oct 2019 08:20:05 +0000 https://office365itpros.com/?p=5185

A Proliferation of Guest User Accounts Within Tenants

Updated July 19. 2023

Azure Active Directory Guest User Accounts are terrifically useful in terms of allowing people outside your Microsoft 365 tenant to access resources inside the tenant. Applications like Teams, SharePoint Online, Planner, and Outlook Groups use the Azure B2B Collaboration framework to create new guest accounts to share information, whether it’s the membership of a team or access to a shared document or folder.

Guest accounts might be needed for to share just one document. Old guest accounts can accumulate over time. A regular spring cleaning is needed to ensure that you detect old guest accounts that are possibly no longer needed.

The Problem of Deciding When to Leave

As always, the problem is to decide when a guest account should be removed. Left by themselves, guest accounts will remain in the tenant directory because neither Office 365 nor Azure Active Directory include an automated method to clean up guests past their best-by date. One approach is to review guest accounts that are older than a certain age and look for evidence to indicate if they should be removed.

For example, you might decide that membership of multiple Microsoft 365 groups (aka Office 365 groups) is sufficient reason to keep guest accounts. The logic here is that these memberships give people access to Teams (conversations), Outlook Groups (conversations delivered via email), and Planner (group tasks). Therefore, if we write a script to scan for guest accounts older than x days and then check if these accounts are members of groups, we should have some evidence upon which to base a decision to remove or keep.

PowerShell Script to Highlight Old Guest Accounts and their Group Membership

The script below does the following:

  • Connects to the Graph with the Connect-MgGraph cmdlet.
  • Finds all guest accounts in the tenant using the Get-MgUser cmdlet.
  • Checks each guest to discover its age using the account creation date.
  • If the guest account is older than 365 days, we look for its group membership by running the Get-MgUserMemberOf cmdlet and report the display names of any groups found.
  • Checks the last sign-in activity for the account. This could be an important indicator that the account is active.
  • Writes the discovered information out to an array.
  • After all guest accounts are processed, the script writes the contents of the array containing information about old guest accounts to a CSV file.

Some example code is shown below. The latest version of the script is available on GitHub and is the version which you should download and use. The latest version runs with the Microsoft Graph PowerShell V2 cmdlets.

Remember that you might want to update the code to add error handling and do whatever testing is necessary before running the script against your production tenant.

# Script to find Old Guest Accounts in an Office 365 Tenant that are older than 365 days and the groups they belong to
# Find guest accounts

Write-Host "Finding Guest Accounts..."
[Array]$GuestUsers = Get-MgUser -Filter "userType eq 'Guest'" -All -Property Id, displayName, userPrincipalName, createdDateTime, signInActivity `
    | Sort-Object displayName
$i = 0; $Report = [System.Collections.Generic.List[Object]]::new()
# Loop through the guest accounts looking for old accounts 
CLS
ForEach ($Guest in $GuestUsers) {
# Check the age of the guest account, and if it's over the threshold for days, report it
   $AccountAge = ($Guest.CreatedDateTime | New-TimeSpan).Days
   $i++
   If ($AccountAge -gt $AgeThreshold) {
      $ProgressBar = "Processing Guest " + $Guest.DisplayName + " " + $AccountAge + " days old " +  " (" + $i + " of " + $GuestUsers.Count + ")"
      Write-Progress -Activity "Checking Guest Account Information" -Status $ProgressBar -PercentComplete ($i/$GuestUsers.Count*100)
      $StaleGuests++
      $GroupNames = $Null
      # Find what Microsoft 365 Groups the guest belongs to... if any
     [array]$GuestGroups = (Get-MgUserMemberOf -UserId $Guest.Id).additionalProperties.displayName
     If ($GuestGroups) {
        $GroupNames = $GuestGroups -Join ", " 
     } Else {
        $GroupNames = "None"
     }
  
#    Find the last sign-in date for the guest account, which might indicate how active the account is
     $UserLastLogonDate = $Null
     $UserLastLogonDate = $Guest.SignInActivity.LastSignInDateTime
     If ($Null -ne $UserLastLogonDate) {
        $UserLastLogonDate = Get-Date ($UserLastLogonDate) -format g
     } Else {
        $UserLastLogonDate = "No recent sign in records found" 
     }

     $ReportLine = [PSCustomObject][Ordered]@{
           UPN               = $Guest.UserPrincipalName
           Name              = $Guest.DisplayName
           Age               = $AccountAge
           "Account created" = $Guest.createdDateTime 
           "Last sign in"    = $UserLastLogonDate 
           Groups            = $GroupNames }     
     $Report.Add($ReportLine) }
} # End Foreach Guest

Sample Report File

The output CSV file is shown (somewhat obscured to protect the names of the guilty) in Figure 1. Any guest that isn’t a member of at least one Microsoft 365 group is a potential delete target. As you can see from the created column, it’s easy for old and stale guest accounts to linger on unless you clean them up from time to time.

 Reporting old guest user accounts and their group membership
Figure 1: Reporting old guest user accounts and their group membership

Details of a more comprehensive report of membership of Microsoft 365 Groups including both tenant and guest members and summary details are explained in this article.


We have lots of other PowerShell examples of how to manage Azure Active Directory guest users and other Office 365 objects in the Office 365 for IT Pros eBook.

]]>
https://office365itpros.com/2019/10/15/report-old-guest-accounts/feed/ 30 5185
Microsoft 365 Groups, Send As, and the Missing NDRs https://office365itpros.com/2019/09/26/microsoft-365-groups-send-as/?utm_source=rss&utm_medium=rss&utm_campaign=microsoft-365-groups-send-as https://office365itpros.com/2019/09/26/microsoft-365-groups-send-as/#comments Thu, 26 Sep 2019 08:35:06 +0000 https://office365itpros.com/?p=4953

Senders Left Without Notice When Send As Messages Fail

Updated: May 20, 2021

The Microsoft 365 Groups Send As and Send on Behalf feature allows group members to send email for group mailboxes in the same manner as used for personal mailboxes. The Send As permission allows someone to impersonate the group so that messages sent with this permission seem to come from the group. The Send on Behalf of permission allows someone to send as the group, but the message is stamped to show that the sender is not the group but rather its representative. It’s the equivalent of a p.p. (per procurationem) signature on a paper document. Interestingly, you don’t need to be a group member to be assigned Send As or Send on Behalf of permission for the group.

The Problem Report

The first indication of a problem came in a discussion in the Microsoft Technical Community where the question was posed why people who send as a Microsoft 365 group didn’t receive Non-delivery Reports (NDRs). As it happens, after a lot of engineering effort, the NDRs generated by Office 365 are more clearer in terms of telling the sender why their message failed to be delivered and what they must do to fix the problem. Clearly, no action can be taken if a NDR is never received and the original message has literally gone into a black hole.

Investigations proved that:

  • Messages sent from a Microsoft 365 Group using the Send on Behalf of permission to a bad address resulted in a NDR being delivered to the sender.
  • Messages sent to a bad address from a personal mailbox also resulted in an NDR (as expected, but good to check anyway).
  • Messages sent from a Microsoft 365 Group using the Send As permission to a bad address resulted in no NDR being delivered to either the group or the sender.
  • A message trace showed that an NDR was processed, but that the Microsoft Agent agent handling the NDR delivered the NDR to the Deletions sub-folder in the Recoverable Items folder of the group mailbox “because of an inbox role the recipient set up” (Figure 1).

Message trace detail tells us what happened to the NDR

Microsoft 365 Groups Send As
Figure 1: Message trace detail tells us what happened to the NDR

Apart from a reference to a “group escalation agent,” the PowerShell version of the message trace didn’t turn up any more detail.

# Get message trace information for a message
 Get-MessageTraceDetail  -MessageTraceId 0941762f-0e0b-4165-d4e7-08d740d4322f -RecipientAddress exchangemvps@xxx.com | Format-List

Message Trace ID : 0941762f-0e0b-4165-d4e7-08d740d4322f
Message ID       : <bf8c2cba-748a-437d-b953-4c7e84b42d7a@am6pr04mb5255.eurprd04.prod.outlook.com>
Date             : 24 Sep 2019 09:47:22
Event            : Deliver
Action           :
Detail           : The message was successfully delivered to the folder:
                   DefaultFolderType:RecoverableItemsDeletions
Data             : <root>
<name="SourceContext" string="08D73FD41D42EEF6;2019-09-24T09:47:21.847Z;ClientSubmitTime:">
<name="MailboxServer" string="VI1PR04MB3214">
<name="DeliveryPriority" string="Normal">
<name="TotalLatency" integer="1"><mep name="ReturnPath" string="">
<name="ClientName" string="AM6PR04MB5255.eurprd04.prod.outlook.com">
<name="CustomData" blob="S:OriginalFromAddress=ExchangeMVPs@xxx.com">
<name="SequenceNumber" long="0">
<name="RecipientStatus" string="DefaultFolderType:RecoverableItemsDeletions-Group Escalation Agent">
<name="RecipientReference" string="">
</bf8c2cba-748a-437d-b953-4c7e84b42d7a@am6pr04mb5255.eurprd04.prod.outlook.com>

Rules in an Microsoft 365 Group?

There’s no easy way to create an inbox rule in a Microsoft 365 group mailbox so the explanation offered in the message trace is unlikely to be true. What’s more likely is that some condition causes the Exchange transport service to automatically route NDRs to Recoverable Items. It’s possible that an engineer thought that it would be best to suppress NDRs for messages sent as a Microsoft 365 Group, but it’s hard to understand the logic. In any case, the messages do end up in Deletions (perhaps thanks to that “group escalation agent”). That fact can be confirmed by running the Get-MailboxFolderStatistics cmdlet against the group mailbox:

# Check number of messages in the Deletions folder 
Get-MailboxFolderStatistics exchangegoms -FolderScope RecoverableItems | ?{$_.Name -eq "Deletions"}| Select Name, ItemsInFolder

Name      ItemsInFolder
----      -------------
Deletions             4

Questions, Always Questions

The big question is why Microsoft decided to route NDRs for messages sent as a Microsoft 365 Group to the Deletions folder in Recoverable Items. You might also ask why leaving the sender in perfect ignorance of their failed message was deemed to be a good idea? And then ask why the message trace report says that an inbox rule processed the NDR when it’s palpably the case that this didn’t happen. So many questions. Maybe we can get an answer at Ignite.


Need more information about Microsoft 365 Groups? We explain many of the mysteries in the Office 365 for IT Pros eBook. Uncloud your mind with the best and most comprehensive guide to Office 365 available anywhere.

]]>
https://office365itpros.com/2019/09/26/microsoft-365-groups-send-as/feed/ 11 4953
The Demise of the Office 365 Facebook Connector https://office365itpros.com/2019/09/06/demise-office-365-facebook-connector/?utm_source=rss&utm_medium=rss&utm_campaign=demise-office-365-facebook-connector https://office365itpros.com/2019/09/06/demise-office-365-facebook-connector/#respond Fri, 06 Sep 2019 09:17:19 +0000 https://office365itpros.com/?p=4654

Office 365 Notification MC189263 informs tenants who have been using the Office 365 Facebook connector that Microsoft retired the connector on September 4, 2019. The notification was posted on August 30, so tenants had just five days to react to the news. This is probably due to Microsoft’s assertion that their “telemetry indicates limited use of the connector to Facebook.” In other words, this connector wasn’t used all that much. Perhaps that’s because if you want to have a conversation in Facebook, that’s where the conversation happens.

Upon retirement, the connector is no longer able to fetch information from Facebook pages and import them into Office 365 Groups or a Teams channel (Figure 1).

Configuring the Office 365 Facebook connector to bring page information in a Teams channel
Figure 1: Configuring the Office 365 Facebook connector to bring page information in a Teams channel

You can also use Office 365 connectors with SharePoint Online and Yammer. However, I confess to only ever using connectors with Office 365 Groups and Teams.

Conversation Starters

Like all the Office 365 connectors, the function of the Facebook connector is to notify users that some information exists in a network source (in this case, one or more Facebook pages). The items are usually not complete copies of the information available in the network source and the idea is that people will see the items and start conversations about them. As you can see from Figure 2, the item posted in Teams might start a discussion about how to improve the horrible statistics of the book’s Facebook page!

A Facebook item posted by the Connector to a Teams channel
Figure 2: A Facebook item posted by the Connector to a Teams channel

Remove Connectors from View

Now that the Facebook connector has met its demise, Microsoft recommends that tenants with the connector configured for Teams or Groups should remove it. Although no great harm will come from keeping the connector in place, it won’t fetch any further data and is therefore a useless appendage on the side of an app.


Although Microsoft has retired the Office 365 Connector for Facebook, there’s still a ton of Office 365 connectors available. Learn how to use them with Office 365 Groups and Teams in the Office 365 for IT Pros eBook.

]]>
https://office365itpros.com/2019/09/06/demise-office-365-facebook-connector/feed/ 0 4654
Reporting Group-Enabled SharePoint Online Sites https://office365itpros.com/2019/08/15/reporting-group-enabled-sharepoint-online-sites/?utm_source=rss&utm_medium=rss&utm_campaign=reporting-group-enabled-sharepoint-online-sites https://office365itpros.com/2019/08/15/reporting-group-enabled-sharepoint-online-sites/#comments Thu, 15 Aug 2019 07:49:54 +0000 https://office365itpros.com/?p=3895
Analyzing group-enabled SharePoint Online sites

A Little Detail Makes the Difference

A reader asked how easy it might be to find out what SharePoint Online sites are connected to Office 365 Groups and Teams and how the link works. Well, the easy answer is to say that you can get a list of group-enabled sites by running the Get-SPOSite cmdlet as follows:

# Fetch a list of SharePoint Online sites created using the Office 365 Groups template
Get-SPOSite -Template "GROUP#0" -IncludePersonalSite:$False -Limit All

However, the output is a simple list that’s not very interesting. The list also includes sites belonging to deleted groups that are being retained by Office 365 because of a retention policy. Things get a lot more interesting when you use the group identifier for a site to look at some group information. To have SharePoint return the group identifier, you must pass the Detailed parameter to Get-SPOSite. This slows down processing, but it means that you get a group identifier. The group identifier (a GUID) can be used with the Get-AzureADGroup, Get-UnifiedGroup, and Get-Team cmdlets (alas, all in separate PowerShell modules) to fetch different information about the group. You can also use the identifier with other cmdlets to retrieve group member information, and so on.

Scripting a Report of Group-Enabled Sites

Equipped with the knowledge of how to get to group information, we can build a script to generate a report. Here’s a rough and ready script to do the job.

# Report Group-enabled SharePoint sites
# Find all sets created with the Office 365 Group template and reports them in a CSV file. Checks if group exists for the site
# and if it is enabled for Microsoft Teams
Cls
Write-Host "Analyzing SharePoint sites created with the Office 365 Groups template..."
$Sites = Get-SPOSite -Template "GROUP#0" -IncludePersonalSite:$False -Limit All
$Report = [System.Collections.Generic.List[Object]]::new()
$ErrorSites = 0
$i = 0
Foreach ($Site in $Sites) {
   $i++ 
   $ProgressBar = "Processing site " + $Site.Title + " (" + $i + " of " + $Sites.Count + ")"
   Write-Progress -Activity "Checking SharePoint Sites" -Status $ProgressBar -PercentComplete ($i/$Sites.Count*100)
   $GroupId = (Get-SpoSite $Site.Url -Detailed).GroupId.Guid
   # Check if the Office 365 Group exists
   $ErrorText = $Null
   $O365Group = $Null
   $O365Group = (Get-UnifiedGroup -Identity $GroupId -ErrorAction SilentlyContinue)
   If ($O365Group -eq $Null) {
       $O365GroupName = "Unknown Office 365 Group"
       $ErrorText = "Failed to find Office 365 Group for site " + $Site.Title + " identifier " + $GroupId
       $O365GroupMembers = 0
       $ErrorSites++ }
   Else {
       $O365GroupName = $O365Group.DisplayName
       $O365GroupMembers = $O365Group.GroupMemberCount
       # Check if site has a team
       $TeamsEnabled = $True
       Try {Get-Team -GroupId $GroupId | Out-Null}
          Catch {$TeamsEnabled = $False} }
   # Generate a line
   $ReportLine = [PSCustomObject]@{
    Site         = $Site.Title
    URL          = $Site.URL
    LastContent  = $Site.LastContentModifiedDate
    O365Group    = $O365GroupName
    Members      = $O365GroupMembers
    TeamEnabled  = $TeamsEnabled     
    Error        = $ErrorText }
  $Report.Add($ReportLine)
}
Write-Host "All done" $ErrorSites "sites reported errors"
$Report | Sort Site | Export-CSV c:\temp\Sites.csv -NoTypeInformation

As with all my scripts, there’s lots that could be done to improve the robustness of the code, improve error handling, and so on. Creating a production-ready script is not the point. What I want to illustrate is how to exploit the connection between SharePoint Online and other PowerShell modules.

Reviewing the SharePoint Online Sites Report

The report is output as a CSV file. You can add extra columns to the file by adding properties to the table generated by the script, which I’ve limited to site title, URL, the last date for content, the name of the Office 365 group, count of group members, a True/False flag to show if the group is enabled for Teams, and some error text. The date for last content modified is unreliable as content can be modified by background activities, so it’s included as an example of using information returned by Get-SPOSite. Figure 1 shows an example of the CSV file.

Reviewing group-connected SharePoint Online sites in Excel
Figure 1: Reviewing group-connected SharePoint Online sites in Excel

The script highlights sites that have a group identifier that no longer points to a valid Office 365 group. These situations are likely to be caused by groups that have been removed but the site remains, probably because an Office 365 retention policy governs the site. You can try to remove the site in the SharePoint Online Admin Center: if you see an error, you know that a retention policy is blocking the deletion.

I look forward to hearing how people amend or expand the script to meet different circumstances. Please post a comment if you do.


For more information about working with SharePoint Online, Groups, and Teams through SharePoint, see the hundreds of code examples included in the Office 365 for IT Pros eBook. We’re bound to have something that will make you think!

]]>
https://office365itpros.com/2019/08/15/reporting-group-enabled-sharepoint-online-sites/feed/ 5 3895
Creating a Dynamic Office 365 Group for Global Administrators https://office365itpros.com/2019/06/27/creating-dynamic-office-365-group-global-administrators/?utm_source=rss&utm_medium=rss&utm_campaign=creating-dynamic-office-365-group-global-administrators https://office365itpros.com/2019/06/27/creating-dynamic-office-365-group-global-administrators/#respond Thu, 27 Jun 2019 07:21:56 +0000 https://office365itpros.com/?p=3206

Dynamic Group Membership Rules are Limited

A reader asks if it is possible to create a dynamic Office 365 Group for all the global administrators in a tenant. Sounds like an interesting request, so let’s dive in and do some research.

A dynamic Office 365 Group is like any other dynamic Azure Active Directory group. It depends on a membership rule to define the membership. Azure Active Directory runs background processes to use the rule to query the directory and return a list of members. The key to the answer therefore lies in if it is possible to construct a membership rule to query Azure Active Directory to find the accounts who are global administrators.

Membership Rules for Dynamic Groups

The Microsoft documentation for how to build membership rules for dynamic groups tell us the set of supported properties for rules. Reading through the list, we quickly discover that there’s no way to query the roles held by accounts. Azure Active Directory supports a set of roles that can be assigned to users; the one we’re interested in is the Company Administrator role, which is also known as a global or tenant administrator. To find the accounts that hold the role in a tenant, we can execute the PowerShell command:

# Discover the set of global administrators
Get-AzureADDirectoryRoleMember -ObjectId (Get-AzureADDirectoryRole |?
{$_.DisplayName -eq "Company Administrator"}).ObjectId |Format-Table ObjectId, DisplayName

These cmdlets are in the Azure AD Module (V2).

Finding a Property to Use

Good as it is to be able to find the set of global administrators, it doesn’t help us build a membership rule for a dynamic Office 365 group. But what we can do is find a property in the set supported by membership rules and use it to mark our tenant administrators.

For example, we could use the JobTitle property and say that anyone with a job title of “Office 365 Global Administrator” should be included in the dynamic group. With this decision made, we can update the accounts of the current global administrators to have the correct value:

# Make sure that tenant administrators have the correct job title
$Admins = Get-AzureADDirectoryRoleMember -ObjectId (Get-AzureADDirectoryRole |? {$_.DisplayName -eq "Company Administrator"}).ObjectId | Select ObjectId, DisplayName
ForEach ($Admin in $Admins) {
    If ($Admin.DisplayName -ne "Microsoft Rights Management Services") {
    Set-AzureADUser -Object $Admin.ObjectId -JobTitle "Office 365 Global Administrator" }}

The Microsoft Rights Management Services account is excluded because it’s not used by humans.

Hybrid is Different

Note: If you are in a hybrid organization, you can use the fifteen extended properties synchronized from Active Directory and populate these values by running the Set-Mailbox cmdlet. These properties are not available in a cloud-only tenant because the schema isn’t extended to allow synchronization of the properties from the on-premises directory.

Creating a Dynamic Office 365 Group with PowerShell

Now we can create our dynamic Office 365 group. It’s easiest to do this through the GUI of the Azure AD portal, but here’s how to create the dynamic group with PowerShell:

# Create Dynamic Office 365 Group
New-AzureADMSGroup -DisplayName "Global Tenant Administrators" -Description "Dynamic Office 365 Group for all the global tenant administrators" -MailEnabled $True -SecurityEnabled $True -MailNickname Office365GlobalAdmins -GroupTypes "DynamicMembership", "Unified" -MembershipRule "(User.JobTitle -eq ""Office 365 Global Administrator"")" -MembershipRuleProcessingState "On 

After a short while, the background job to calculate the group membership will complete and you can check if the correct members are present. Again, the GUI is the easiest way to check the membership (Figure 1)

Checking the membership of a dynamic Office 365 group
Figure 1: Checking the membership of a dynamic Office 365 group

Checking the overview for the group will tell us when Azure Active Directory last calculated the membership (Figure 2).

Checking when the membership of a dynamic Office 365 group was last calculated
Figure 2: Checking when the membership of a dynamic Office 365 group was last calculated

Imperfect Solution

This is an imperfect solution albeit one that works: if the job title for a global administrator is set correctly, they will be part of the dynamic Office 365 group. It would be better if Azure Active Directory supported the ability to include a more extensive set of queries in dynamic groups. That might happen in the future, but for the moment we can only work with what we have.

And if a dynamic distribution group will work for you, the solution described by Vasil Michev works because Exchange Online is more flexible than Azure Active Directory in terms of the recipient filters it supports.


This is the kind of practical challenge we discuss in many places in the Office 365 for IT Pros eBook. If you run an Office 365 tenant, can you afford to be without a copy of Office 365 for IT Pros?

]]>
https://office365itpros.com/2019/06/27/creating-dynamic-office-365-group-global-administrators/feed/ 0 3206
New OWA Includes Office 365 Groups Management Interface https://office365itpros.com/2019/06/05/owa-new-groups-management-interface/?utm_source=rss&utm_medium=rss&utm_campaign=owa-new-groups-management-interface https://office365itpros.com/2019/06/05/owa-new-groups-management-interface/#comments Wed, 05 Jun 2019 06:40:45 +0000 https://office365itpros.com/?p=3009

Manage the Settings of Office 365 Groups through OWA

Given the attention Microsoft dedicates to Teams, it’s sometimes difficult to remember that many people use Outlook Groups via OWA or Outlook as their collaboration platform. An Outlook group is an Office 365 Group that stores conversations in the group mailbox instead of Teams or Yammer. Although more people tend to use Outlook than OWA as their full-time client, the restricted nature of the Outlook user interface makes it difficult to introduce new Outlook Groups features. On the other hand, OWA is in a perpetual state of development and evolution, and every time you look at the browser client, it seems to have changed slightly.

OWA group management has never been particularly strong, but now it’s been revamped in the new version of OWA. The new Groups management UI is revealed through the Manage Groups section in OWA’s email tab or in the Groups section of OWA’s People tab.

Group members and owners can see details of the groups they belong to (including group membership), perform actions like leave the group, and access the different resources associated with a group. Members can also create invitations for others to join a group. Invitations to public

Owner Settings

Owners have additional options as they can edit the group settings and take care of any issues that need action to maintain the group. For example, in Figure 1 we see that the group is under the control of the Office 365 Groups expiration policy (explained in Chapter 10) and that it is due to expire in 18 days. The owner can renew the group or, if the group has served its function and is no longer needed, allow it to expire and go into the removal cycle. During the cycle, owners have 30 days during which they can recover a deleted group. To do this, open the Deleted link under Groups, select the group you want to restore, and click the Restore button.

Managing an Office 365 group through the People section of OWA
Figure 1: Managing an Office 365 group through the People section of OWA

Notice that OWA puts groups with outstanding actions at the top of the list. We can see that one of the flagged groups has a pending join request while the others are awaiting renewal.

Other Ways of Managing Group Settings in OWA

The group management interface isn’t the only place you can edit group settings. If you open a group in the Mail section of OWA and click the member link, you see the UI shown in Figure 2 and the option to edit group settings is in the […] menu.

Managing Office 365 group membership through OWA
Figure 2: Managing Office 365 group membership through OWA

You can also click on a group’s card to expose the Edit group option. The same UI and capabilities are displayed in both cases.

Although you can’t do everything to manage group settings through OWA, the new group management UI is a major improvement to the previous interface. You still have to use PowerShell for some management operations for Office 365 Groups, but not as many as you had to before.


Need to know more about Office 365 Groups? We dedicate two chapters of the Office 365 for IT Pros eBook to Office 365 Groups, and even more if you count the chapter on using PowerShell to manage Office 365 Groups and Teams.

]]>
https://office365itpros.com/2019/06/05/owa-new-groups-management-interface/feed/ 1 3009
Managing Office 365 Group Membership with PowerShell https://office365itpros.com/2019/05/30/managing-office-365-group-membership-powershell/?utm_source=rss&utm_medium=rss&utm_campaign=managing-office-365-group-membership-powershell https://office365itpros.com/2019/05/30/managing-office-365-group-membership-powershell/#respond Thu, 30 May 2019 14:46:33 +0000 https://office365itpros.com/?p=2977

Want Dynamic Groups But Don’t Want to Pay for Azure Active Directory Premium Licenses? Here’s How to Do the Job

A reader says that they like the notion of dynamic Office 365 groups, but they don’t want to pay for the Azure Active Directory premium licenses needed to use the feature. As you might recall, dynamic groups have their membership controlled by queries executed against Azure Active Directory. Every account that comes within the scope of a query must be licensed.

Instead of using dynamic groups, our reader is willing to run scheduled background jobs to populate the membership. They need some guidance as to how to approach building the script to manage membership for a group. As an example to help them, this post describes how to manage group membership based on Office location. Our first step is therefore to grab a set of mailboxes with the right value for the Office attribute and store it in a PowerShell variable. Because I’m based in Dublin, I’ll use it as the Office location.

$Mbx = (Get-Mailbox -Filter {Office -eq "Dublin"} -ResultSize Unlimited)

Using the Filter parameter is important because this forces Exchange Online to process the query on the server, and we get the right results faster. That is, if your directory is correctly populated.

Adding Members to an Office 365 Group

To update the membership of an Office 365 group, we use the Add-UnifiedGroupLinks cmdlet. The simplest method is to use the variable holding the set of mailboxes as the input, passing the distinguished name of each mailbox as the link. To test everything, I created a new group called Dublin Employees and then ran this code to populate its membership.

Add-UnifiedGroupLinks -Identity DublinEmployees -LinkType Member -Links $Mbx.DistinguishedName

To check that the correct membership has been added, we can run the Get-UnifiedGroupLinks cmdlet:

Get-UnifiedGroupLinks -Identity DublinEmployees -LinkType Member

Maintaining Membership

All easy so far, but the issue is now how to maintain the membership. We don’t have to worry about deleted mailboxes as they lose membership when they are removed. But we do need to add new employees whose accounts match the filter and remove people who no longer match.

Adding new members is straightforward because we can use the same commands to form a set of matching mailboxes and run the Add-UnifiedGroupLinks command again. Exchange Online will ignore mailboxes that already exist in the membership.

Mailboxes that no longer match can be removed by running the Remove-UnifiedGroupLinks cmdlet. However, we must figure out what members to remove. One way to do this is to check the current membership against the set of mailboxes that should be members and remove any members that no longer qualify. In this code snippet, we create a hash table and populate it with the set of mailboxes (it’s faster to check against a hash table if the membership is large). We then check each of the members in the current membership against the hash table. Any member that isn’t found in the table doesn’t work in the Dublin office, so we go ahead and remove them.

# Remove lingering members from the group after they leave the Dublin office.
$Members = (Get-UnifiedGroupLinks -Identity DublinEmployees -LinkType Member | Select Alias, DistinguishedName, DisplayName)
$MembersHash = @{}
# Populate MembersHash with the current set of mailboxes from the Dublin office
ForEach ($M in $Mbx) {$MembersHash.Add($M.DistinguishedName, $M.Alias) }
# Check each member in the current membership. If they're not in the mailbox hash table, remove them from the membership
ForEach ($Member in $Members) {
  If ($MembersHash.ContainsKey($Member.DistinguishedName) -eq $False) {
     Write-Host "Removing" $Member.DisplayName "from Dublin Employees membership" 
     Remove-UnifiedGroupLinks -Identity DublinEmployees -Linktype Member -Links $Member.Alias -Confirm:$False }
}

Dealing With Group Owners

One small glitch. Group owners are also members, but a group owner might not belong to the Dublin office. The command fails if you run Remove-UnifiedGroupLinks to remove an owner from the member list without removing them as an owner first. As we don’t want to see any nasty errors, we should incorporate a check for owner status before we try to remove a member. Here’s the change I made to the script.

# Include check for group owners before we delete a member
ForEach ($Member in $Members) {
  If ($MembersHash.ContainsKey($Member.DistinguishedName) -eq $False) {
    If ((Get-UnifiedGroupLinks -id "Dublin Employees" -LinkType Owner | Select Alias) -Match $Member.Alias) {
       Write-Host "Can't remove" $Member.DisplayName "as member - they are group owner." }
    Else {
       Write-Host "Removing" $Member.DisplayName "from Dublin Employees membership" 
       Remove-UnifiedGroupLinks -Identity DublinEmployees -Linktype Member -Links $Member.Alias -Confirm:$False }
}}

Because Teams uses Office 365 Groups to manage the membership of teams, the same approach works for Teams without the need to rewrite to use the cmdlets in the Teams PowerShell module.

More Work to Do

I’m sure other bells and whistles could be added to make the code work the way an organization wants, but that’s not the purpose of this post. I set out to answer the question and give some guidance about the commands used to maintain Office 365 group membership. There’s enough here for serious programmers (more serious than I am) to get their teeth into the problem and craft a production-quality solution.


For more information about using PowerShell to manage Office 365 Groups (and Teams), read the comprehensive chapter in the Office 365 for IT Pros eBook.

]]>
https://office365itpros.com/2019/05/30/managing-office-365-group-membership-powershell/feed/ 0 2977
Using PowerShell to Add Teams to the Groups Expiration Policy https://office365itpros.com/2019/05/24/powershell-add-teams-groups-expiration-policy/?utm_source=rss&utm_medium=rss&utm_campaign=powershell-add-teams-groups-expiration-policy https://office365itpros.com/2019/05/24/powershell-add-teams-groups-expiration-policy/#comments Fri, 24 May 2019 07:30:26 +0000 https://office365itpros.com/?p=2916

Easily Done, But Prepare for Teams That Expire Afterwards

A contribution to the Microsoft Technical Community offered a solution for how to add all the Teams in an Office 365 tenant to the Office 365 Groups Expiration Policy. Once teams are added to the policy, the groups they belong to expire at the end of the policy lifetime (say, 750 days) and must be renewed by a team owner. If not, the group is soft-deleted for 30 days, during which time it can be recovered. At the end of that period, Office 365 permanently removes the group for the team and all the associated resources.

In any case, the script worked on the basis of finding all the Office 365 Groups in the tenant and then figuring out which groups are team-enabled before adding those groups to the policy. It’s a valid approach, but a better method is to use the Get-Team cmdlet in the Teams PowerShell module because it only returns the set of teams and you don’t have to fiddle around checking what groups are team-enabled.

Once you have the set of teams, it’s easy to add them to the expiration policy using the Add-AzureADMSLifecyclePolicyGroup cmdlet.

Tuning The Solution

A script showing how to add multiple groups to the expiration policy is included in the chapter covering how to manage Groups and Teams in the Office 365 for IT Pros eBook. It was simple to take that script and amend it to process Teams rather than Groups. We can improve the solution further by implementing a check for teams already covered by the policy so we don’t trigger an error when running Add-AzureADMSLifecyclePolicyGroup.

One way to do this is to update one of the fifteen custom attributes available for all mail-enabled objects. In the example, we write the GUID of the policy into this attribute, meaning that we can check for its existence before trying to add a team to the policy. Here’s the code:

# Add all Teams that aren't already covered by the Groups expiration policy 
# to the policy
$PolicyId = (Get-AzureADMSGroupLifecyclePolicy).Id
$TeamsCount = 0
Write-Host "Fetching list of Teams in the tenant…"
$Teams = Get-Team
ForEach ($Team in $Teams) {
  $CheckPolicy = (Get-UnifiedGroup -Identity $Team.GroupId).CustomAttribute3
  If ($CheckPolicy -eq $PolicyId) {
    Write-Host "Team" $Team.DisplayName "is already covered by the expiration policy" }
  Else { 
    Write-Host "Adding team" $Team.DisplayName "to group expiration policy"
    Add-AzureADMSLifecyclePolicyGroup -GroupId $Team.GroupId -Id $PolicyId -ErrorAction SilentlyContinue
    Set-UnifiedGroup -Identity $Team.GroupId -CustomAttribute3 $PolicyId
    $TeamsCount++ }}
Write-Host "All done." $TeamsCount "teams added to policy"

Another advantage of using a custom attribute is that many cmdlets support server-side filtering for this attributes. For instance, to find the set of teams that have been added to the expiration policy, we can run the command:

Get-UnifiedGroup -Filter {CustomAttribute3 -ne $null} | Format-Table DisplayName, CustomAttribute3

Update After Groups Expiration Policy Update

After I wrote the original post, Microsoft updated the Groups expiration policy to be activity based. A side effect of the change was that the Get-UnifiedGroup cmdlet returns the calculated expiration date for groups covered by the policy, meaning that you could use this instead of a custom attribute to figure out what groups are covered by the policy. Thus, we can now base the script on the expiration date as shown below.

$PolicyId = (Get-AzureADMSGroupLifecyclePolicy).Id
Write-Host "Fetching list of Teams in the tenant…"
[array]$Teams = Get-Team
$TeamsCount = 0
ForEach ($Team in $Teams) {
  $CheckPolicy = $Null
  $CheckPolicy = (Get-UnifiedGroup -Identity $Team.GroupId).ExpirationTime
  If ($CheckPolicy -ne $Null) {
    Write-Host "Team" $Team.DisplayName "covered by expiration policy and will expire on" (Get-Date($CheckPolicy) -format g)}
  Else { 
    Write-Host "Adding team" $Team.DisplayName "to group expiration policy" -Foregroundcolor Red
    Add-AzureADMSLifecyclePolicyGroup -GroupId $Team.GroupId -Id $PolicyId -ErrorAction SilentlyContinue
    Set-UnifiedGroup -Identity $Team.GroupId -CustomAttribute3 $PolicyId
    $TeamsCount++ }}
Write-Host "All done." $TeamsCount "Teams added to policy"

In turn, this means that to find the groups covered by the policy you can do the following (unfortunately the ExpirationTime property is not supported for server-side filtering):

[array]$Groups = Get-UnifiedGroup -ResultSize Unlimited |? {$_.ExpirationTime -ne $Null}  
$Groups | Sort Expirationtime | Format-Table DisplayName, ExpirationTime 

Expiring Groups

After you add a bunch of groups to the expiration policy, the likelihood exists that some of those groups will expire because they are already older than the expiration period. For this reason, it’s a good idea to prepare team owners to let them know what to do if they see an expiration notice. If the group is team-enabled, the notification appears in the activity feed of the team owner (Figure 1).

Expiring teams show up in the team owner's activity feed
Figure 1: Expiring teams show up in the team owner’s activity feed

They can then extend the lifetime of the team by editing its settings. Select the team expiration option to view the current expiration date and then click Renew now (Figure 2) if needed.

Renewing an expired group via Teams settings
Figure 2: Renewing an expired group via Teams settings

Need more examples of how to manage Teams and Office 365 Groups (and many other things) with PowerShell? Look no further than the Office 365 for IT Pros eBook. At the last count, the text included over a thousand examples.

]]>
https://office365itpros.com/2019/05/24/powershell-add-teams-groups-expiration-policy/feed/ 7 2916
Office 365 Groups Naming Policy Now Configurable in Azure Active Directory Portal https://office365itpros.com/2019/05/16/office-365-groups-naming-policy-now-in-azure-active-directory-portal/?utm_source=rss&utm_medium=rss&utm_campaign=office-365-groups-naming-policy-now-in-azure-active-directory-portal https://office365itpros.com/2019/05/16/office-365-groups-naming-policy-now-in-azure-active-directory-portal/#comments Thu, 16 May 2019 08:38:31 +0000 https://office365itpros.com/?p=2776

Use PowerShell or the Portal to Configure Office 365 Groups Naming Policy

The naming policy for Office 365 Groups allows tenants to enforce a naming policy for new Office 365 Groups created by users through group-enabled applications like Teams, Outlook, Planner, Stream, and Yammer. The policy does not apply to groups created by administrators.

Since 2016, administrators have configured the naming policy through PowerShell. Now they’ve released a preview to do the same job in the Azure Active Directory portal (Figure 1). Go to the groups section of the portal and you’ll find the naming policy listed under Settings.

Configuring the Office 365 Groups Naming Policy in the AAD portal
Figure 1: Configuring the Office 365 Groups Naming Policy in the AAD portal

There’s no doubt that configuring policy settings through a GUI is much easier than messing around with PowerShell, especially given the somewhat cryptic steps needed to manipulate policy settings for Azure Active Directory policy objects. Apart from setting prefix and suffix variables to add to user-provided names, the portal also allows you to manage blocked words. These are words that you don’t want people to use in group names. Some of the words are functional, like “Payroll” and “CEO,” and some are offensive terms.

Policy Not Retrospective

Remember that the Groups Naming Policy only applies to new groups and doesn’t apply its naming standard retrospectively to old groups. If you want to use the new standard with old groups, you’re going to have to write some PowerShell. Thankfully, this is relatively easy (see Chapter 12 of Office 365 for IT Pros for some hints and sample code).

Premium AAD Feature

Using the Office 365 Groups Naming policy is a premium Azure Active Directory feature requiring users to have Azure Active Directory Premium P1 licenses. Given the revelation at Microsoft’s FY19 Q3 earnings call that Enterprise Mobility and Security has 100 million users (much of the enterprise Office 365 population), this shouldn’t be much of a problem for the organizations that need policies like this to exert control over group sprawl.


For information about the policies used to control Office 365 Groups, read Chapter 12 of the Office 365 for IT Pros eBook.

]]>
https://office365itpros.com/2019/05/16/office-365-groups-naming-policy-now-in-azure-active-directory-portal/feed/ 6 2776
Limiting SharePoint Storage for Teams https://office365itpros.com/2019/05/09/limiting-sharepoint-storage-teams/?utm_source=rss&utm_medium=rss&utm_campaign=limiting-sharepoint-storage-teams https://office365itpros.com/2019/05/09/limiting-sharepoint-storage-teams/#comments Thu, 09 May 2019 08:44:28 +0000 https://office365itpros.com/?p=2407

A Profusion of Teams Can Consume Storage

When Teams creates a new team, it provisions a SharePoint Online team site along with other resources like a shared notebook and wiki. All of this is goodness, unless you like managing SharePoint storage manually.

SharePoint Site Storage Management

By default, SharePoint Online uses a central pool of storage that all sites draw upon on an as-needed automatic basis up to a maximum of 25 TB per site. Sounds good, because who wants to keep a close eye on site storage quotas to adjust them whenever sites need more space to allow users to store documents and do other useful work. But the downside is that if you allow free creation of Office 365 groups and teams, the central pool can be absorbed quicker than you anticipate and force the tenant to buy more storage from Microsoft just to keep operations running.

Enterprise tenants get 1 TB of SharePoint storage plus 10 GB per licensed Office 365 account. The new SharePoint Online Admin Center makes it easy to see how much storage the tenant has and what sites are consuming most storage. You can also export details of sites to a CSV file to dice and slice the data as you want.

Tracking storage usage with the (new) SharePoint Admin Center
Tracking storage usage with the (new) SharePoint Admin Center

If you use Office 365 retention policies to make sure that documents are kept for specific periods, you’ll discover that more storage is consumed because SharePoint must keep copies of deleted files. In any case, most tenants are happy to leave SharePoint to manage site storage automatically, which is the default management setting for Office 365 tenants. You only need to change the Site storage limits setting to Manual in the SharePoint Admin Center if you want to control the storage allocation for individual sites.

SharePoint Online site storage management settings
SharePoint Online site storage management settings

Controlling Individual Site Storage

One reason why you might want to control storage for individual sites is when a tenant makes extensive use of Teams and you don’t want the sites created for teams to be able to grow to 25 TB. In this scenario, you can switch the Site storage limit setting to Manual and then:

  • Edit the storage quota for each site through the SharePoint Admin Center, or
  • Use PowerShell to set a storage quota for every site associated with Teams and then adjust the quota upwards as necessary for individual sites.

Given the number of sites that you might need to process, the second option (PowerShell) is best.

Setting Storage Quotas for SharePoint Sites with PowerShell

The only complication we face is that the cmdlets needed for the job are spread across three modules: Teams, Exchange Online, and SharePoint Online. Once you’ve loaded the modules and connected to the three endpoints with a tenant administrator account, the code to update sites is pretty simple:

  • Find all teams.
  • Find the SharePoint site URL for each time (already covered in a previous post).
  • Update the storage quota for the site.

Here’s some code to do the work. In this example, we set a 20 GB quota for each site with a warning limit at 98% of quota:

# SetTeamsSitesStorage.PS1
# Set the storage for the SharePoint sites belonging to Teams to a certain storage value
#
# Find Teams
Write-Host "Finding Teams in the Tenant..."
$Teams = (Get-Team -Visibility Public | Select DisplayName, GroupId)
ForEach ($T in $Teams) {
    $SPOUrl = (Get-UnifiedGroup -Identity $T.GroupId | Select -ExpandProperty SharePointSiteURL)
    If ($SPOUrl -ne $Null) {
       Write-Host "Setting SharePoint Site quota to 20 GB for" $T.DisplayName
       # Set storage value for SharePoint site
       Set-SPOSite -Identity $SPOUrl -StorageQuota 20480 -StorageQuotaWarningLevel 20070 }
    Else {Write-Host "Can't Process storage update for" $T.DisplayName "- Please check SharePoint site" -ForegroundColor Red}}}

After you’ve set the storage quotas for the sites owned by Teams, you can set the Site storage limits setting back to Automatic to allow SharePoint to manage storage for the sites that don’t belong to Teams.

Of course, the problem with any procedure like this is that you need to periodically rerun the code to deal with newly-created sites. To avoid reprocessing sites, you could update one of the 15 customized attributes available for Office 365 groups when you set the storage for a site and check if the attribute is set the next time the script runs.

—————————————

For more on managing Teams with PowerShell, read Chapter 14 of the Office 365 for IT Pros eBook.

]]>
https://office365itpros.com/2019/05/09/limiting-sharepoint-storage-teams/feed/ 2 2407
Office 365 Groups Naming Policy Now Generally Available https://office365itpros.com/2019/03/11/groups-naming-policy-generally-available/?utm_source=rss&utm_medium=rss&utm_campaign=groups-naming-policy-generally-available https://office365itpros.com/2019/03/11/groups-naming-policy-generally-available/#comments Mon, 11 Mar 2019 11:32:19 +0000 https://office365itpros.com/?p=2046

Sometimes Office 365 Moves at the Pace of Cold Treacle

Office 365 Groups Naming Policy in action
Office 365 Groups Naming Policy in action

In a piece of earth-shattering news released on March 8, Microsoft said that the Office 365 Groups Naming Policy is now Generally Available. The policy allows organizations to define a prefix or suffix to be added to group names, something often done to highlight the fact that these directory objects are groups and to gather them together in the directory. Groups created by tenant administrators are not subject to the group naming policy.

Quite how Microsoft has the brass neck to call this a “new feature” is beyond me considering that the naming policy has been in use for nearly two years. In fact, the naming policy was one of those called out by Microsoft when they discussed licensing requirements for premium Groups features at Ignite 2017.

What’s surprising is how little has changed in the time when the naming policy was in preview. You still must configure the policy through PowerShell as no management GUI supports the ability to enable and change its settings. I guess the time in preview was occupied persuading Office 365 applications that create groups to respect the policy. This is true for Outlook, Yammer, Stream, Teams, and Planner.

Editor’s Note: In May 2019, Microsoft released a preview GUI to configure the naming policy through the Azure Active Directory portal.

Licensing Office 365 Groups

Licensing is likely to be the issue that stops many Office 365 tenants using the naming policy. Unless you’ve bought Enterprise Mobility and Security (which includes the necessary Azure Active Directory Premium licenses) or purchased the AAD Premium licenses separately, the need to buy “an Azure AD Premium license for every user who creates groups, is a member of the group and the admin who creates the Groups naming policy” is a big ask.

I’ve always thought that Microsoft is asking too much when they look for extra money for a naming policy. After all, Exchange Online bundles a naming policy for distribution lists free of charge. The Exchange policy is similar to the groups naming policy and consists of being able to define how distribution list names should be constructed and a list of bad words to avoid. And while you can configure the Exchange policy in PowerShell, it does boast a UI in the Exchange Admin Center.

And if Microsoft ever wants tenants to move away from distribution lists, they shouldn’t erect barriers like additional fees, especially when the naming policy is not integrated into a management GUI like the Office 365 Admin Center.

Large Organizations Might Not Care

To be fair, policies like this are of most interest to large organizations who might well have invested in EM+S (or Microsoft 365), but if you haven’t then you could run up quite a cost. Microsoft lists Azure Active Directory Premium P1 at $6/user per month if you buy online. Organizations that have an Enterprise Agreement with Microsoft pay less. Even so, the bill for Azure Active Directory P1 for a 10,000 user tenant could easily be multiple tens of thousands of dollars monthly.

Of course, you get more than a naming policy for your money. Azure Active Directory Premium also includes useful functionality like dynamic Office 365 Groups and the group expiration policy, along with some dubious features that it’s difficult to attribute the premium label to, like being able to set a default classification (a very simple label) to Office 365 Groups.

PowerShell Alternative

If you think a naming policy is important, you can build one yourself with PowerShell. You could even take the naming policy used for distribution lists and apply it to Office 365 Groups. Here’s a really simple example of what you could do.

  • Retrieve the DL naming policy from the Exchange organization configuration.
  • Extract the prefix (for the purpose of this demonstration, we only use the prefix)
  • Find all the Office 365 Groups in the organization (don’t use Get-UnifiedGroup as it’s too slow). Select the alias and display name properties as they are all we need to process.
  • Loop through our set to find groups with a display name that doesn’t have the prefix and update the display name property with a new value.
$Policy = Get-OrganizationConfig | Select -ExpandProperty DistributionGroupNamingPolicy
$Prefix = $Policy.Split("-")[0]

$Groups = Get-Recipient -RecipientTypeDetails GroupMailbox | Select Alias, DisplayName

ForEach ($G in $Groups) {
  If ($G.DisplayName -notmatch "O365Grp-") {
  $NewDisplayName = "O365Grp-" + $G.DisplayName
  Set-UnifiedGroup -Id $G.Alias -DisplayName $NewDisplayName 
  Write-Host "New display name for" $G.DisplayName "is" $NewDisplayName }
}

Obviously this is very simple code and there are many twists that you could incorporate to make it fit for purpose for operational use.

Updating display names is easy. The biggest value in Microsoft’s naming policy is that clients respect the policy and won’t allow users to create group names outside the policy. If you use your own code, you’ve got to scan periodically for new groups and also look for any groups that need to be updated if owners change display names outside the policy.

One Last Thing

The Office 365 naming policy is not retrospective. It does not look for groups created before the introduction of the policy to update their display names to comply with policy settings. Again, this is relatively easily done with PowerShell, but it’s a task that shouldn’t be overlooked (we include some sample code for the purpose in Chapter 12 of the Office 365 for IT Pros eBook.

]]>
https://office365itpros.com/2019/03/11/groups-naming-policy-generally-available/feed/ 3 2046
Tuning PowerShell for Office 365 Group Membership https://office365itpros.com/2019/01/28/tuning-powershell-office-365-group-membership/?utm_source=rss&utm_medium=rss&utm_campaign=tuning-powershell-office-365-group-membership https://office365itpros.com/2019/01/28/tuning-powershell-office-365-group-membership/#respond Mon, 28 Jan 2019 11:07:52 +0000 https://office365itpros.com/?p=1494

Making PowerShell Faster with Office 365 Groups

A recent Practical365.com article by Steve Goodman covering how to export the membership of an Office 365 group to a CSV file caused me to test a recommendation we make in Chapter 14 of the Office 365 for IT Pros eBook.

The recommendation is to select properties that you want to process when fetching a set of objects like mailboxes or groups. The idea is that this approach results in a set of filtered objects instead of needing an extra step to use ForEach-Object to loop through the set to fetch properties.

Exporting Group Membership

In this instance, Steve’s script calls the Get-UnifiedGroupLinks cmdlet to get the membership of a group. He then loops through the membership to extract the primary SMTP address for each member. Nice and simple.

As it happens, Get-UnifiedGroupLinks is a “heavy” cmdlet because it returns the same set of properties as a call to Get-Mailbox (for a tenant user) or Get-MailUser (for a guest member). If you examine the set of properties returned, you’ll see how many they are. For example:

$Members = Get-UnifiedGroupLinks -Identity ExchangeGoms -LinkType Member
$Members[0] | Format-List

Returning to my theory that we can speed things up by selecting the required properties by piping the output of a cmdlet to Select-Object, we can use PowerShell’s Measure-Command cmdlet to test if it is any faster.

Here’s the code from the article as fed through Measure-Command:

Measure-Command { $Members = Get-UnifiedGroupLinks -Identity ExchangeGoms -LinkType Members -ResultSize Unlimited
    $MembersSMTP=@()
    foreach ($Member in $Members) {$MembersSMTP+=$Member.PrimarySmtpAddress}}

Seconds           : 0
Milliseconds      : 858
Ticks             : 8586323
TotalSeconds      : 0.8586323
TotalMilliseconds : 858.6323

Not too bad. Now let’s try the alternative. As you can see, this result is faster.

Measure-Command {$MembersSMTP = (Get-UnifiedGroupLinks -Identity ExchangeGoms -LinkType Members -ResultSize Unlimited | Select PrimarySmtpAddress)}

Seconds           : 0
Milliseconds      : 522
Ticks             : 5222026
TotalSeconds      : 0.5222026
TotalMilliseconds : 522.2026

Extended Testing

I used an Office 365 group with 51 members to test both approaches. The results of a single run (above) shows that avoiding a loop is faster and I suspect that the impact is greater as group membership grows. However, it’s important to recognize that demand on the Exchange Online server that handles the request can vary the results of any PowerShell command, so I ran both commands twenty times to see if the advantage is kept over an extended series. The results showed that using a ForEach loop to extract properties is about 9% slower than extracting with Select.

Warning! Your mileage may vary depending on the number of members in the group and the type of members (users versus guests). Even so, the exercise proves that it is possible to improve PowerShell performance by paying attention to what you ask Office 365 to return as a response to a command. Whether or not the extra performance will make any difference or be noticeable is entirely a different matter.


For more information about using PowerShell to manage Office 365 Groups and Teams, see Chapter 14 of the Office 365 for IT Pros eBook.

]]>
https://office365itpros.com/2019/01/28/tuning-powershell-office-365-group-membership/feed/ 0 1494
How to Post Information to Microsoft 365 Groups or Teams Channels https://office365itpros.com/2019/01/14/inbound-webhook-connector/?utm_source=rss&utm_medium=rss&utm_campaign=inbound-webhook-connector https://office365itpros.com/2019/01/14/inbound-webhook-connector/#comments Mon, 14 Jan 2019 10:22:30 +0000 https://office365itpros.com/?p=1382

Use Inbound WebHook Connector to Fetch and Post Service Information

Chapter 14 of the Office 365 for IT Pros eBook describes an example of how to post messages to an Office 365 group or a team channel using the inbound webhook connector. The inbound webhook connector is one of the standard connectors supported by Office 365. In this context, you can think of the webhook as a URI that Office 365 can use to find a target destination into which it posts messages. The posted messages are in JSON format and are called cards.

The process to connect a webhook to a team channel or Office 365 group is similar. Select the inbound webhook from the set of connectors available, give it a name and a replacement icon (if you want), and Office 365 responds with a webhook address. You can then copy that address and use it in scripts. The address will be something like this (the format changed in 2021):

https://outlook.office.com/webhook/5348781d-52a8-490f-b75b-a72e702114d1@b662313f-14fc-43a3-9a7a-d2e27f4f3478/IncomingWebhook/f286f53c0d244ebdba7fea50035f35df/eff4cd58-1bb8-4899-94de-795f656b4a18

Creating an inbound webhook for a Teams channel

inbound webhook connector
Figure 1: Creating an inbound webhook connector for a team channel

Using PowerShell to Post to the Inbound Webhook Connector

In any case, it’s pretty simple to write some PowerShell to fetch some data, format it, and post a card with the data to Office 365. The example we have in the book uses information about Office 365 service incidents, but anything you can fetch with PowerShell will do. The service incidents are gathered using the Office 365 service communications module for PowerShell.

The biggest challenge isn’t usually to find data to post. Instead, the usual issue that people run into is to format the JSON payload for the post. Microsoft has a message card “playground” to help people design actionable cards. We don’t need to go quite that far for the relatively simple and static card used in the demo, but you might like to explore the possibilities in the playground and see how the JSON structure is built out.

A Reader Suggestion

A reader suggested that instead of hand-crafting the card for each post, it would be simpler to create a template post and replace fields in the template before posting to the webhook. This seemed like a good idea, so we tried. The script below creates a template, then finds some service data, and updates the template to create a new JSON card before posting it to a team channel. Exactly the same code would work with a Microsoft 365 group if you change the target to a webhook pointing to the group.

$Notification = @"
    {
        "@type": "MessageCard",
        "@context": "https://schema.org/extensions",
        "summary": "Office 365 Notification",
        "themeColor": "0072C6",
        "title": "Office 365 Service Degradation",
         "sections": [
            {
            
                "facts": [
                    {
                        "name": "Service Incident:",
                        "value": "ID"
                    },
                    {
                        "name": "Start time:",
                        "value": "DATETIME"
                    },
                    {
                        "name": "Service:",
                        "value": "SERVICENAME"
                    },
                    {
                        "name": "Description:",
                        "value": "MESSAGE"
                    }
                ],
                "text": "Office 365 Service Problem"
            }
        ]
    }
"@

$Incidents = Get-SCEvent -EventTypes Incident -PastDays 2 -SCSession $O365ServiceSession | ? {$_.Status -eq "Service degradation"} | Sort StartTme -Descending | Select-Object Id, Status, StartTime, @{n='ServiceName'; e={$_.AffectedServiceHealthStatus.servicename}},
    @{n='Message';e={$_.messages[0].messagetext}}
ForEach ($Incident in $Incidents) {
   $IncidentID = $Incident.Id
   $IncidentStartTime = Get-Date ($Incident.StartTime) -format g
   $IncidentServiceName = $Incident.ServiceName
#   $IncidentMessage = out-string -InputObject $incident.message -Width 80
   $IncidentMessage = $Incident.Message
   $NotificationBody = $Notification.Replace("ID","$IncidentId").Replace("DATETIME","$IncidentStartTime").Replace("SERVICENAME","$IncidentServiceName").Replace("MESSAGE","$IncidentMessage")
   $Command = (Invoke-RestMethod -uri $TargetChannel -Method Post -body $NotificationBody -ContentType 'application/json')
}

Here’s what the cards look like after they are posted to the target channel.

How cards created using the webhook show up in a Teams channel using the Teams webhook connector
Cards for Office 365 service incidents posted in a team channel

The template method is probably better than the one we previously used, so we’re going to update Chapter 14 to include it. As I’ve often said, one of the joys of working on an eBook is that we can integrate new material and republish as often as we want – or in the case of Office 365 for IT Pros, monthly. And like the suggestion that lead to this update, we welcome comments and hints to improve our material.

PSTeams Module

If you’re interested in exploring the possibilities that exist in posting messages to Teams via the inbound webhook connection, you might consider the PSTeams module in GitHub, which is designed to help programmers build and send cards to Teams channels.


Read Chapter 14 in Office 365 for IT Pros for more information about using PowerShell to manage Office 365 Groups and Teams.

]]>
https://office365itpros.com/2019/01/14/inbound-webhook-connector/feed/ 8 1382
Sending Protected Email to Teams, Yammer, Groups, and Shared Mailboxes https://office365itpros.com/2018/12/19/protected-email-teams-yammer-groups/?utm_source=rss&utm_medium=rss&utm_campaign=protected-email-teams-yammer-groups https://office365itpros.com/2018/12/19/protected-email-teams-yammer-groups/#respond Wed, 19 Dec 2018 11:48:07 +0000 https://office365itpros.com/?p=1234

Encrypted or protected email is becoming more common inside Office 365 with the advent of the Encrypt-Only feature available in Outlook 2016 (Click to Run) and OWA.

You can include a mixture of internal and external recipients, including those who do not use Office 365, in the recipient list for a protected message and, subject to scoping defined for the template used to protect the message, will be able to open and access the content. You can also send protected messages to other Office 365 destinations, but as explained below, some restrictions apply.

Office 365 Groups

Protected messages (and attachments) sent to an Office 365 group can be read by any member of the group, including guest users, because they authenticate their access through membership of the group. 

Protected messages in an Office 365 group

Scoped Templates will Stop Access

The exception is when the template used to protect a message is scoped to assign permissions to specific recipients and a member of the Office 365 group is not included. In this case, the group member sees a conversation and who contributed to the conversation, but can’t see the content of the message (see below). if they click the banner telling them that a message can’t be displayed, they see the link to the Office 365 Message Encryption portal. However, this link won’t give them access because their account is not in the permissions list for the message.

Protected messages in an Office 365 group inaccessible to a group member

Shared Mailboxes

Protected messages sent to a shared mailbox can be opened and read by those with access to the shared mailbox if they use OWA. However, the same people can’t read the messages if they use Outlook. The difference in behavior is explained by the way that OWA fetches use licenses. Microsoft has admitted that they need to make both clients work the same way.

Teams Channels

Protected messages sent to the email address of a Teams channel (for example, 95c133a3.office365itpros.com@emea.teams.ms) are rejected by Exchange Online because the transport service cannot re-encrypt the message for delivery to the phantom mailbox used to route messages to Teams. As shown below, the sender receives a 5.7.1.Delivery Service Notification (DSN). Exchange Online decrypts protected messages as they pass through the transport service to allow transport rules to process the content.

DSN 5.7.1 when sending to a Teams channel

Yammer Groups

The same happens if you try to post a protected message to a Yammer group (with an address like office365QA+office365itpros@yammer.com). Again, Exchange Online can’t re-encrypt the message to deliver it to Yammer, so it issues a 5.7.1. DSN.


Learn all about rights management, templates, and email protection in Chapter 24 of the Office 365 for IT Pros eBook.

]]>
https://office365itpros.com/2018/12/19/protected-email-teams-yammer-groups/feed/ 0 1234
How to Include a Teams Channel in an Exchange Distribution List https://office365itpros.com/2018/12/03/teams-channel-email-address-dl/?utm_source=rss&utm_medium=rss&utm_campaign=teams-channel-email-address-dl https://office365itpros.com/2018/12/03/teams-channel-email-address-dl/#comments Mon, 03 Dec 2018 11:36:58 +0000 https://office365itpros.com/?p=1128

Include a Teams Channel Email Address in a DL to Make it Easier for Users to Email

Updated: January 2022

Following yesterday’s post about the email addresses used by Microsoft 365 Groups and Teams, including Teams channel email addresses, the following question was asked:

I have an existing email address from my distribution list.
I am using this address for a Microsoft flow “send an email to a SharePoint list”.
The emails send to this email address I also want to place in a teams channel.
1. Can I use my existing email address as an alias from a team channel or
2. can I forward my email sent to the existing email address to a teams channel?

In other words, we have an existing distribution list that we want to add a Teams channel email address as a member so that anything sent to the list is copied to the channel, including the capture of the messages and attachments in SharePoint.

Simple Solution – an Exchange Mail Contact

The simple solution is to create a new mail contact in Exchange Online using the email address for the channel. Go to the Recipients section of the (new or old) Exchange Admin Center (EAC), then Contacts, and add a new Mail Contact with the email address of the channel entered in the external email address property (Figure 1).

Creating a new Mail Contact in the EAC

Teams channel email address
Figure 1: Creating a new Mail Contact in the EAC

If you plan to allow people to email the distribution list from outside your organization, make sure to configure the distribution list to allow it to accept messages from unauthenticated senders. You can do this by editing the distribution list properties through the EAC, or by running the Set-DistributionGroup cmdlet to set the list’s RequireSenderAuthenticationEnabled property to $False:

Set-DistributionGroup -Identity "Teams DL" -RequireSenderAuthenticationEnabled $False

Exchange Online fully supports the addition of mail contacts in its distribution lists, so it’s an easy step afterwards to update the distribution list with the new contact. You can do this through the EAC or with PowerShell. For example, here’s how to add the contact created above to a DL.

Add-DistributionGroupMember -Identity "My DL" -Member "Teams911"

Any message now sent to the distribution list will be copied to the Team channel. If you don’t want the mail contact to show up in the GAL and OAB, set it to be hidden.

Set-MailContact -Identity Teams911 -HiddenFromAddressListsEnabled $True

More Complicated with Guest Accounts

You can also create a Azure Active Directory guest account for a teams channel email address and when you have the account set up, you can add that account to a distribution list. Exchange Online treats guests as mail users, which are a valid recipient type for email and supported as distribution lists members.

However, Exchange won’t deliver copies of messages sent to the distribution group to a guest member. The reason is that guest accounts don’t appear in Exchange address lists, so Exchange can’t check the validity of the recipient. Messages sent to the distribution list are delivered to all other members, but the guest account is a black hole.

The workaround is to add the guest to a Microsoft 365 group. Guest accounts are automatically added to the subscribers list of a Microsoft 365 group because email is the way they participate in conversations. If you then add the Microsoft 365 group to a distribution list, routing works as expected because when Exchange checks the recipients, it validates the Microsoft 365 group and not the individual members. Messages sent to a distribution group that include a Microsoft 365 group with a guest member pointing to a team channel work, but it’s a complicated approach when compared to the simplicity of using a mail contact.


For more information about distribution lists and mail contacts, go to Chapter 7 of the Office 365 for IT Pros eBook. And when you’ve read all that material, go on to Chapter 11 to learn about Microsoft 365 Groups and Chapter 13 to learn about Teams.

]]>
https://office365itpros.com/2018/12/03/teams-channel-email-address-dl/feed/ 11 1128
How to Populate Team or Group Membership from Email Distribution Lists https://office365itpros.com/2018/11/26/populating-group-from-dl/?utm_source=rss&utm_medium=rss&utm_campaign=populating-group-from-dl https://office365itpros.com/2018/11/26/populating-group-from-dl/#respond Mon, 26 Nov 2018 11:59:14 +0000 https://office365itpros.com/?p=1068

A question on the Microsoft Technical Community asked whether it’s possible to add the members from a mail group to a team. Taking “mail group” to mean “distribution list,” the answer is “of course with PowerShell.”

The big gotcha to remember is that distribution lists allow any mail-enabled recipient to be a member while Office 365 Groups and Teams only support mailboxes. Any code must therefore exclude objects like shared mailboxes, public folders, and mail contacts.

Read DL, Write Group

With that in mind, here’s some code to read the membership from a distribution list and add the mailboxes found in the list to an Office 365 group. As Teams and Groups share the same membership, the new members show up in Teams too. As written, the code uses cmdlets in the Exchange Online PowerShell module.

$i = 0
$Members = (Get-DistributionGroupMember -Identity "Company Sales")
$TeamId = (Get-UnifiedGroup -Identity "Sales Team").ExternalDirectoryObjectId
Write-Host "Processing Members"
ForEach ($M in $Members) {
  # Is this a mailbox
  If ($M.RecipientTypeDetails -eq "UserMailbox") {
    Write-Host "Adding" $M.DisplayName "to Sales Team"
    Add-UnifiedGroupLinks -Identity $TeamId -LinkType Member -Links $M.Alias
    # $UPN = (Get-Mailbox -Identity $M.Alias).UserPrincipalName
    # Add-TeamUser -GroupId $TeamId -User $UPN -Role Member
    $i++ }
}

Using the Teams PowerShell cmdlets

The two commented-out lines perform the update using the Add-TeamUser cmdlet, which is equally valid. However, remember to:

  • Load the Teams PowerShell module.
  • Pass the User Principal Name for the new team member (that’s why the call to Get-Mailbox is present).
  • Only team owners can update team membership. This restriction is likely to be removed soon, but it exists now.

Dynamic Groups

The note in the Microsoft Technical Community said that people spend a lot of time updating the distribution group membership. One response recommended dynamic groups, which is a perfectly valid option. The only downside is that you still need to maintain the directory so that the queries used for the dynamic groups return the right data. And you need Azure AD Premium P1 licenses for every account that comes within the scope of a query used for a dynamic group. If you have EM&S licenses, you don’t need to worry about Azure AD Premium as these licenses are included in that bundle.


Read more about using PowerShell with Office 365 Groups (and Teams) in Chapter 14 of the Office 365 for IT Pros eBook. Distribution lists are covered in Chapter 7.

]]>
https://office365itpros.com/2018/11/26/populating-group-from-dl/feed/ 0 1068
How to Add Admins to Every Microsoft 365 Group https://office365itpros.com/2018/11/24/admins-every-office-365-group/?utm_source=rss&utm_medium=rss&utm_campaign=admins-every-office-365-group https://office365itpros.com/2018/11/24/admins-every-office-365-group/#comments Sat, 24 Nov 2018 13:51:15 +0000 https://office365itpros.com/?p=1058

PowerShell to the Rescue

A question was asked about how to add an administrator account to every Microsoft 365 Group in an Office 365 tenant to allow the administrator access to the content in all groups.

This is a straightforward operation with PowerShell. This code finds all the groups in a tenant and adds a nominated administrator account to the membership of each group as a member. Change the LinkType  value to be “Owner” if you want the administrator to be a group owner. We also update the CustomAttribute14 property with a value that we can use later.

$AdminAccount = "Administrator@office365itpros.com"
Write-Host "Finding Groups..."
$Groups = (Get-Recipient -RecipientTypeDetails GroupMailbox -ResultSize Unlimited | Select DisplayName, Alias)
Write-Host "Processing" $Groups.Count "groups"
ForEach ($G in $Groups) {
    Write-Host "Processing" $G.DisplayName
    Add-UnifiedGroupLinks -Identity $G.Alias -LinkType Member -Links $AdminAccount 
    Set-UnifiedGroup -Identity $G.Alias -CustomAttribute14 "Admin"}

The code uses the Get-Recipient cmdlet instead of the Get-UnifiedGroup cmdlet to fetch a list of Microsoft 365 Groups. The reason why is that Get-Recipient is much faster at returning a simple set of group objects than Get-UnifiedGroup is because Exchange Online has less processing to perform. All we need is the group alias and displayname, so there’s no need to incur the overhead of Get-UnifiedGroup.

Handling New Groups

The code above is a one-time operation to process all the existing groups in the tenant. Of course, new groups will be created afterwards, and if we want the admin account to be The reason why we update CustomAttribute14 is to be able to find groups that are already processed because we don’t want to process them again. In fact, it wouldn’t make much difference if we ran the same code time after time because the Add-UnifiedGroupLinks cmdlet will complete and tell you that no settings of the group are changed if you try to add a member who already exists.

Applying a Filter

The code needed to find groups that are not yet processed adds a filter to exclude those where CustomAttribute14 is set to the value:

Get-Recipient -RecipientTypeDetails GroupMailbox -Filter {CustomAttribute14 -ne "Admin"} -ResultSize Unlimited

Replace the line in the original script with the line with the filter and you can find and update new groups.

One Script Does The Job

In fact, you could use the same script with the filter to do the job from the start as the first time it’s run, the filter will find all the groups in the tenant.

$AdminAccount = "Administrator@Office365itpros.com"
Write-Host "Finding Groups..."
$Groups = (Get-Recipient -RecipientTypeDetails GroupMailbox -Filter {CustomAttribute14 -ne "Admin" -ResultSize Unlimited | Select DisplayName, Alias)
Write-Host "Processing" $Groups.Count "groups"
ForEach ($G in $Groups) {
   Write-Host "Processing" $G.DisplayName
   Add-UnifiedGroupLinks -Identity $G.Alias -LinkType Member -Links $AdminAccount -ErrorAction SilentlyContinue
   Set-UnifiedGroup -Identity $G.Alias -CustomAttribute14 "Admin"}

You’d need to set up a schedule to look for and update groups if you really want to make sure that administrators have access to all groups in the tenant, but that’s easily done.

Isn’t PowerShell wonderful?


For more information about using PowerShell to manage Office 365 Groups, read Chapters 13 and 14 of the Office 365 for IT Pros eBook.

]]>
https://office365itpros.com/2018/11/24/admins-every-office-365-group/feed/ 2 1058
Tip: Make Sure to Add Owners as Members When Creating New Teams https://office365itpros.com/2018/11/23/creating-teams-powershell/?utm_source=rss&utm_medium=rss&utm_campaign=creating-teams-powershell https://office365itpros.com/2018/11/23/creating-teams-powershell/#comments Fri, 23 Nov 2018 13:04:45 +0000 https://office365itpros.com/?p=1047

Creating New Teams is Easy

New teams can be created in a variety of ways – through a Teams client, via PowerShell, or by using the Graph API.

If you create a team via a client, the person creating the team is automatically added as the owner. Their account is also added to the membership of the underlying Azure Active Directory (and Office 365) group. Teams masks this fact by only ever displaying the owner entry if you check using a client or PowerShell.

For instance, here’s a small team with 1 owner and 3 members as viewed through the Teams client:

RWC19
Teams lists the membership of a team

Examining Team Membership

If we look at the membership of the team via PowerShell, we see the following:

Get-TeamUser -GroupId eba86b74-aef7-4a6b-aa8a-b9769e97716e -Role member

UserId User Name Role
------ ---- ---- ----
d36b323a-32c3-4ca5-a4a5-2f7b4fbef31c Kim.Akers@office365itpros.com Kim Akers member
a3eeaea5-409f-4b89-b039-1bb68276e97d Ben.Owens@office365itpros.com Ben Owens (Business Director) member
c6133be4-71d4-47c4-b109-e37c0c93f8d3 Oisin.Johnston@office365itpros.com Oisin Johnston member

Get-TeamUser -GroupId eba86b74-aef7-4a6b-aa8a-b9769e97716e -Role owner

UserId User Name Role
------ ---- ---- ----
eff4cd58-1bb8-4899-94de-795f656b4a18 Tony.Redmond@office365itpros.com Tony Redmond owner

But if we examine the membership via Azure Active Directory, we see:

Get-AzureADGroupMember -ObjectId eba86b74-aef7-4a6b-aa8a-b9769e97716e

ObjectId                             DisplayName                   UserPrincipalName                  UserType
--------                             -----------                   -----------------                  --------
eff4cd58-1bb8-4899-94de-795f656b4a18 Tony Redmond                  Tony.Redmond@office365itpros.com   Member
d36b323a-32c3-4ca5-a4a5-2f7b4fbef31c Kim Akers                     Kim.Akers@office365itpros.com      Member
a3eeaea5-409f-4b89-b039-1bb68276e97d Ben Owens (Business Director) Ben.Owens@office365itpros.com      Member
c6133be4-71d4-47c4-b109-e37c0c93f8d3 Oisin Johnston                Oisin.Johnston@office365itpros.com Member

And the same information is reported for the Office 365 Group:

Get-UnifiedGroupLinks -LinkType Member -id eba86b74-aef7-4a6b-aa8a-b9769e97716e

Name           RecipientType
----           -------------
TRedmond       UserMailbox
Kim Akers      UserMailbox
Ben Owens      UserMailbox
Oisin.Johnston UserMailbox

Planner Likes Members

Why is this important? Well, it’s not if you only ever create new teams via a client. It becomes important if you create new teams via PowerShell or the Graph, because it means that you should always add new owners as members first, and then add them as an owner. If you don’t, applications that check for membership of the underlying group will fail. Planner is one application that I know that won’t allow a team owner access unless they are also a member, but that doesn’t mean that there aren’t others that will also fail, now or in the future.

Creating a New Team with PowerShell

The right way to create a new team with PowerShell is to create the team with the New-Team cmdlet and specify the name of the team owner in the call (this also adds that person as a member). Afterwards, add other owners and members of the team with the Add-TeamUser cmdlet, making sure to add the owners first as a team member and then as an owner.

In this example, we create a new team and then add one owner and one member. The $TeamId variable stores the GUID for the new team, which makes it easy to call Add-TeamUser. As you can see, Donald Vickers is added both as an owner and as a member.

$TeamId = (New-Team -DisplayName "Planning Team" -Alias PlanningTeam -Description "Team for the folks who like to plan" -AccessType Private -Classification Confidential -Owner Brian.Weakliam@office365itpros.com)

Add-TeamUser -GroupId $TeamId.GroupId -User Donald.Vickers@Office365itpros.com -Role Member
Add-TeamUser -GroupId $TeamId.GroupId -User Donald.Vickers@Office365itpros.com -Role Owner

All good clean PowerShell fun…

Note: The current Teams PowerShell module is 0.9.6. You need to use this version to see things work as described in this article.


We cover using PowerShell to work with Teams and Office 365 Groups in Chapter 14 of the Office 365 for IT Pros eBook. We like Teams, so there’s lots to discuss.

]]>
https://office365itpros.com/2018/11/23/creating-teams-powershell/feed/ 16 1047
Teams Now Supports Dynamic Microsoft 365 Groups https://office365itpros.com/2018/11/13/dynamic-teams/?utm_source=rss&utm_medium=rss&utm_campaign=dynamic-teams https://office365itpros.com/2018/11/13/dynamic-teams/#comments Tue, 13 Nov 2018 12:32:05 +0000 https://office365foritpros.com/?p=963
Dynamic Teams

Work Done. Formal Support Announced

As noted in September, the support for dynamic Teams was not fully baked, even if the functionality worked. Well, Microsoft has completed the tweaking to make sure that dynamic Azure AD groups work as expected for Teams. The November post about new functionality in Teams says:

You can now create teams backed by Office 365 groups with a dynamic membership rule for which membership is managed dynamically based on user or device properties in Azure Active Directory. If a user or device satisfies a rule for a group, they are added as a member, and when they no longer satisfy the rule, they are removed.

This helps with scenarios like:

  • A hospital can create different teams for nurses and doctors that automatically reflect current staffing.
  • A university can create a team for all faculty within a college, including an adjunct faculty that changes frequently.”

The functionality to enable a dynamic group with a team is now supported in the latest version of the Teams desktop and browser client. Teams with dynamic membership signal owners with the warning banner shown above.

All of which is nice and the details of how to create and use dynamic groups with Teams are as reported previously. The kicker comes in the statement that “Dynamic membership rules in Azure Active Directory require an Azure AD Premium P1 license for each unique user that is a member of one or more dynamic groups.”

Extra Cost to Use

To put this another way, if you create a large team, say covering all the employees in a department or country, you must make sure that each one of those accounts has an Azure AD Premium P1 license. This isn’t an issue if you license Enterprise Mobility + Security (EMS) or one of the Microsoft 365 bundles as the license is included, or if you’ve bought the add-on for another of the Groups features that need the Azure AD Premium license, like imposing a naming convention for new groups.

However, if you don’t have the licenses already, being asked to shell out an extra $6/user/month might be a significant hurdle in overcome in making the decision whether to use dynamic groups.

Org-Wide Teams Don’t Use Dynamic Groups

Org-wide teams don’t use dynamic groups, so they don’t incur any need for extra licenses. However, these teams are currently limited to 10,000 members. If you need to create a larger team for org-wide communications up to the current 25,000 member limit for a team, you can use a dynamic group.


We cover using dynamic Teams in Chapter 13 of the Office 365 for IT Pros eBook. Other information is in Chapter 12, where we discuss the Azure AD policy for Groups and the features that need to be licensed.

]]>
https://office365itpros.com/2018/11/13/dynamic-teams/feed/ 2 963
How to Create a List of Teams for Processing in Power BI https://office365itpros.com/2018/11/11/exporting-teams-powerbi/?utm_source=rss&utm_medium=rss&utm_campaign=exporting-teams-powerbi https://office365itpros.com/2018/11/11/exporting-teams-powerbi/#respond Sun, 11 Nov 2018 16:13:40 +0000 https://office365foritpros.com/?p=954

No OOTB Method, but PowerShell Works

A recent question in the Microsoft Technical Community asked how to export information about the set of teams in a tenant to Power BI. There’s no OOTB method to do this, but it’s an easy task for PowerShell.  The only complicating factor is that you must use cmdlets from both the Teams and Exchange Online PowerShell modules to generate data that you might want to process with Power BI.

Conceptually, the process is straightforward:

  1. Get a list of Teams in the tenant.
  2. Process each team and extract the necessary data.
  3. Store the data.
  4. When all teams are processed, write the data to a CSV file.
  5. Import the CSV file into Power BI.

Writing the Script

Here’s the script that I used. There’s nothing very complicated here and it’s easy to change the set of properties I choose to export.

# Set up variables and get list of teams....
$Report = [System.Collections.Generic.List[Object]]::new()
$Teams = Get-Team
Write-Host "Reporting" $Teams.Count "teams"
ForEach ($T in $Teams) {
# Fetch information about the team - mostly by getting it from the Unified Group Object
   Write-Host "Processing" $T.DisplayName
   $G = (Get-UnifiedGroup -Identity $T.GroupId | Select GroupMemberCount, GroupExternalMemberCount, PrimarySmtpAddress, AccessType, Classification)
   $Owners = (Get-TeamUser -Role Owner -GroupId $T.GroupId | Select Name)
   $OwnerNames = $Null
   $First = $True
   ForEach ($O in $Owners) {
     If ($First -eq $True) {
       $OwnerNames = $O.Name
       $First = $False}
     Else {
      $OwnerNames = $OwnerNames + ", " + $O.Name }}
   $ReportLine = [PSCustomObject][Ordered]@{
       Team = $T.DisplayName
       Email = $G.PrimarySmtpAddress
       Members = $G.GroupMemberCount
       Guests = $G.GroupExternalMemberCount
       Owners = $OwnerNames
       Access = $G.AccessType
       Classification = $G.Classification }
    $Report.Add($ReportLine) }
$Report | Export-Csv -NoTypeInformation c:\temp\Teams.csv

When the CSV file is ready, you can import it into Power BI and create whatever visualization or report you want there.

TeamsPowerBI
Processing the CSV file in Power BI

We’ll leave it to Power BI experts to figure out what to do next…


This is exactly the kind of example of using PowerShell to fill in a gap in Office 365 or solve a real-life problem for a tenant administrator that we like having in the Office 365 for IT Pros eBook, which is why we have over 1,000 examples in the book. If you want to know how to use PowerShell with Teams, go to Chapter 14…

]]>
https://office365itpros.com/2018/11/11/exporting-teams-powerbi/feed/ 0 954
Existing Guest Accounts and the Azure B2B Collaboration Policy https://office365itpros.com/2018/10/29/guest-accounts-azure-b2b-collaboration-policy/?utm_source=rss&utm_medium=rss&utm_campaign=guest-accounts-azure-b2b-collaboration-policy https://office365itpros.com/2018/10/29/guest-accounts-azure-b2b-collaboration-policy/#respond Mon, 29 Oct 2018 13:18:02 +0000 https://office365foritpros.com/?p=874

What Takes Priority?

As you might know, the Azure B2B Collaboration policy for a tenant can hold a deny (block) or an allow list. The list is used to stop owners of Office 365 groups adding guest users from specific domains or to restrict them to adding guest users from specific domains. Tenants use these lists to make sure that group owners don’t add guests from competitors, consumer email domains, and other domains that deemed objectionable for one reason or another.

Steve Crowe sent me a note to say that he had run into a problem using the B2B collaboration policy with Teams. He had blocked some domains but group owners were still able to add users from those domains as guests.

As it turned out, the reason was that guest accounts for the users being added already existed in Azure Active Directory. Teams doesn’t apply restrictions on guest accounts that are already present in your directory because an assumption is made that an administrator added the guest account, so it’s OK and can be added to other groups.

Guests in Place

The offending guest account was added before the block list was enforced, so that’s why it exists in the directory and why Teams assumes it’s OK to add the account to other groups. Guest accounts are now added by multiple applications, including SharePoint, Planner, and Office 365 Groups, so it’s hard to know where the account might have originated. In this instance, the guest account was added when someone shared a document in a SharePoint library.

You can argue that respecting existing guest accounts is the right approach. Administrators can add guest accounts from any domain they choose through the Azure portal, and if they do, shouldn’t team owners be allowed include these guests in their teams? On the other hand, administrators might assume that when they impose a block, they want applications like Teams to respect that block.

The “gap” in the block proves that you should use the Azure B2B collaboration policy to control domains for guest users AND check the guest user membership of groups on a regular basis, just to be sure that unwanted guests don’t slip through.

Keep Your Secrets

And if you have very confidential teams, consider blocking guest user access for the underlying Office 365 Groups. That way you’ll know that your organization’s most confidential discussions will never be shared with guests.


All of this is explained in Chapters 13 and 14 of the Office 365 for IT Pros eBook. It’s the kind of practical straightforward advice we offer to readers…

]]>
https://office365itpros.com/2018/10/29/guest-accounts-azure-b2b-collaboration-policy/feed/ 0 874
Managing Guest Users in a Microsoft 365 Tenant https://office365itpros.com/2018/10/18/managing-office-365-guest-users/?utm_source=rss&utm_medium=rss&utm_campaign=managing-office-365-guest-users https://office365itpros.com/2018/10/18/managing-office-365-guest-users/#respond Thu, 18 Oct 2018 18:03:51 +0000 https://office365foritpros.com/?p=815

Proliferating Guests

Today’s Petri.com article covers the topic of how to manage guest users in Microsoft 365 tenants. Guest accounts are created by several Office 365 applications, notably Teams, SharePoint Online, and Office 365 Groups. If you leave the guest accounts alone, they accumulate in your Azure Active Directory. Some are used all the time but some gather dust after a one-time use.

The article outlines some basic techniques (including some PowerShell snippets) to review and manage guest user accounts. Given that Office 365 Groups are the cornerstone for membership management for these applications, a lot of the work that’s done is with the Groups cmdlets to find, report, and remove unwanted guests. In my small tenant, I have 82 guest accounts – and I know that only 45 or so are used on a weekly basis. I guess I have some clean-up to do.


The Office 365 for IT Pros eBook contains tons of examples for how to manage different aspects of guest user accounts from the invitation process to removing them from your tenant. Look in Chapters 12 and 13!

]]>
https://office365itpros.com/2018/10/18/managing-office-365-guest-users/feed/ 0 815
How Microsoft IT Manages Microsoft 365 Groups https://office365itpros.com/2018/10/01/how-microsoft-manages-office-365-groups/?utm_source=rss&utm_medium=rss&utm_campaign=how-microsoft-manages-office-365-groups https://office365itpros.com/2018/10/01/how-microsoft-manages-office-365-groups/#respond Mon, 01 Oct 2018 17:16:36 +0000 https://office365foritpros.com/?p=687
Figure 12-99

The Lessons of Experience

Those given the job of planning the deployment of a new technology usually like to know how other companies approach the same task. After all, no one likes to make the same mistake as other companies have, so it’s always good to find out about successful techniques for the deployment and management of technology.

At the Ignite 2018 conference, Microsoft IT described the way they manage Office 365 Groups (now Microsoft 365 Groups – here’s a recording of the session). Microsoft is different from most companies: they don’t have to worry about the cost of licensing advanced features (like those which need Azure Active Directory P1 licenses) and their user community is more technically-savvy than the norm. However, there’s still value in understanding their perspective towards groups.

First, Microsoft uses a dynamic group for all full-time employees (“blue badges”) and allows members of this group to create new groups. While allowing all full-time employees to create new groups (and teams) might lead to a lot of groups that don’t get much usage, Microsoft uses an aggressive 180-day expiration policy to age out groups that no one needs.

Microsoft doesn’t use a naming policy, possibly because they never used a naming policy for distribution lists. They have custom jobs to scan for groups with no owner (important when you have an aggressive expiration policy), to ensure that groups have at least two owners, and to make sure that groups that have certain classifications are disabled for guest membership. They also use Azure Active Directory group reviews to make sure that guest members only keep access to groups for as long as they need to.

Multi-Geo Too

Microsoft also uses the Office 365 multi-geo capabilities for SharePoint Online and Microsoft 365 Groups (in preview and expected to be generally available in Q1 2019) to provision the team sites according to users’ preferred data locations (the Office 365 datacenter region they are deployed in).

Documenting a management framework for Microsoft 365 Groups within an organization is a good idea because it brings clarity to the deployment and lays out how the groups policy and other associated policies (like the Azure B2B collaboration policy and expiration policy) fit into the framework.


For more information about how to use the Azure Active Directory policy for Groups to control Office 365 Groups (and Teams) and associated policies like the Azure B2B Collaboration policy or the Groups expiration policy, read Chapter 12 of the Office 365 for IT Pros eBook.  We have lots to say on this subject!

]]>
https://office365itpros.com/2018/10/01/how-microsoft-manages-office-365-groups/feed/ 0 687
How to Synchronize AAD Security Groups with Microsoft 365 Groups https://office365itpros.com/2018/09/16/synchronizing-security-groups-office-365-groups/?utm_source=rss&utm_medium=rss&utm_campaign=synchronizing-security-groups-office-365-groups https://office365itpros.com/2018/09/16/synchronizing-security-groups-office-365-groups/#comments Sun, 16 Sep 2018 11:30:25 +0000 https://office365foritpros.com/?p=503

Exploiting Security Groups

Dan Stephenson, one of the Teams program managers, posted an interesting script to synchronize the membership of an AAD security group with an Office 365 group (now called Microsoft 365 Groups). The idea is that you might have invested in security groups to control access to different resources and now want to extend that investment and use the same group membership for collaboration with Teams.

PowerShell is Flexible

One of the wonders of PowerShell is the way that you can come up with different answers to the same problem. Everyone has their own way to attack a problem and code a solution. Here’s the script we include in Chapter 14 of Office 365 for IT Pros, where we deal with the many joys of managing Office 365 Groups and Teams with PowerShell.

The script synchronizes the membership of a security group called eDiscovery Admins with an Microsoft 365 Group called eDiscovery Administrators. The security group is the master, meaning that its membership is what we want to see synchronized to the Office 365 Group. Any members found in the Microsoft 365 Group membership that are not in the security group are removed. You need to connect your PowerShell session to Azure AD and Exchange Online (use the Exchange Online Management module) to access the cmdlets used in the script.

Synchronizing Group Memberships

First, we fetch details of the two groups we want to synchronize.

$M365Group = (Get-UnifiedGroup -Identity "eDiscovery Administrators")
$SecurityGroup = (Get-AzureADGroup -SearchString "eDiscovery Admins").ObjectId
# Grab list of security group members
$SecurityGroupMembers = (Get-AzureADGroupMember -ObjectId $SecurityGroup -All $True | Select UserPrincipalName, UserType)

Now we update the membership of the Office 365 Group based on the members of the security group.

ForEach ($i in $SecurityGroupMembers) {
If ($i.UserType -eq "Member") {
        Add-UnifiedGroupLinks -Identity $M365Group.ExternalDirectoryObjectId -LinkType Member -Links $i.UserPrincipalName }
}

The next step is to check the membership of the two groups and remove any member found in the Microsoft 365 Group who doesn’t exist in the security group.

$GroupMembers = (Get-UnifiedGroupLinks -Identity $M365Group.ExternalDirectoryObjectId -LinkType Member)
ForEach ($i in $GroupMembers) {
 $Member = (Get-Mailbox -Identity $i.Name)
 If ($SecurityGroupMembers -Match $Member.UserPrincipalName)
      { Write-Host $Member.DisplayName "is in security group" }
    Else
      { Write-Host "Removing" $Member.DisplayName "from Office 365 group because they are not in the security group" -ForeGroundColor Red
      Remove-UnifiedGroupLinks -Identity $M365Group.ExternalDirectoryObjectId -Links $Member.Alias -LinkType Member -Confirm:$False}
}
Write-Host "Current Membership of" $M365Group.DisplayName
Get-UnifiedGroupLinks -Identity $M365Group.ExternalDirectoryObjectId -LinkType Member | Select DisplayName

The next step for the budding PowerShell maestro to improve matters is to deal with nested groups (an exercise for the reader), improve error handling, and  come up with a way to run the script every day or so to ensure that the two group memberships remain synchronized.


We have a complete chapter (13) on using PowerShell in the Office 365 for IT Pros eBook. Not that you experts need to read it, but it is nice to know that the chapter is there.

]]>
https://office365itpros.com/2018/09/16/synchronizing-security-groups-office-365-groups/feed/ 3 503
Office 365 Groups and the ProvisioningOption property https://office365itpros.com/2018/09/15/office-365-groups-provisioningoption-property/?utm_source=rss&utm_medium=rss&utm_campaign=office-365-groups-provisioningoption-property https://office365itpros.com/2018/09/15/office-365-groups-provisioningoption-property/#comments Sat, 15 Sep 2018 14:33:53 +0000 https://office365foritpros.com/?p=346

Office 365 Groups are Connected to Lots of Resources

Update: Better methods now exist to find the set of team-enabled groups in a tenant.

One of the impressive things about Office 365 Groups is how quickly Microsoft development groups turned to Groups to use their simple membership model instead of creating their own application-specific implementation. The premier list of Office 365 applications that use Groups include Stream, SharePoint Online, Power BI, Planner, Yammer, and Teams.

All of which is great, but administrators sometimes want to know what resources a group is connected to, such as whether a group is connected to a team or Planner. The sad fact is that there’s no good way to make a simple PowerShell query to return this information.

Some people advocate looking at the ProvisioningOption property returned by the Get-UnifiedGroup cmdlet. This will tell you if Yammer created a group because the value of the property is then set to “YammerProvisioning.”

[Update – January 9, 2019: Microsoft has updated the Get-UnifiedGroup cmdlet to remove the ProvisioningOption property.]

The Many Values Created by Exchange

However, when an Exchange client (including the New-UnifiedGroup PowerShell cmdlet) creates a new Office 365 Group, you end up with some explainable values in the property. Here’s a selection of what I find in my own tenant:

  • ExchangeProvisioningFlags:2028
  • ExchangeProvisioningFlags:2020
  • ExchangeProvisioningFlags:2529
  • ExchangeProvisioningFlags:3552
  • ExchangeProvisioningFlags:227
  • ExchangeProvisioningFlags:481

Worse, you might find that the property doesn’t have a value. I accept that this might be the case for older groups (those created in 2016 or before), but even newly-created groups sometimes have a blank value for ProvisioningOption.

The profusion of different values or the lack of a value makes it hard to depend on the ProvisioningOption for anything, including listing Office 365 Groups that are team-enabled, which is probably the most frequent request when it comes to figuring out what resources belong to a group.

Microsoft’s Warning

The Office 365 Groups marketing manager, Christophe Fiessinger, said in 2017 that “Using ExchangeProvisioningOption is NOT recommended since not all apps leverage it.” Not much has changed since and there’s no word from the engineering group that they might have done anything to improve the situation.

Use Get-Team to See Team-Enabled Groups

Since the original post was written, Microsoft has updated the PowerShell module for Teams. Running the latest version of the Get-Team cmdlet without any parameters returns the set of team-enabled groups in a tenant. This eliminates any need to jump through hoops to figure out a list of teams by checking the properties of groups, looking for team compliance records in the group mailbox, and so on.

Use the Graph Too

If you don’t want to limit yourself to PowerShell, the Microsoft Graph is the fastest method to fetch a set of Teams-enabled groups in a tenant. Here’s an example of using the Graph to fetch Teams. Remember that if you have more than 100 Teams in a tenant, you must use pagination to fetch the team information from the Graph. This post tells you how.


Lots has changed since the original post for this topic appeared in September 2018. Do yourself a favor and keep up to date with the latest in Office 365 by subscribing to the Office 365 for IT Pros eBook. All the information about using the Get-Team cmdlet is in Chapter 14.

]]>
https://office365itpros.com/2018/09/15/office-365-groups-provisioningoption-property/feed/ 9 346
Office 365 Audit Records Truncated for Azure Active Directory Events https://office365itpros.com/2018/09/12/office-365-audit-record-truncated/?utm_source=rss&utm_medium=rss&utm_campaign=office-365-audit-record-truncated https://office365itpros.com/2018/09/12/office-365-audit-record-truncated/#comments Wed, 12 Sep 2018 09:32:53 +0000 https://office365foritpros.com/?p=538

A Live Demo Fails

The shifting sands of cloud services caught me out on Monday when I spoke at the UK Evolve conference. My topic was how to use PowerShell to manage Office 365 Groups and Teams (aka “Hacking your way to Happiness” – you can download a PDF of the deck here). During the session, I use several demos to show people how easy PowerShell really is and how quickly it lets you get real work done. All went well and then I came to an example where I look for records in the Office 365 audit log for “add group” events.

EvolvePresentation
Presenting at Evolve – Before the code problem struck (photo: Matt Ellis via Twitter)

To make sure that demos run smoothly I use a cheat sheet of PowerShell code snippets in a Word document. Cutting and pasting known good code is faster and saves the embarrassment of getting code wrong in front of large audiences. I was therefore nonplussed to see an error from code that “used” to work perfectly well and is from an example in Chapter 21 of the Office 365 for IT Pros eBook.

Cannot index into a null array.
At line:1 char:7
+ $ReportLine = [PSCustomObject][Ordered]@{
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : NullArray

Add Group is Truncated

Looking at the code, I found that the problem happened after I used the Search-UnifiedAuditLog cmdlet to search for audit records for the “add group” event. The idea is that you can extract these audit records from the log and then analyze them to figure out who’s creating new Office 365 Groups and Teams. Audit records hold a lot of interesting information in the JSON content held in the AuditData field, so we need to unpack the content to extract information about the name of the newly created groups. The resulting $AuditData variable for an unpacked record contains the data shown below:

ObjectId       : Not Available
UserId         : Tony.Redmond@office365itpros.com
ClientIP       : 
Id             : a6ddc5dc-bfce-4d7c-b39b-775cba7b48ae
RecordType     : 8
CreationTime   : 2018-07-11T14:36:54
Operation      : Add group.
OrganizationId : b662313f-14fc-43a2-9a7a-d2e27f4f3478
UserType       : 0
UserKey        : 1003BFFD805C87B0@office365itpros.com
Workload       : AzureActiveDirectory
ResultStatus   : Success : Record Truncated
Version        : 1

Seeing “Record Truncated” in a status field doesn’t create a feeling of confidence that the audit records are complete. In fact, the data is missing two fields that used to be available called Actor and Target, the latter being the field that the group identifier and group name were available in. When my code tried to access the information in $AuditData with references to $AuditData.Target[0].Id and $AuditData.Target[1].Id, the null array error happened because that array was never populated by the JSON extract.

Something Changed

Something had clearly changed in the audit records generated for “add group” events since I used the same demo code at the European Collaboration Summit in late May.  I looked at all the audit events I could find for “add group” using the Audit log viewer in the Security and Compliance Center and found that every one of the events lack the data.

Office 365 only keeps audit log records for 90 days, so I could only go back to early July.  I found good records on July 5 and bad records after July 11. It therefore seems likely that the format of the audit records captured for Azure Active Directory events ingested into the Office 365 audit log changed sometime between July 5 and 11. I can’t be more definite than that.

Changing Audit Records is a Bad Thing

As it transpires, the problem of truncated information in Office 365 audit records exists for other Azure Active Directory group operations like add and remove user (see below) and group removal and updates. This is a real problem. Customers depend on this information to understand what happens with groups inside their tenant.

RecordTruncated
Office 365 audit record is truncated for remove member operation

Looking at the Azure audit log, the details of the group (name and identifier) are present, so it seems likely that the problem occurs when Office 365 extracts information from Azure Active Directory and normalizes the data before ingestion into the audit log.

Activity
Date : 9/9/2018, 4:45:32 PM
Name : Remove member from group
CorrelationId : 3669b365-5346-4fb7-aeb5-0260a1e64305
Source : AzureAD
Category : Core Directory
Activity Status
Status : Success
Reason :
Initiated By (Actor)
Type : User
Name : Microsoft Teams Services
ObjectId : eff4cd58-1bb8-4899-94de-795f656b4a18
Upn : Tony.Redmond@office365itpros.com
IpAddress :
Target(s)
Target
Type : User
ObjectId : bd8ad08e-c964-41e0-b5e9-456ab487a0c1
Upn : O365-ExchangeConnections2015@office365itpros.onmicrosoft.com
Modified Properties
Name : Group.ObjectID
New Value : "37991751-f6dd-48e5-bc86-1967181a7e53"
Name : Group.DisplayName
New Value : "All R &A Users"
Name : Group.WellKnownObjectName
Target
Type : Group
ObjectId : 37991751-f6dd-48e5-bc86-1967181a7e53
Additional Details

Not a Good Situation

I don’t know why Microsoft decided to change the format of the Azure Active Directory audit records as they were ingested into the Office 365 audit log. I do know that they messed up by removing essential data from the records. Where once it was possible to easily determine the name of a newly created group, now it is not. The same is true when trying to find out who was added or removed from groups, or accounts that are added or removed from the tenant. Losing this information is not good and it doesn’t give you confidence in the testing regime used to validate code changes.

I also don’t like when changes happen to data that might be used for compliance purposes without any warning or documentation. It doesn’t help people who roll their own analysis with PowerShell and it doesn’t help the ISVs who extract audit data on behalf of Office 365 tenants and store that data for longer than the 90-day default retention period.

All the Office 365 for IT Pros writing team can do is to keep checking to make sure that the code examples we include in the book continue to work over time. I’m happy that I found this problem and have been able to report it to Microsoft; it just wasn’t so good to run smack into the issue when doing a live demo.

]]>
https://office365itpros.com/2018/09/12/office-365-audit-record-truncated/feed/ 2 538
How Eradicating Bad Email Habits Improves Microsoft 365 Account Security https://office365itpros.com/2018/09/06/eradicating-bad-email-habits-office-365/?utm_source=rss&utm_medium=rss&utm_campaign=eradicating-bad-email-habits-office-365 https://office365itpros.com/2018/09/06/eradicating-bad-email-habits-office-365/#respond Thu, 06 Sep 2018 13:25:49 +0000 https://office365foritpros.com/?p=500

Stop Password Sharing Now

ZDNet report described a number of bad security habits in small to medium companies, among which was the headline statistic that 22% of business leaders share their email passwords with co-workers or assistants.

Much of the success of Office 365 is fueled by small to medium businesses, who find it much easier to use cloud services than to deploy their own Exchange and SharePoint servers (a point underlined by attacks on on-premises Exchange servers) . I hope that 22% of business leaders who use Office 365 don’t share their passwords. It’s old-school thinking that doesn’t reflect the reality of today. Sharing passwords is bad practice and it is utterly unnecessary.

Knowing someone’s account password gives you access to much more than their email. You can then log onto Teams and read the conversations in the private teams that person belongs to, or open protected SharePoint documents, or read whatever’s in their OneDrive for Business account, or take part as that person in Yammer conversations. As people move more data into cloud services, knowing personal passwords becomes the key to access all that data rather than just a mailbox.

The sad thing is that no need exists for anyone to ever share the password to their account. Mailbox delegation, shared mailboxes, Microsoft 365 Groups, and Teams all provide other ways for senior people to collaborate effectively and securely with their assistants.

No matter what size your company is, it’s time to stop the awful habit of password sharing now. Make sure that none of your users share passwords, and if you find that some do, be kind but firm and help them understand why what they are doing is so dreadfully wrong.

Better Sharing Options Exist

If people argue back and say that sharing passwords is the only way they can collaborate with their assistants, take the opportunity to prove that they are dead wrong. Clinging to techniques that worked in the 1980s is not a recipe for good IT security or successful collaboration. Point out that a variety of methods exist in Office 365 to allow better and more secure sharing:

  • Delegate access to folders in their mailbox, including the inbox and calendar, to allow assistants process email on their behalf. Delegation is very straightforward and doesn’t need the delegator to share passwords.
  • Have their email sent to a shared mailbox where it is processed by their team. Any important email can be sent to a separate private mailbox used by the executive for their most personal and sensitive communications. The private mailbox is hidden from the GAL and only available to certain senders. You can define a list of approved senders (use a distribution list for maximum flexibility) for the mailbox or use moderation to control what email gets through. Using a mix of shared/private mailboxes for executive communications is often used to protect executives in large corporations, but as shared mailboxes are free in Office 365, there’s no reason why the same technique can’t be used in smaller companies.
  • If they prefer, they could use an Microsoft 365 group instead of a shared mailbox. Microsoft 365 Groups are included in many Office 365 subscriptions and the email that arrives in the group can be responded to by assistants. The benefit of using a group is that it comes along with a SharePoint team site, so it’s easy to handle shared documents. The group can also be used with Planner. Again, the executive can have a private mailbox for their most sensitive and secure email.
  • If the executive wants to have a secure place to discuss matters with their assistants, they could also consider using a team instead of a group and take discussions out of email. The executive could send messages needing action to different channels in the team (like a “Priority” channel or channels named after projects, or a private channel shared only between the executive and their assistant). The downside of using Teams is that you cannot send email from a team (or on behalf of a user from a team), so outbound communication will still have to be processed by email.
  • Sensitivity labels with information protection can stop unauthorized access to confidential documents and email even if they are leaked or shared inappropriately.

Microsoft 365 Groups and Teams both support shared calendars, so supporting the executive’s calendar is not a problem. Outlook for iOS and Android support access to shared mailboxes and Microsoft 365 Groups, and Teams has its own mobile client, so there’s no problem getting to information when on the road.

Deploy MFA Now

Using basic authentication to connect to Exchange Online exposes mailboxes to attack, including business email compromise attacks. And accounts that are only protected by passwords, especially those shared with other people, are more likely to be pwned. Every account used by senior personnel and those used by administrators should be protected by MFA and you should check the MFA status of accounts periodically.

After you use MFA to protect an account, knowing passwords is not enough for others to access the account. They need to have access to the second authentication method, like a mobile phone. Although it’s conceivable that executives might give their mobile phone to their assistants to allow access to their email, implementing MFA in a tenant is an excellent way to begin eradicating password sharing.

Break Old Habits

Executives have different modes of working and the transition from email-based, password-sharing access to mailboxes will be difficult for some (and their assistants). It is sensible to sit down with the assistants to understand the ebb and flow of information and how the executive processes work to come up with the right solution for them. The good thing is that Office 365 offers different highly functional options. The challenge is to pick the right one for the person to help them break the horrible and dangerous habit of password sharing.


The Office 365 for IT Pros eBook goes into great detail about all these topics. Isn’t it worth your while having access to the best and most up-to-date information about Office 365?

]]>
https://office365itpros.com/2018/09/06/eradicating-bad-email-habits-office-365/feed/ 0 500
Using Dynamic Office 365 Groups with Teams https://office365itpros.com/2018/09/03/dynamic-office-365-groups-teams/?utm_source=rss&utm_medium=rss&utm_campaign=dynamic-office-365-groups-teams https://office365itpros.com/2018/09/03/dynamic-office-365-groups-teams/#comments Mon, 03 Sep 2018 19:17:46 +0000 https://office365foritpros.com/?p=348

Teams and Dynamic Office 365 Groups

Update: From November 2018, support for dynamic groups is included in Teams. See this article for more information.

Despite having some dynamic teams working in my tenant, some people told me that Microsoft doesn’t support dynamic Office 365 Groups when used with Teams. The documentation covering Office 365 Groups and Teams doesn’t address the point, so there doesn’t seem to be a formal restriction. At least, there wasn’t until I tried to team-enable a new dynamic Office 365 group and ran into an error.

I asked the Teams development group whether dynamic teams are supported. They admitted that some people had got dynamic teams to work (like me) but as they hadn’t completed the work to validate that dynamic teams work properly in all scenarios, they had placed a block on the creation of new dynamic teams. Microsoft will enable the feature when they complete their development and test work, and hopefully this will happen soon. We have updated Office 365 for IT Pros (August 28) to reflect the current situation.

A Dynamic Team

Every team is represented by an Office 365 Group. The membership of the group represents the membership of the team. The group can be made up of static or dynamic membership. A dynamic group uses a query against Azure Active Directory to calculate its membership. You cannot create a team with dynamic membership using a Teams client or with the PowerShell New-Team cmdlet. Instead, you create the dynamic group through the Azure Active Directory portal and then team-enable the group.

Figure 1 shows an example. The top is an extract of properties for a dynamic group taken from the Azure Active Directory portal. We can see that the membership type is dynamic and that the group has five members. The bottom is the membership visible in Teams. Five members are shown, which is what we expect.

Pictures of the Marketing department - a team that uses a dynamic group
Figure 1: The Marketing Department – a team using a dynamic group

All of this is based on experience with dynamic teams created before Microsoft initiated the block. Things could change in the future!

Owners and Members

Each team should have at least one owner. The person who creates a new team automatically becomes an owner, unless they decide not to and nominate another user for the role. You can add other owners via the Azure Active Directory portal, PowerShell, or by updating the role of a member to become an owner.

Owners are always members of the team, but they are static in that their membership does not depend on the query executed against Azure Active Directory. In other words, a dynamic group has two membership lists – one is static (the owners), and one is dynamic (the members). The dynamic list is actually composed of the owners and the members computed by the query against Azure Active Directory. You don’t see two sets in the dynamic list because the user interfaces combine the two into one seamless set.

But if you use the Get-TeamUser cmdlet to examine members of a team, you see:

Get-TeamUser -GroupId a53141d5-54ef-4a6d-877d-63b0cbda409f | ft user, role

User                                Role
----                                ----
Tony.Redmond@office365itpros.com    owner
dxredmond@office365itpros.com       owner
Administrator@redmondassociates.org owner
Sanjay.Patel@office365itpros.com    owner
Kim.Akers@office365itpros.com       member
James.Abrahams@office365itpros.com  member
James.Ryan@office365itpros.com      member

While if you run the Get-AzureADGroupOwner and Get-AzureADGroupOwner cmdlets to examine the underlying group in Azure Active Directory, you see the two sets:

Get-AzureADGroupMember -ObjectId a53141d5-54ef-4a6d-877d-63b0cbda409f

ObjectId                             DisplayName     UserPrincipalName                  UserType
--------                             -----------     -----------------                  --------
eff4cd58-1bb8-4899-94de-795f656b4a18 Tony Redmond    Tony.Redmond@office365itpros.com
96155a51-6885-4c8f-a8b6-e1614af08675 Deirdre Redmond dxredmond@office365itpros.com
d36b323a-32c3-4ca5-a4a5-2f7b4fbef31c Kim Akers       Kim.Akers@office365itpros.com
d446f6d7-5728-44f8-9eac-71adb354fc89 James Abrahams  James.Abrahams@office365itpros.com Member
cad05ccf-a359-4ac7-89e0-1e33bf37579e James Ryan      James.Ryan@office365itpros.com     Member

Get-AzureADGroupOwner -ObjectId a53141d5-54ef-4a6d-877d-63b0cbda409f

ObjectId                             DisplayName                            UserPrincipalName                   UserType
--------                             -----------                            -----------------                   --------
eff4cd58-1bb8-4899-94de-795f656b4a18 Tony Redmond                           Tony.Redmond@office365itpros.com
96155a51-6885-4c8f-a8b6-e1614af08675 Deirdre Redmond                        dxredmond@office365itpros.com
53f08764-07d4-418c-8403-a737a8fac7b3 Administrator (Redmond and Associates) Administrator@redmondassociates.org Member
ab5dc939-bb3e-4b68-bf26-8e401f0b6f00 Sanjay Patel                           Sanjay.Patel@office365itpros.com    Member

Some members are marked with UserType = Member while others are not. There’s a slight inconsistency in how users are tagged that I can’t quite explain. But everything works.

Problems

Although dynamic teams do work (if you configured them before Microsoft blocked the feature), it’s fair to say that some gotchas exist. One example of an edge case is when you demote an owner to become a member. If the demoted user does not come within the scope of the query used to populate the team membership, they are removed from the membership.

Another problem is that no documentation exists, work that would flow from testing.

Some attention might be needed to improve the synchronization between Azure Active Directory and Teams to respect changes made in dynamic membership. Anyone who has made a change to Azure Active Directory knows that Teams is sometimes not fast when it comes to synchronization, which could be a problem when dynamic membership changes. When an administrator updates the query underlying a dynamic group, background jobs evaluate the query and compute the new membership. Any changes must then be synchronized from Azure Active Directory to Teams, and then replicated to the local cache in clients.

I’m sure that Microsoft knows of all these issues and is working to resolve them before the formal launch of dynamic teams.

Update: Teams now fully supports dynamic Microsoft 365 Groups.

For More Information

For more information about Dynamic Office 365 Groups, see Chapter 12 of Office 365 for IT Pros. For more information about Teams, see Chapter 13.

 

]]>
https://office365itpros.com/2018/09/03/dynamic-office-365-groups-teams/feed/ 4 348
Office 365 Groups management capabilities coming to the SharePoint Online admin center https://office365itpros.com/2018/08/31/office-365-groups-management-sharepoint-online-admin/?utm_source=rss&utm_medium=rss&utm_campaign=office-365-groups-management-sharepoint-online-admin https://office365itpros.com/2018/08/31/office-365-groups-management-sharepoint-online-admin/#respond Fri, 31 Aug 2018 06:35:20 +0000 https://office365foritpros.com/?p=424

Finally, Office 365 administrators will  have the ability to manage Office 365 Groups from the SharePoint Online Admin Center. The news came in a recent message (MC147409) published in the Microsoft 365 Messages Center:

We’re updating Office 365 Group management capabilities in the SharePoint Online admin center. We’ll begin rolling this feature out soon. In the current SharePoint Online admin center experience, the following Microsoft 365 admin roles can manage Office 365 Groups: global administrator, user administrator, and Exchange administrator. In response to customer feedback, we will provide SharePoint Online administrator permissions to manage Office 365 Groups in the new SharePoint Online admin center.

This new capability to manage Office 365 Groups directly in the SharePoint Online Admin Center is associated with Office 365 Roadmap ID: 32864.

Implications of the change
The implications of this change is that SharePoint Online Admins will also be able to perform Office 365 Groups management tasks from the Admin Center: create, delete, restore and change Owners of a group. Given the importance of Office 365 Groups to SharePoint Online, it’s a good change.

Microsoft is expecting to roll out this change in early September and it should be completed worldwide by the end of January

]]>
https://office365itpros.com/2018/08/31/office-365-groups-management-sharepoint-online-admin/feed/ 0 424
Microsoft to Support Google IDs for Azure B2B Collaboration https://office365itpros.com/2018/08/29/google-accounts-supported-azure-b2b/?utm_source=rss&utm_medium=rss&utm_campaign=google-accounts-supported-azure-b2b https://office365itpros.com/2018/08/29/google-accounts-supported-azure-b2b/#respond Wed, 29 Aug 2018 14:33:58 +0000 https://office365foritpros.com/?p=380

AzureADSplash

No Azure AD Account Necessary

Today, if you invite someone with a Google account to join an application that supports Azure B2B Collaboration (like Teams, Office 365 Groups, or Planner), that person ends up with a guest user account in your tenant’s Azure Active Directory.

In the future, that guest account won’t be needed because Microsoft is enabling federation for Google accounts. The feature is now in preview and works for accounts with a Gmail.com address. What it means is that Azure AD will recognize the credentials belonging to Gmail.com accounts when their owners try to access applications in your tenant.

Apps Might Still Need Guest User Accounts

It’s early days yet and the documentation is naturally sparse because it focuses on getting federation going with Google and doesn’t get into the details of how this might apply to applications like Teams and Office 365 Groups. My guess is that guest user accounts might still be needed for applications that depend on memberships, but we shall see in time.

For more information on Office 365 Groups, see Chapter 11 in Office 365 for IT Pros. Azure B2B Collaboration and how invitations result in guest user accounts is covered in Chapter 12, while Teams is in Chapter 13 and Planner in Chapter 15.

]]>
https://office365itpros.com/2018/08/29/google-accounts-supported-azure-b2b/feed/ 0 380
Adding a New Microsoft 365 Group to an Existing (Classic) SharePoint Online Site https://office365itpros.com/2018/08/28/adding-a-new-office-365-group-to-an-existing-classic-sharepoint-online-site/?utm_source=rss&utm_medium=rss&utm_campaign=adding-a-new-office-365-group-to-an-existing-classic-sharepoint-online-site https://office365itpros.com/2018/08/28/adding-a-new-office-365-group-to-an-existing-classic-sharepoint-online-site/#respond Tue, 28 Aug 2018 06:51:27 +0000 https://office365foritpros.com/?p=353 Read More "Adding a New Microsoft 365 Group to an Existing (Classic) SharePoint Online Site"

]]>

As announced in this post in the Microsoft Tech Community, the ability to add a new Office 365 Group to an existing SharePoint Online (SPO) site is finally available to Office 365. You will be able to connect existing classic SPO sites to new Office 365 Groups by means of two possible mechanisms:

  • PowerShell (first mechanism available after the official announcement of this feature)
  • The “Connect to new Office 365 Group” option available in the site settings menu

This article was published on Petri.com on July 20, 2018. For more information about SharePoint Online and OneDrive for Business, see Chapter 8 in Office 365 for IT Pros

]]>
https://office365itpros.com/2018/08/28/adding-a-new-office-365-group-to-an-existing-classic-sharepoint-online-site/feed/ 0 353
How to Control the Access of Guest Users to Confidential Information in Microsoft 365 Groups and Teams https://office365itpros.com/2018/08/16/guest-member-access-data/?utm_source=rss&utm_medium=rss&utm_campaign=guest-member-access-data https://office365itpros.com/2018/08/16/guest-member-access-data/#respond Thu, 16 Aug 2018 14:23:35 +0000 https://office365foritpros.com/?p=229
Guest member or external member access to information

Keeping Confidential Information Secret

Many SharePoint Online sites belonging to Microsoft 365 Groups and Teams hold confidential information that you might not want to share with guest members. When Microsoft first supported guest users for Office 365 Groups (now Microsoft 365 Groups) through Azure B2B Collaboration, the focus was on allowing guests to collaborate with tenant users through email and shared documents. Over time, apps like Teams and Planner included support for Azure B2B Collaboration and increased the amount of data available to guests. The issue often encountered now is how to keep organizational secrets when using collaborative applications.

Controlling Guest Access

In the early days of Office 365 Groups, there wasn’t much that group members could do to protect confidential information from guests. The Groups membership model is very simple. All members enjoy equal access to group content. This led to the creation of many additional groups to segregate information which needed to stay internal with that which could be shared externally.

As time went by, Microsoft introduced functionality to help. A range of options now exist:

  • Groups and Teams blocked against guest access. By restricting membership to tenant users, you create conditions for unfettered internal discussions and sharing. The block is imposed by updating the properties of the group in Azure AD to prevent group owners adding guest members. An administrator can update the group properties manually or the group can inherit the block when a group owner or administrator assigns a sensitivity label with the appropriate restriction to the group.
  • Inside a group with guest members, sensitivity labels with encryption can stop specific members (guests and perhaps some internal users) accessing sensitive documents in the group’s document library. Access rights defined in the label control who can interact with documents, and if guests aren’t assigned rights in a label, they cannot open any document assigned that label. This method is an effective block, but it does go against the general philosophy that members share equal access to group resources. Remember that document metadata is not encrypted by sensitivity labels, so guests will be able to see document titles and authors.
  • Private channels avoid the need to create a new group by establishing barriers to sharing within teams. Private channels are restricted to a subset of team members, such as only tenant users. Anything shared in a private channel is only available to the members of the channel, including documents stored in the SharePoint Online team site for the channel.
  • Shared channels don’t use Azure B2B collaboration, so don’t use guest members to control external access. Instead, tenants agree to federate using Azure AD cross-tenant access settings to allow users to work together in shared channels, including access to the SharePoint Online team sites used by the channels (just like private channels, each shared channel has its own site). Sensitivity labels placed on confidential documents can limit access to tenant members of shared channels.

With these options in mind, the best approach might be to stop external users getting into sensitive groups in the first place. As noted above, this is possible by blocking the ability of owners to add guests to their groups and teams at a group level or (for shared channels) with cross-tenant access settings. Administrators can always add guest members to teams and groups if necessary.

Controlling Group Policy Settings

The Azure Active Directory policy for Groups holds settings for how Microsoft 365 Groups behave in a tenant. One of those settings is AllowToAddGuests, which is True if the tenant allows guests to be members of groups, and False if you want to block guests. This policy covers all groups and is managed through PowerShell. If the tenant policy allows guests users, the properties of individual groups can be amended to block access to those groups.

Use Sensitivity Labels

Today, sensitivity labels are the best method to controlling external access to confidential information. A sensitivity label can hold several container management settings, including guest access and the external sharing capability for SharePoint. Applying the label to a group forces the inheritance of the container settings, and if the settings dictate a block for guest access, the group’s AllowAddGuests property is set to #False. Sensitivity labels are available in the Office 365 E3 and E5 plans.

Using Classifications to Block Guest Access

If you choose not to use sensitivity labels, you can use group classifications to mark confidential groups and update the properties of those groups to block guest access. A classification is a text value defined in the ClassificationList setting of the Groups policy. Classifications are visual markers intended to convey to users what kind of information a group holds. They do not affect how a group or team works, nor does a classification protect content or place any restriction on how that content is used. Adding or updating a new classification or removing a classification from the list does not affect classifications placed on existing groups.

Let’s assume that you define a “Secret” classification to mark confidential groups (or teams). After classifying the secret groups (using PowerShell or client UIs), we can use PowerShell to scan for and block guest access for those groups.

The first step in the example code creates a set of groups classified as “Secret.” The code then loops through each group to discover whether group-specific policy settings are in place. If so, the code updates the settings to block guest access. Groups that don’t have a policy setting are controlled by the tenant policy, so the first step is to create policy settings for the group. We can then update the setting to block guest access.

$GroupTemplate = (Get-AzureADDirectorySettingTemplate | ? {$_.DisplayName -eq "Group.Unified.Guest"})
$Groups = (Get-UnifiedGroup -ResultSize Unlimited | Where {$_.Classification -eq "Secret"})
 
ForEach ($Group in $Groups) {
    $GroupSettings = Get-AzureADObjectSetting -TargetType Groups -TargetObjectId $Group.ExternalDirectoryObjectId 
    if($GroupSettings) {
       # Policy settings already exist for the group - so update them
       $GroupSettings["AllowToAddGuests"] = $False
       Set-AzureADObjectSetting -Id $GroupSettings.Id -DirectorySetting $GroupSettings -TargetObjectId $Group.ExternalDirectoryObjectId -TargetType Groups
       Write-Host "External Guest accounts prohibited for" $Group.DisplayName 
    }
    Else
    {
       # Settings do not exist for the group - so create a new settings object and update
       $Settings = $GroupTemplate.CreateDirectorySetting()
       $Settings["AllowToAddGuests"] = $False
       New-AzureADObjectSetting -DirectorySetting $Settings -TargetObjectId $Group.ExternalDirectoryObjectId -TargetType Groups
       Write-Host "External Guest accounts blocked for"$Group.DisplayName 
    }
}

To check that the block for guest access is in place, we can create a list of the groups blocked from having guest members. To do this, run the Get-UnifiedGroup cmdlet to check the AllowAddGuests property, which is $False if the group is blocked. For example, this command reports the display names and classification for all blocked groups. Remember that the block works for all clients that populate group membership, including Teams.

Get-UnifiedGroup -ResultSize Unlimited | ? {$_.AllowAddGuests -eq $False } | Format-Table DisplayName, Classification

It’s critical to realize that applying a block on guests to a group does nothing to remove existing guests. If you want to eject existing guests, you need to do that separately.

Multiple Secret-Keeping Techniques

Multiple approaches are available to block guests from accessing content shared in Teams and Groups. The most fundamental is to block guest access completely, but if guests are already present, consider using Private channels in Teams or limit access to confidential documents with sensitivity labels and encryption.

]]>
https://office365itpros.com/2018/08/16/guest-member-access-data/feed/ 0 229
Removing Email Addresses from Microsoft 365 Groups https://office365itpros.com/2018/08/14/removing-email-microsoft-365-groups/?utm_source=rss&utm_medium=rss&utm_campaign=removing-email-microsoft-365-groups https://office365itpros.com/2018/08/14/removing-email-microsoft-365-groups/#respond Tue, 14 Aug 2018 10:06:41 +0000 https://office365-ebook.com/?p=184
MC146221 Microsoft 365 groups

The Curious MC146221 Update

Microsoft published update MC146221 in the Microsoft 365 Message Center on August 8, 2018. The text is a masterpiece of obfuscation. It announces a new feature, but really what is happening here is that Microsoft has fixed a bug in the Set-UnifiedGroup cmdlet so that you can remove proxy email addresses from a Microsoft 365 Group. Although the notice says that Microsoft is releasing a new cmdlet, it’s just a fix for a cmdlet that’s been around since the introduction of Microsoft 365 Groups in November 2014.

Reclaiming an Email Address

When Microsoft says that “it was not possible to reclaim email addresses of Groups,” it means that the Set-UnifiedGroup cmdlet didn’t work when you tried to remove a proxy address from the set in a group’s EmailAddresses attribute. The bug has now been fixed.

In the following example, we examine the set of addresses for a group and then remove one. When we check the EmailAddresses attribute again, the address we removed is gone, which is what we want. In Microsoft terms, the address is reclaimed because it can now be assigned to another mail-enabled object.

Get-UnifiedGroup -Identity BankingTeam | select -ExpandProperty emailaddresses
SMTP:BankTeam@office365itpros.com
smtp:BankingTeam@Office365itpros.com
smtp:BankingGroup@Office365itpros.com
smtp:CorporateBanking@office365itpros.com
SPO:SPO_d8f732ac-454e-4ba1-b596-c2c5effb911d@SPO_b662313f-14fc-43a2-9a7a-d2e27f4f3478

Set-UnifiedGroup -Identity BankingTeam -EmailAddresses @{Remove="BankingTeam@Office365itpros.com"}
Get-UnifiedGroup -Identity BankingTeam | select -ExpandProperty emailaddresses

SMTP:BankTeam@office365itpros.com
smtp:BankingGroup@Office365itpros.com
smtp:CorporateBanking@office365itpros.com

Note: Don’t try to update the SPO proxy address for groups. These addresses are used for internal links with SharePoint Online.

The same syntax can be used to add a new SMTP proxy address or MOERA address to a group. These commands create two new proxy addresses, the latter being a MOERA address.

Set-UnifiedGroup -Identity BankingTeam -EmailAddresses @{Add="Banking.Team.Winners@Office365itpros.com"}
Set-UnifiedGroup -Identity BankingTeam -EmailAddresses @{Add="Banking.Team.Winners@Office365itpros.onmicrosoft.com"}

To set a new primary address, run Set-UnifiedGroup -PrimarySmtpAddress and select one of the proxies already present for the group:

Set-UnifiedGroup -Identity BankingTeam -PrimarySmtpAddress Banking.Team.Winners@Office365itpros.com

Restrictions in SMTP Address Assignment

You can’t remove the primary SMTP address of a group without reassigning primary status to another address first. Also, you can’t remove the MOERA address from a group (unless another exists). MOERA stands for Microsoft Online Email Routing Address. It is an SMTP proxy address from the tenant’s service domain (the one that looks like office365itpros.onmicrosoft.com).

In the past, all Microsoft 365 groups only had MOERA addresses. This situation persisted until Microsoft introduced support for email address policies for groups, a capability which allows administrators to dictate that the email addresses assigned to new groups come from a selected domain. Even if email address policies are in force, Exchange Online makes sure that new groups receive a MOERA SMTP proxy address.

Administrators can only remove a MOERA address from a group if another MOERA address is present in the set of proxy addresses for the group. In other words, before attempting to remove a MOERA address from a group, assign another to take its place. If you don’t, Exchange Online signals the error:

“There should be atleast one MOERA in Email Addresses.”

And yes, there’s no space between at and least in the error message.

Be Careful

Before you rush out to reclaim addresses, remember why SMTP proxy addresses exist. If you remove an address from Object A and assign it to Object B, any email sent to that address will be delivered to Object B. This might not be what you want to happen. Keeping old proxy addresses in the set assigned to mail-enabled objects allows those objects to continue receiving email for old addresses after updates to the primary SMTP address or MOERA address.

Retaining old proxy addresses might not be so important for a Microsoft 365 group because most of the traffic to group mailboxes is typically internal, but it is for recipients which receive a higher volume of external email such as user and shared mailboxes.


Learn more about how the Office 365 applications really work on an ongoing basis by subscribing to the Office 365 for IT Pros eBook. Our monthly updates keep subscribers informed about what’s important across the Office 365 ecosystem.

]]>
https://office365itpros.com/2018/08/14/removing-email-microsoft-365-groups/feed/ 0 184
Why Search-Mailbox Can’t Remove All Office 365 Content https://office365itpros.com/2018/08/12/why-search-mailbox-cant-remove-all-office-365-content/?utm_source=rss&utm_medium=rss&utm_campaign=why-search-mailbox-cant-remove-all-office-365-content https://office365itpros.com/2018/08/12/why-search-mailbox-cant-remove-all-office-365-content/#comments Sun, 12 Aug 2018 21:09:47 +0000 https://office365-ebook.com/?p=181

ExchangeOnline

Search-Mailbox – Powerful but Limited

Note: Search-Mailbox is due for deprecation on July 1, 2020. See this post for more information.

Search-Mailbox is a very powerful cmdlet. It can search user mailboxes to find and remove content, or copy content to another mailbox, or both. The usual situation when Search-Mailbox is called into use is when someone, invariably an important person (in their minds, anyway), makes a mistake and sends email when they shouldn’t have and now wants every trace of the message eradicated. Search-Mailbox can do this, but only within the boundary of a single Office 365 tenant, and only in user and shared mailboxes.

Another common scenario is when some inappropriate or malicious content is circulating in email. If you can construct search criteria to find the bad content, Search-Mailbox can track it down and erase it, again from user and shared mailboxes.

No Group Mailboxes

Search-Mailbox can’t deal with group mailboxes, so it cannot erase content posted to the Inbox of Office 365 Groups nor can it remove Teams compliance records from the Team Chat folder. Removing compliance records might seem to be a bad thing, and normally it is, but if you do this to force Teams to synchronize the deletions back to its Azure data services and so remove the bad content from channel conversations, it could be a good thing. If, that is, appropriate authorizations are sought and granted to allow deletions to proceed.

The reason why Search-Mailbox is limited to user and shared mailboxes is that it was built many years ago to run inside an Exchange on-premises environment where the only objects it might have to process were user and shared mailboxes. Apart from making sure that it can understand queries expressed in KQL-syntax, Microsoft hasn’t done much to Search-Mailbox since Exchange 2010.

Dealing with Non-Mailbox Content

Search-Mailbox cannot process documents stored in SharePoint or OneDrive for Business libraries, or sways, plans, or forms, or any of the other non-Exchange content created by users and found inside Office 365.

If you need to run a search to find information across all the Office 365 workloads, you can use a content search, which covers Exchange (including public folders), SharePoint, OneDrive, and Teams. Once you’ve found the information, you can add a purge action to the search and have it remove items. But here’s the downside – content searches can only purge 10 items at a time and can only soft-delete information. In other words, the deletions can be reversed.

Hard Deletes

Probably with good reason, Microsoft has not yet allowed content searches to hard-delete items from the workloads it supports. Perhaps this is because the same kind of backups that exist on-premises don’t exist in the cloud, and if you made a mistake and permanently removed some information, Microsoft wouldn’t be able to retrieve that information. When backups don’t exist, soft-deletion and a nice period in a recycle bin seems like a good idea.

But Search-Mailbox does hard-delete items, which is what you want to do with malware or other objectionable material in mailboxes, so it’s a powerful tool that needs to be handled with care.

For more information about Search-Mailbox, see Chapter 6 of Office 365 for IT Pros. For more information about content searches, see Chapter 20.

]]>
https://office365itpros.com/2018/08/12/why-search-mailbox-cant-remove-all-office-365-content/feed/ 7 181