Vue lecture

Il y a de nouveaux articles disponibles, cliquez pour rafraîchir la page.
✇Office 365 for IT Pros

Find Out Who’s Using Teams Shared Channels in Another Tenant

Use Inbound and Outbound Shared User Profiles to Reveal the Ins and Outs of Membership in Teams Shared Channels

In August 2022, I discussed how to use the Get-AssociatedTeam cmdlet to report the membership of channels in teams for users within a tenant. It’s a useful cmdlet that includes the ability to report membership of shared channels in other tenants. In most cases, the reports that can be generated from the data returned by the Get-AssociatedTeam cmdlet meet the needs of administrators to know what channels users access.

Microsoft 365 often offers multiple ways to report data. In this instance, Azure AD supports shared user profile resources created for use with Azure AD B2B Direct Connect, the underlying cross-tenant access mechanism for shared channels.

  • An inbound shared user profile represents an Azure AD user from an external Azure AD tenant whose profile data is shared with your tenant. The profile data is used by applications like Teams to display information about the inbound user in shared channels.
  • Conversely, an outbound shared user profile represents Azure AD users from your tenant who share their profile information when they access resources in other Azure AD tenants.

Essentially, when a shared channel owner invites an external user to become a member of the channel and that user confirms their acceptance, Azure AD creates an inbound shared user profile to note this fact. Azure AD creates an outbound shared user profile when a user from your tenant becomes a member of a shared channel hosted by another tenant. For example, Figure 1 shows the membership of a Teams shared channel. The users marked with (External) have inbound shared user profiles.

Membership information for Teams shared channels
Figure 1: Membership information for Teams shared channels

Using PowerShell to Report Shared User Profiles

The Microsoft Graph PowerShell SDK contains cmdlets to fetch information about unbound and outbound user profiles. With consent for the CrossTenantUserProfileSharing.Read.All permission, you can connect to the Graph and run these commands:

Connect-MgGraph CrossTenantUserProfileSharing.Read.All
Select-MgProfile beta
Get-MgDirectoryOutboundSharedUserProfile

UserId
------
08dda855-5dc3-4fdc-8458-cbc494a5a774
5b52fba5-349e-4624-88cd-d790883fe4c4
a221d10f-e0cf-4a1d-b6a2-4e844670f118
cad05ccf-a359-4ac7-89e0-1e33bf37579e
eff4cd58-1bb8-4899-94de-795f656b4a18

The output is a list of identifiers for Azure AD user accounts, so it’s not very exciting. IApart from not listing account names, the output doesn’t tell us what outbound tenants are accessed. To get that information, we must run the Get-MgDirectoryOutboundSharedUserProfileTenant cmdlet for each account. The output of that cmdlet is a list of tenant identifiers, which we can resolve to discover the tenant name. Here’s the code:

[array]$Users =  Get-MgDirectoryOutboundSharedUserProfile | Select-Object -ExpandProperty UserId
ForEach ($User in $Users) {
   $UserData = Get-MgUser -UserId $User
   [array]$TenantNames = $Null; $TenantDisplayNames = $Null
   [array]$TenantIds = Get-MgDirectoryOutboundSharedUserProfileTenant -OutboundSharedUserProfileUserId $User | Select-Object -ExpandProperty TenantId
   If ($TenantIds) {
       ForEach ($TenantId in $TenantIds) {
         $Uri = ("https://graph.microsoft.com/beta/tenantRelationships/findTenantInformationByTenantId(tenantId='{0}')" -f $TenantId.ToString())
         $ExternalTenantData = Invoke-MgGraphRequest -Uri $Uri -Method Get  
         $TenantNames += $ExternalTenantData.DisplayName
       }
       $TenantDisplayNames = $TenantNames -join ", "    
   }
   Write-Host ("User {0} has outbound shared profiles in these tenants {1}" -f $UserData.DisplayName, $TenantDisplayNames)
}

User Sean Landy has outbound shared profiles in these tenants o365maestro
User Ken Bowers has outbound shared profiles in these tenants o365maestro
User Tony Redmond has outbound shared profiles in these tenants o365maestro, Microsoft Community & Event Tenant

Getting Inbound Shared User Profiles

The Get-MgDirectoryinboundSharedUserProfile cmdlet lists information stored about inbound shared user profiles. We can’t read Azure AD to find information about these users because they come from other tenants. This is what the cmdlet returns:

Get-MgDirectoryinboundSharedUserProfile | Format-List

DisplayName          : Alex Wilber
HomeTenantId         : 22e90715-3da6-4a78-9ec6-b3282389492b
UserId               : a6453657-2058-4c15-a38a-b0a94f0ed737
UserPrincipalName    : AlexW@o365maestro.onmicrosoft.com
AdditionalProperties : {}

Once again, we can resolve the tenant identifier to make the information more understandable:

[array]$Guests = Get-MgDirectoryinboundSharedUserProfile
ForEach ($Guest in $Guests) {
    $Uri = ("https://graph.microsoft.com/beta/tenantRelationships/findTenantInformationByTenantId(tenantId='{0}')" -f $Guest.HomeTenantId.ToString())
    $ExternalTenantData = Invoke-MgGraphRequest -Uri $Uri -Method Get  
    Write-Host ("User {0} comes from tenant {1}" -f $Guest.DisplayName,  $ExternalTenantData.DisplayName)
}

User Christina Smith comes from tenant CM Portal Solutions
User Nicolas Blood comes from tenant NBConsult
User Alex Wilber comes from tenant o365maestro
User Tom Jones comes from tenant o365maestro
User Vlad Bitton comes from tenant vNext Solutions

The interesting thing here is that I didn’t recognize some of the user names and tenants that Azure AD stored inbound shared user profiles for. However, given that the names were all MVPs and my tenant supported many beta versions of Teams shared channels in the past, it’s entirely possible that the profiles originated in a test. Azure AD doesn’t register a date to tell you when it created a profile, so there’s no clue from that source.

Tracking External Access to Teams Shared Channels

My previous article describes how to create a report about the users accessing shared channels in your tenant. The added piece of information covered here is finding the set of Azure AD accounts from your tenant who use Azure AD B2B Connect to access resources in other tenants. That’s a valuable nugget if you want to track who’s interacting with Teams shared channels externally.

✇Office 365 for IT Pros

Reducing the Likelihood of Token Theft with Conditional Access Policies

New Token Protection Conditional Access Policy Session Control

Now that the removal of basic authentication from Exchange Online has made password spray attacks far less likely to compromise user credentials for an Azure AD account, those who want to sneak into a tenant need another avenue to explore. Microsoft’s Detection and Response Team (DART) reports an increase in adversary-in-the-middle phishing attacks where attempts are made to capture user credentials and the tokens used by applications to access protected resources like user mailboxes or SharePoint Online sites.

If you need further evidence of the techniques used to compromise and exploit tokens, this article by Edwin David is a good read. It’s a reminder that although all Azure AD accounts should be protected by multi-factor authentication, MFA is not a silver bullet and attackers will continue to develop methods to work around barriers erected by tenants.

Token Binding to Devices

Which brings me to a new session control for Azure AD conditional access policies designed to protect sign-in tokens (refresh tokens) using token protection. The control, which has just appeared in preview, creates a “cryptographically secure tie” between the token and the device Azure AD issues the token to (aka token binding). Without the client secret (the device), the token is useless to an attacker. The device needs to run Windows 10 or above and be Azure AD joined, hybrid Azure AD joined, or registered in Azure AD. When this is the case, a user’s identity is bound to the device.

Microsoft notes that “Token theft is thought to be a relatively rare event, but the damage from it can be significant.” One interpretation of this statement is that Microsoft knows the bad guys are working on using more token thefts, so they’re investing to get ahead of the curve.

Clients

It’s a preview, so some limitations are inevitable. For instance, conditional access policies with token protection can only process connections from tenant accounts and can’t handle inbound connections from guest accounts. Token protection supports Microsoft 365 apps for enterprise subscription versions of desktop clients accessing Exchange Online and SharePoint Online. Perpetual versions of the Office apps aren’t supported. The apps include the OneDrive sync client (22.217 or later) and the Teams desktop client (1.6.00.1331 or later). These are relatively old versions already, so meeting the software requirements should not be a big issue.

PowerShell clients accessing Exchange Online, SharePoint Online, or these endpoints via the Microsoft Graph APIs are unsupported by conditional access policies with token protection, meaning that users are blocked from accessing Exchange and SharePoint. The same is true for some other apps like Visual Studio and the Power BI desktop app. It also applies to connections generated using OWA and Outlook mobile.

In effect, the users selected to test a token protection condition access policy (Figure 1) should be those who don’t need to use any of the unsupported clients and are happy to limit their access to Outlook desktop and Teams.

Parts of a conditional access policy with token protection
Figure 1: Parts of a conditional access policy with token protection

Users who don’t meet the policy requirements (like attempting to sign in with OWA, the browser version of Teams, or the SharePoint Online or OneDrive for Business browser clients) will fail to connect (Figure 2).

Token protection stops an app connecting
Figure 2: Token protection stops an app connecting

In fact, any Office browser app that connects to Exchange or SharePoint resources will be inaccessible. For instance, Viva Engage (Yammer) will start up before immediately exiting when the client attempts to access SharePoint Online.

A Pointer to the Future

Given the relative lack of support by Microsoft 365 apps for token protection, this preview feature is unlikely to get the same range of testing as other recent extensions to conditional access policies (like authentication strength). That being said, if token theft becomes as biga  problem as some security commentators think it might, it will be good to have methods like token protection ready to repel the threat.


Insight like this doesn’t come easily. You’ve got to know the technology and understand how to look behind the scenes. Benefit from the knowledge and experience of the Office 365 for IT Pros team by subscribing to the best eBook covering Office 365 and the wider Microsoft 365 ecosystem.

✇Office 365 for IT Pros

Teams Adds Captions to Chat Video Messages

Auto-generation of Captions for Teams Video Messages

In September 2022, Microsoft announced the ability to send video messages in Teams chat. Released in November 2022, the feature allows users to send video clips up to one minute long to participants in Teams private or group chats, if the Teams messaging policy assigned to their accounts allows video messages.

Sometimes it’s hard to listen to video messages and understand fully what the sender says. Microsoft addresses that problem in an update to add support for auto-generated captions that can be read by message recipients with the sound turned on or off. The availability of captions makes it possible to read a video message in a crowded space where you don’t want to turn the device volume up to hear the audio.

According to message center notification MC534735 (last updated March 31, 2023), users in targeted release tenants have started to receive the feature while deployment to standard release tenants will start in mid-April and complete by the end of the month.

Microsoft doesn’t say what languages are available for video message transcripts. Given that meeting transcription is available in 34 languages, I imagine that the same applies.

Caption Auto-Generation

It’s likely that the same process that generates live captions for Teams meetings is employed to generate the captions for video clips. Generation occurs when the sender sends the video message. At that point, Teams uploads the video file to an online repository where the captions are generated.

Figure 1 shows a video messages with captions displayed (enabled with the CC or closed captioning button). Recipients can play video messages in line within the chat or can expand to full screen, which uses what appears to be a version of the Stream video player with minimal playback options (quality, speed, forward/back 10 seconds, turn audio off, etc.).

Viewing auto-generated captions for a Teams video message
Figure 1: Viewing auto-generated captions for a Teams video message

Caption Transcript File

Captions form the basis for transcript generation in Teams meetings and for other videos stored in Stream. Each caption is text generated for a timecoded part of a video or audio file. Only the sender of the video message can download the transcript (Figure 2).

The sender of a Teams video message can download the transcript
Figure 2: The sender of a Teams video message can download the transcript

The result is a file called MicrosoftTeams-transcript.vtt. VTT or WebVTT is a Video Text Tracks file and is a common format used for video subtitling. You can use a text editor like Notepad to open and view the contents of a VTT file like the one shown below.

WEBVTT

00:00:00.340 --> 00:00:03.539

The review for the Office 365 for IT

00:00:03.540 --> 00:00:07.359

Pros 2024 Edition

00:00:07.360 --> 00:00:10.799

will take place on the 27th of April

00:00:10.800 --> 00:00:12.210

and I hope you can be there

Downloading a Video Message

Speaking of downloads, Teams doesn’t offer users the option to download a video clip. It’s possible to do this, but only by using developer tools. In summary:

  • Press F12 to open developer tools in the browser.
  • Select the Network tab.
  • Open the chat where the video message is and play it.
  • In the Name section of developer tools, look for 0 (zero) and then look at the Headers tab. You should find a Request URL there that points to the location where Teams fetches the video from (Figure 3). Copy this value to Notepad or your favorite text editor.
  • In the editor, select the /dash_video_orginal/videoSegment/0 part of the URL and replace it with /video
  • The result should be a URL like https://eu-prod.asyncgw.teams.microsoft.com/v1/objects/0-neu-d1-c4457fef4c67a75fe3c0732e0aceb538/views/video.
  • Paste this into a browser tab to download the video message (MP4 file).

Getting the URL for a Teams video message
Figure 3: Getting the URL for a Teams video message

Video Messages and Compliance

When I wrote about Teams video messages in September 2022, I pointed out that it’s difficult for compliance investigators to find information in video messages. I had hoped that the advent of transcripts for video messages would close the compliance gap and make it easier to find video messages based on the information captured in the transcript. Alas, this is not so. All my attempts to find video messages by inputting transcript contents into content searches failed. That’s a real pity.

Good Upgrade but Compliance is a Real Miss

Adding transcripts to video messages in Teams chat is a nice upgrade. It would be even nicer if Microsoft addressed the compliance issue as the inability to search for video content (now available in the transcripts) is more than enough to stop some organizations using this facility.


Make sure that you’re not surprised about changes that appear inside Office 365 applications by subscribing to the Office 365 for IT Pros eBook. Our monthly updates make sure that our subscribers stay informed.

✇Office 365 for IT Pros

Microsoft Retires AIP Add-On for Office

Need Recedes for Unified Labeling Client

On April 11, Microsoft announced that they will retire the AIP client, aka the Unified Labeling client, aka the AIP add-on for Office, on 11 April 2024. The add-on has been in maintenance mode since January 1, 2022, so its final retirement was only a matter of time. Once retirement happens, users cannot assign sensitivity labels to documents through the add-on.

A Long Road

In 2016, when I first started writing about how to protect Office documents with labels, the labels were called Azure Information Protection labels and users needed to install the add-on to add elements like the information protection bar and the code to apply rights management to documents. The situation was natural because Azure Information Protection was a separate product that targeted Office but had no formal alignment with Office development. The add-on was only available for Office on Windows.

Things changed when Microsoft decided that sensitivity labels were strategically important to Office 365, which meant that they needed to build support for sensitivity labels across the infrastructure in apps like SharePoint Online and Exchange Online and desktop, browser, and mobile apps. Sensitivity label support is now broad and deep across Microsoft 365, including for container management of sites, groups, and teams. Regretfully, sometimes Microsoft demands additional licenses for features that seem very basic, such using the Syntex-SharePoint Advanced Management license to control the assignment of default sensitivity labels to SharePoint document libraries.

In 2019, Microsoft started the process of removing the add-on by incorporating the code to handle sensitivity labels in the Office applications (native mode protection). The goal is to provide the same or better functionality in the out-of-the-box Microsoft 365 apps for enterprise (Office desktop) versions of Word, Excel, and PowerPoint. Microsoft says that the Microsoft 365 apps for enterprise “now have most of the capabilities found in the AIP Unified Labeling add-in for Office as well as advanced capabilities not possible with the AIP Unified Labeling add-in for Office.” The most important of these capabilities are:

  • PDFs exported from the Office apps retain protection applied by sensitivity labels.
  • Sensitivity labels can protect meeting invitations (including attachments) and responses.
  • Account switching.
  • Users cannot disable labeling controls.

Microsoft has long stressed that incorporating code from the Microsoft Information Protection SDK to make applications natively aware of information protection leads to better performance and increased stability. In other words, something that’s built-in is likely to work better than when an application needs to load in external code.

Native protection is only available with the subscription versions of Office. The functionality isn’t supported by perpetual versions of Office like Office 2019.

Making Changes to Ease Migration

Technologies that affect how people work are usually harder to migrate to new platforms than background processing is. Changes to Office applications are good examples of the truth of this assertion (as anyone who remembers the introduction of the ribbon in Office 2007 can attest).

As an example, the add-on features an information protection bar that people like. The Microsoft 365 apps don’t use the information protection bar. Instead, Microsoft has changed the menu and title bars of the Office apps to highlight labels in a different way, including displaying different colors for different labels. The latest tweak is in Outlook desktop, where the latest builds feature a prominent new button to allow users to more easily assign a sensitivity label to emails (Figure 1).

Applying a sensitivity label with Outlook

Unified labeling client
Figure 1: Applying a sensitivity label with Outlook

Other Azure Information Protection Elements

I stopped using the unified labeling client two years ago. However, I have installed the unified labeling client on PCs to get other elements that came with the add-on such as the Azure Information Protection PowerShell module and the ability to classify and protection files from the Windows Explorer. The PowerShell module is especially helpful when the need exists to remove sensitivity labels from files.

Microsoft says that they are not retiring these elements, nor are they retiring the viewers that allow people to view protected content on Windows, iOS, and Android, or the Azure Information Protection Scanner. Microsoft says that following the retirement of the add-on, they will remove it from the installable package available in the Download Center. User will be able to install the new version of the package to access the other elements, which will also be rebranded as Microsoft Purview capabilities.

Time to Move On

The unified labeling client or add-on for Office has served its purpose. It’s time to let it go and migrate as quickly as possible to use the built-in capabilities that exist in Office. Apart from the small fact about the retirement, it’s clear that Microsoft has poured engineering effort into building out the sensitivity label infrastructure across Microsoft 365 for the last several years. Benefit of that work isn’t available to the add-on, which is a good a reason to move on as anything else.


So much change, all the time. It’s a challenge to stay abreast of all the updates Microsoft makes across Office 365. Subscribe to the Office 365 for IT Pros eBook to receive monthly insights into what happens, why it happens, and what new features and capabilities mean for your tenant.

✇Office 365 for IT Pros

The Right Way to Revoke Access from Azure AD Accounts with PowerShell

Use the Revoke-MgUserSignInSession cmdlet to Revoke Access for Azure AD Accounts

Microsoft’s documentation for how to revoke access to an Azure AD account describes the use of the Revoke-AzureADUserAllRefreshToken cmdlet from the Azure AD PowerShell module. That’s unfortunate because of the upcoming deprecation of that module. If we consult Microsoft’s cmdlet map to find the appropriate replacement cmdlet from the Microsoft Graph PowerShell SDK, it turns out to be Invoke-MgInvalidateUserRefreshToken, which “Invalidates all of the user’s refresh tokens issued to applications (as well as session cookies in a user’s browser), by resetting the refreshTokensValidFromDateTime user property to the current date-time.”

The guidance could not be clearer. Any script using the Revoke-AzureADUserAllRefreshToken should replace it with the Invoke-MgInvalidateUserRefreshToken cmdlet. Except when you discover that the SDK also includes the Revoke-MgUserSignInSession cmdlet. This cmdlet is in beta and its documentation is less than perfect (or totally inadequate), but the salient fact is that it performs the same task. These two commands have the same effect:

$RevokeStatus = Revoke-MgUserSignInSession -UserId $UserId
$InvalidateStatus = Invoke-MgInvalidateUserRefreshToken -UserId $UserId

Up to now, the Office 365 for IT Pros eBook (chapter 5) documented how to use the Invoke-MgInvalidateUserRefreshToken cmdlet to block an Azure AD user account. Finding the alternative cmdlet used in a Microsoft example provoked a query to ask why two cmdlets did the same thing.

Microsoft’s response is that they built Invoke-MgInvalidateUserRefreshToken for a specific purpose. The cmdlet still works and has the significant benefit of being part of the production (V1.0) module. However, Microsoft’s recommendation is to use Revoke-MgUserSignInSession in the future, even if it is in the beta module.

Use the Beta SDK Module

Using cmdlets from the beta module might seem problematic but it’s not. For instance, if you want to do any license management with the Microsoft Graph PowerShell SDK, you must use the beta module because the production version of cmdlets like Get-MgUser don’t return any license information. It’s one of those important to know things when converting scripts to use the SDK.

Revoking Access for an Azure AD Account is the Start

Of course, revoking access for an Azure AD account might just be the first step in the process of securing the account. Revoking access will force the user to reauthenticate, but if you want to stop further access to the account, you must:

Disabling the account and changing the password are both critical events that force Azure AD to signal applications that support continuous access evaluation (CAE) to terminate sessions. Many of the important Microsoft 365 apps like Outlook and SharePoint Online support CAE (see current list).

This PowerShell code does the necessary, if the account signing into the Microsoft Graph PowerShell SDK holds at least the User Administrator role:

Connect-MgGraph -Scopes Directory.AccessAsUser.All
Select-MgProfile Beta
$Account = Read-Host "Enter the User Principal Name of the account to block"
$User = (Get-MgUser -UserId $Account -ErrorAction SilentlyContinue)
If (!($User)) { Write-Host ("Can't find an Azure AD account for {0}" -f $Account); break }
Write-Host ("Revoking access and changing password for account {0}" -f $User.DisplayName)  
# Disable the account
Update-MgUser -UserId $User.Id -AccountEnabled:$False
# Create a password profile with details of a new password
$NewPassword = @{}
$NewPassword["Password"]= "!NewYorkCity2022?"
$NewPassword["ForceChangePasswordNextSignIn"] = $True
Update-MgUser -UserId $User.Id -PasswordProfile $NewPassword
# Revoke signed in sessions and refresh tokens
$RevokeStatus = Revoke-MgUserSignInSession -UserId $User.Id
# Disable registered devices
[array]$UserDevices = Get-MgUserRegisteredDevice -UserId $User.Id
If ($UserDevices) {
ForEach ($Device in $UserDevices) {
    Update-MgDevice -DeviceId $Device.Id -AccountEnabled $False}
}

Figure 1 shows that after running the script, the user account is disabled and the SignInSessionsValidFromDateTime property (referred to as refreshTokensValidFromDateTime above) is set to the time when the Revoke-MgUserSignInSession cmdlet ran.

Running PowerShell to revoke access for an Azure AD account
Figure 1: Running PowerShell to revoke access for an Azure AD account

Consequences of Disabling an Azure AD Account

In a scenario like a departing employee, losing access to some teams might not be important. If it is, or in situations where it’s necessary to preserve the account in full working order, an alternative to disabling an account is to change its password and revoke access. The account remains active but is inaccessible unless those attempting to sign-in know the new password.

Example of Knowledge Gap

In July 2022, I wrote about the opening of a knowledge gap as tenants transitioned from the depreciated Azure AD and Microsoft Online Services (MSOL) modules. Having two cmdlets that revoke user access to pick from is one too many. It doesn’t help people migrate scripts to use the Microsoft Graph PowerShell SDK. But at least the recommendation is clear: use Revoke-MgUserSignInSession.


Insight like this doesn’t come easily. You’ve got to know the technology and understand how to look behind the scenes. Benefit from the knowledge and experience of the Office 365 for IT Pros team by subscribing to the best eBook covering Office 365 and the wider Microsoft 365 ecosystem.

✇Office 365 for IT Pros

Microsoft Removes Remote PowerShell for Compliance Sessions

No Remote PowerShell Connections for Compliance Endpoint

Following the December 15, 2022 announcement to deprecate Remote PowerShell connections to Exchange Online, the news in MC541649 (April 14) that the connection to the compliance endpoint with Connect-IPPSSession cmdlet will follow suit is no surprise. The only surprise is that the text of the announcement is quite so confusing.

Connect-IPPSSession establishes a PowerShell connection to what used to be called the Security and Compliance endpoint (SCC). Microsoft also refers to EOP in the announcement because some cmdlets loaded (like Get-PhishSimOverridePolicy) are associated with Exchange Online Protection.

Today, the endpoint might be called the Microsoft Purview endpoint or compliance endpoint because the cmdlets loaded after establishing the connection allow access to objects like retention labels, sensitivity labels, and their respective publishing policies.

REST Rather than Remote PowerShell

Microsoft says that “in line with our vision to enhance the security of our cloud,” the compliance cmdlets will now use a REST API instead of the traditional (established in Exchange 2010) Remote PowerShell approach. Once you install V3.2 of the Exchange Online management module (apparently available on May 1, 2023), the REST-base cmdlets are available and Remote PowerShell is no longer required. You won’t see this kind of message when connecting to the endpoint:

WARNING: Your connection has been redirected to the following URI:
"https://eur01b.ps.compliance.protection.outlook.com/Powershell-LiveId?BasicAuthToOAuthConversion=true;PSVersion=5.1.22621.963"

Existing scripts don’t need to be updated. As Microsoft says “Simply using the new module will ensure REST is used rather than RPS.”

Part of the confusion in this announcement is the need to use a version of the Exchange Online management module that is currently unavailable. The current version doesn’t support the UseRPSSession parameter mentioned by Microsoft in their text:

Connect-IPPSSsession -UseRPSSession:$false

Microsoft says that Remote PowerShell connections to the compliance endpoint will not be available after July 15, 2023. This is a tad ahead of the announced schedule for the depreciation of Remote PowerShell for the main Exchange module (due on October 1, 2023).

Using a REST API instead of Remote PowerShell should make cmdlets more reliable and better performing. Remote PowerShell is very much a mechanism rooted in a period when Microsoft needed to support management of Exchange servers from workstations without the need to log into the servers. It worked well for Exchange 2010 and 2013 but its deficiencies are obvious with cloud services when connecting to a service is more important than connecting to a server.

More to Do

Welcome as it is to see the compliance cmdlets transition to a REST-based endpoint, there’s still more to do to fully modernize these cmdlets. Adding support for Azure managed identifies is a big step that needs to happen. It can be argued that the compliance cmdlets are less heavily accessed than those in the main Exchange module, but this ignores the fact that many of the tasks that you might want to run on a scheduled basis using an Azure Automation runbook might need to access compliance elements, like the list of sensitivity labels defined in a tenant (Figure 1).

 Listing sensitivity labels after connecting to the compliance endpoint
Figure 1: Listing sensitivity labels after connecting to the compliance endpoint

Good Change

There’s no doubt that moving the compliance endpoint away from a dependency on Remote PowerShell is a good thing. Throwing away the baggage of on-premises implementations to make things work smoother in the cloud is always positive for those who need to automate Microsoft 365 operations. This is especially so when discussing compliance because the range of compliance functionality available in Microsoft 365 is so much wider and deeper than in the on-premises servers.

At this point, we don’t have the V3.2 release of the Exchange Online management module available so it’s hard to verify Microsoft’s assertion that nothing needs to be done to move the compliance cmdlets from Remote PowerShell to REST-based APIs. However, given the progress seen in the main Exchange Online management module, Microsoft is progressing down a well-known path and the change should be smooth. At least. I hope it will be.

✇Office 365 for IT Pros

Microsoft Pushes Deprecation of Some Client Access Rules to September 2024

Extra Year to Give Tenants Time to Overcome Technical Limitations that Prevent Migration

Without much fanfare, the Exchange Online team decided to give tenants that use client access rules an extra year to make the transition to Azure AD conditional access policies. The original deprecation date of September 2023 is now September 2024. The kicker in this statement is that only rules that cannot be migrated to conditional access policies because of a “technical limitation” can continue working for the extra year.

First announced at the Microsoft Ignite 2017 conference, client access rules are only available in Exchange Online and exist to control connections coming into Exchange Online. You can do things like block POP3 and IMAP4 connections or restrict access to these protocols from specific IP addresses.

Client access rules are a solution created by Exchange Online for an environment that was very different to today. In 2017, customers wanted help to control inbound connections to Exchange Online. Azure AD conditional access policies didn’t have the feature set that’s available now and Exchange Online still supported basic authentication across all its connectivity protocols.

The Current State of Microsoft 365 Connection Management

Moving forward to today, Microsoft has largely eliminated basic authentication from Exchange Online to cut off techniques like password sprays that attackers heavily depended on to retrieve user account credentials. Attackers still try, but attempts to use basic authentication to check username/password combinations fail at the first hurdle. Apart from keeping access to SMTP AUTH, there’s no further need for authentication policies.

Deprecating client access rules could be construed as another side effect of modern authentication becoming the norm in Exchange Online. But the more important factor is that Microsoft 365 favors features that function across the entire ecosystem instead of being tied to a single workload. Azure AD is the directory of record and conditional access policies are how Azure AD controls inbound connections. Dropping client access rules (specific to Exchange Online) to embrace conditional access policies is evidence of that trend. We see the same in the compliance and information protection areas where Microsoft 365 policies take prime position.

Microsoft is pouring engineering effort into Azure AD conditional access policies. In the last year alone, Microsoft has added features such as:

Conditional access policies are closely associated with multi-factor authentication and are often configured to ensure that inbound user connections use MFA, especially for administrator accounts.

Migration Away from Workload-Specific Implementations Can be Problematic

Moving from a workload-specific implementation to a platform-wide implementation can be problematic. It’s likely that the workload-specific code covers narrower use cases that only occur within a workload. For example, Exchange Online mailbox retention policies can process items at a folder level and move items to the online archive when their retention period expires. By comparison, Microsoft 365 retention polices process mailboxes as a single unit and don’t go to folder level and can only delete or keep items instead of being able to move them to the archive. Then again, because Microsoft is actively developing Microsoft 365 retention policies, they benefit from recent innovations like adaptive scopes and disposition reviews, neither of which are available for Exchange mailbox retention policies.

In the case of client access rules, Microsoft acknowledges that they “have encountered a few scenarios where it’s not possible to migrate current rules” and say that they will allow the ongoing use of client access rules “until we can support them” (presumably the scenarios that migration is not currently possible).

Microsoft doesn’t describe what scenarios are problematic. They also don’t say how customers can discover if their client access rules fall into the category of those that Microsoft consider to have a technical limitation that prevents migration. Microsoft plans to disable client access rules that they consider can be migrated to conditional access policies in September 2023. Only rules that receive Microsoft approval can continue running until September 2024, at which point the curtain descends for all client access rules (Figure 1).

Microsoft timeline for deprecation of client access rules
Figure 1: Microsoft timeline for deprecation of client access rules

Apart from not documenting the technical limitations that get in the way of migration, Microsoft also doesn’t say how customers receive approval for the one-year extension for client access rules. The blog says that customers should “open a support ticket so we can investigate and understand your needs,” but doesn’t explain how this process results in a rule being allowed to continue running past September 2023.

The Filtering Issue

Browsing the documentation for client access rules, the obvious issue appears to be in the areas of filtering. Like in other areas (like dynamic distribution lists), Exchange Online supports recipient filters for client access rules in a different manner than operated for conditional access policies. You can assign conditional access policies to specific users and groups (including dynamic Microsoft 365 groups), but that’s not quite the same as using a recipient filter. I’m sure that I am missing something else, but recipient filtering seems like the big obstacle for migration.

I strongly support moving away from client access rules to embrace more secure implementations like conditional access policies that operate across the complete Microsoft 365 ecosystem. Microsoft throws continuous access evaluation (CAE) into the pot. Although CAE is a very good innovation to revoke access from accounts immediately important events like password changes occur, the issue here is all about migration.

Client Access Rules Migration Might Need Updates to Conditional Access Policies

If you’re using client access rules, it’s time to review the state of the migration.

  • Remove client access rules that are no longer necessary.
  • Migrate the remaining rules to conditional access policies.
  • If any rules cannot be migrated, contact Microsoft Support to discover if a technical limitation exists to prevent migration. If it does, the rules can continue working until September 2024. If not, Microsoft Support should be able to tell you how to migrate to conditional access policies before September 2023.

Microsoft doesn’t say how they will address the technical limitations that allow some client access rules to remain operational until September 2024. This might be because the Exchange Online team is waiting for their Azure AD colleagues to implement some features in conditional access policies. At least, I hope that’s what’s happening.


Insight like this doesn’t come easily. You’ve got to know the technology and understand how to look behind the scenes. Benefit from the knowledge and experience of the Office 365 for IT Pros team by subscribing to the best eBook covering Office 365 and the wider Microsoft 365 ecosystem.

✇Office 365 for IT Pros

Bring Your Own Domain for Microsoft 365 Service Messages

Use a Verified Domain to Send Microsoft 365 Service Messages

Announced as Microsoft 365 message center notification MC531211 (21 March 2023, Microsoft 365 roadmap item 103628) and now rolling out to tenants, organizations can choose one of the verified domains available for their tenant as the domain used for product advisory emails (Microsoft 365 service messages).

Microsoft 365 apps that support the feature include:

  • SharePoint Online
  • OneDrive for Business
  • Office
  • Stream
  • Planner
  • Project
  • Viva Connections
  • Viva Topics
  • Viva Amplify

Microsoft 365 apps use email addresses like no-reply@sharepointonline.com and no-reply@planner.com when they generate informational messages to communicate alerts, events, or digest information to users. For instance, when someone stores a document with a higher-level sensitivity label in a SharePoint Online site, SharePoint generates an email to tell them about the potential problem caused by the label mismatch. Figure 1 shows an example of such a message after selecting the office365itpros.com domain to send service messages.

Using a verified tenant domain to send Microsoft 365 service messages
Figure 1: Using a verified tenant domain to send Microsoft 365 service messages

The messages don’t cover service alerts (when a service has an outage), nor do they cover One Time Passcodes (OTP) generated by sharing actions from OneDrive and SharePoint Online. Sharing notifications continue to use no-reply@notify.microsoft.com to ensure delivery of these emails.

Using a Verified Domain

The steps to select a verified domain for service messages are laid out in the Microsoft documentation. In essence, tenant administrators use the Send email notifications from your domain option in the Organization profile section of Org Settings in the Microsoft 365 admin center to select a username and domain (Figure 2).

Selecting a username and verified domain to use for Microsoft 365 service messages
Figure 2: Selecting a username and verified domain to use for Microsoft 365 service messages

The domain must be one of the verified domains for the tenant. After saving the new configuration, the Microsoft 365 apps switch to use the selected username and domain instead of their default domains when they send email. Messages are now routed by Exchange Online on behalf of the organization. Just like any of the verified domains used for mail routing, the DNS records for the chosen domain should be configured for SPF, DKIM, and DMARC. This is especially important if email is relayed to Exchange on-premises or an external email service.

The Username for Service Messages

By default, the username is set to no-reply. The intention of a no-reply address is that users know that replying to the address will result in an undeliverable message. However, it’s possible to change the username to one for a routable address such as a shared mailbox so that users can get a response to questions about why they received a service message. Be careful if you do this because service emails then appear to be like any other email sent by the chosen address. Figure 3 shows an example of a message sent by SharePoint Online to report updates to documents in a site. The message appears to come from a shared mailbox because that’s what matches the configured address for service messages.

A service message from a shared mailbox
Figure 3: A service message from a shared mailbox

Not External Messages

Because the tenant’s instance of Exchange Online routes the service messages, they are now internal rather than external and therefore will not be tagged with the external indicator. In some respects, this is a major advantage of choosing to use a verified domain as users might better accept the content of the messages if they don’t come from an external source. The downside is that users might need to adjust inbox rules to process service messages correctly.

If you use a mail flow rule to protect administrator accounts from external email, remember to update the rule to deal with messages from your chosen domain.

Not a Change to Worry Too Much About

After using this option for a couple of weeks, I don’t see any great downside to using a verified domain to send Microsoft 365 service messages. Something might have slipped my attention (and if so, I’d like to know), but overall I think this is a good change that all tenants should consider.


Make sure that you’re not surprised about changes that appear inside Office 365 applications by subscribing to the Office 365 for IT Pros eBook. Our monthly updates make sure that our subscribers stay informed.

✇Office 365 for IT Pros

Teams Adds Snapchat Lenses to Video Effects for Meetings

Make Yourself Silly with Snapchat Lenses in Teams Meetings

Yesterday, I wrote about the profanity filter for Teams meetings, which is something that most business could see value in. Today, we have the arrival of Snapchat Lenses for Teams meetings, which is something that I think might spark a different reaction. Microsoft’s announcement calls for people to “let their silly side shine” and notes that “Snapchat Lenses are a witty and lighthearted addition to the world’s leading communication platform.” I think I prefer mesh avatars. According to Microsoft, Snapchat Lenses for Teams is rolling out and should be deployed to all commercial tenants by the end of April 2023.

Snapchat Lenses are available in the Teams desktop client for Windows and Mac. They are unavailable in the browser (including PWA) or mobile clients.

The Teams Snapchat Lenses App

Using Snapchat filters in Teams meetings is not new. The technique was first explored in early 2020 when people used the Snap camera in meetings (Snap camera is now discontinued). What’s different now is that Microsoft includes a third-party Teams app called Snapchat Lenses (Figure 1) in the set of apps published to tenants.

The Snapchat Lenses app in the Teams admin center
Figure 1: The Snapchat Lenses app in the Teams admin center

By default, the app is allowed (enabled). If an organization doesn’t want people using Snapchat Lenses in Teams meetings, all they need to do is disable the app by moving the toggle to the Blocked position. Further control over the app (for instance, to make it available to a limited set of people) with app permission policies. Oddly, Microsoft chose to make the app available to commercial clients only and hasn’t included it in Teams for Education. There’s no indication whether the feature will be available in the GCC, GCC-High, or DoD tenants.

Consent Required

Using a Snapchat lens follows the same process as adding other effects to a meeting participant’s video feed. You can choose the lens before joining a meeting or during a meeting and enjoy the effect in preview before sharing it with others. The Snapchat Lenses are listed under a tab in the video effects section of video settings.

Like the video effects introduced by Microsoft in January 2023, a user must grant explicit consent to allow the Snapchat Lenses app to amend their video feed (Figure 2). This is an example of Teams resource specific consent (RSC) in action where an app receives consent to amend some but not all of the resources available to a user.

Granting user consent to the Snapchat Lenses app
Figure 2: Granting user consent to the Snapchat Lenses app

Once the app receives consent, the meeting participant can download and use any of the available lenses (24 at present). Lenses can combine with other effects, such as a background image or one of the styles or frames provided by Microsoft.

During a boring meeting, participants can wile away the minutes by experimenting with different lenses before settling on just the right one to make the best possible impression on their colleagues (Figure 3).

Snapchat Lenses gives a touch of class to a Teams meeting participant
Figure 3: Snapchat Lenses gives a touch of class to a Teams meeting participant

The Snapchat Lenses app is not available in the preview version of the Teams 2.1 client. It’s a good example of the kind of feature that isn’t needed to test new software that will be added before the client becomes generally available. The lack of the silly lenses might just be a reason to prefer the Teams 2.1 client, but I shall leave it to you to make your mind up on that subject.

Some in the Teams Community Will Relish Snapchat Lenses

In an example of the strange but backed up by a report statistics beloved by Microsoft, they assert that “video calls make up 78% of positive memories in meetings.” Whether having a giant mushroom perched on my head will enable me to create more positive memories in meetings is a research topic that remains to be explored. I have my doubts.

With over 280 million monthly active users, there’s enough room in the Teams user community for features like Snapshot Lenses. It’s not my style and I doubt that I shall ever use these effects after this brief experiment, but then again, I doubt that I am in the target group Microsoft is going after in the ongoing battle to match features already available in Zoom.


Make sure that you’re not surprised about changes that appear inside Office 365 applications by subscribing to the Office 365 for IT Pros eBook. Our monthly updates make sure that our subscribers stay informed.

✇Office 365 for IT Pros

Teams Introduces a Profanity Filter for Meetings

Teams Profanity Filter Looks for Obscene or Profane Words

When I read message center notification MC537415 (5 Apr 2023, Microsoft 365 roadmap item 113412) about the “newly introduced toggle to turn on/off profanity filtering in live captions” in Teams settings (Figure 1), I wondered about how much usage this feature will get. I can imagine that it will be popular and useful in education settings (hopefully, those running the meetings will take control if profanities abound), but the corporate world is slightly more robust.

Setting the Teams profanity filter to On
Figure 1: Setting the Teams profanity filter to On

Deployment of the profanity toggle started to targeted release tenants in early April. After completing this phase, standard release tenants will see the feature in early May. Full deployment to commercial and GCC tenants should be complete by mid-May. GCC High and DoD tenants should see it in mid-July.

Filter Inserts Masks for Bad Words

The profanity toggle controls whether Teams inserts ***** masks when the transcription of a meeting to generate live captions detects that a spoken word is profane (Figure 2). In this respect, I believe that Teams looks for words deemed to be vulgar or obscene rather than irrelevant or unsanctified.

The effect of the Teams profanity filter
Figure 2: The effect of the Teams profanity filter

Some corporate executives I have direct experience of, including some at Microsoft, were prone to dropping a few f-bombs during meetings to emphasize a point or stress just how they felt about a discussion. This is the kind of behavior that I think Teams will seek to filter out.

If you don’t turn the toggle on, you see every word Teams generates for a caption. This is the default, so you need to turn the toggle on if you think that you’re in danger of being offended by seeing a profane caption. Of course, if you’re listening to the meeting, you’ll hear the objectionable term in its full glory because Teams doesn’t filter the audio feed.

Factors Affecting Detection

Another thing to consider is that the generation of live captions depends on the transcription engine being able to recognize words. When seeking to identify profanities, the engine must first recognize the word and then determine it to be profane. Quite how this process will deal with local accents, argots, and slang remains to be seen. My experience when testing the Teams profanity filter was that it detected some words and ignored others. Your mileage might vary depending on the clarity of enunciation by meeting participants and quality of microphones. A whispered expletive is unlikely to be picked up by live captions.

A further challenge exists for live translated captions (one of the four features moved to Teams premium in January 2023). I do not know how effective the profanity filter will be in a meeting where participant contributions are in multiple languages or if the filter will be able to handle concurrent translation of profanities from multiple languages. That would be an interesting test to run.

Improvements for Live Captions

MC538737 (April 8) notes that users will be able to choose colors, height, position (left or bottom) and font size for live captions. There’s no facility to highlight profanities in a different color. This update will roll out in mid-May 2023.

Personal Choice

Opting to use the Teams profanity filter is very much a personal choice. Some won’t care at all if someone’s contribution is on the edge while others will be very offended at terms that some consider unremarkable. There’s no way to set the control programmatically with PowerShell or the Graph that I can see to allow administrators to enable the filter for users. Maybe it’s best to leave this option for individuals to make up their own mind.


Support the work of the Office 365 for IT Pros team by subscribing to the Office 365 for IT Pros eBook. Your support pays for the time we need to track, analyze, and document the changing world of Microsoft 365 and Office 365.

✇Office 365 for IT Pros

Microsoft Releases Cmdlet to Retrieve Disposition Review Items

Export Details of Disposition Review Items

Message Center notification MC521457 (Microsoft 365 roadmap item 106102) might have passed you buy on February 27 when Microsoft announced a new PowerShell cmdlet for disposition review. Relatively few people are concerned with Microsoft Purview Data Lifecycle Management to care that a new cmdlet is available to export (not just “to support”) disposition review items, so it’s entirely natural that you might have gone on to read about other announcements occurring around the same time, like Exchange Online’s improved message recall feature.

Roll-out of the new Get-ReviewItems cmdlet is now complete. The cmdlet is available after loading the latest version of the Exchange Online management module.

Disposition Items

Microsoft 365 retention labels often result in the deletion of items after the lapse of their retention periods. This is enough for most organizations, but those that want oversight over the final processing of selected items can configure retention labels to invoke a disposition review, part of the Microsoft Purview records management solution. Disposition reviews are often used to retain messages and documentations such as those for project documentation until the organization is absolutely sure that it’s safe to remove individual items.

Using a disposition review with retention labels requires advanced licenses, like Office 365 E5. An organization can put items through a single-stage or multi-stage review (Figure1) leading to final deletion, retention for another period, or assignment of a new retention label. The reviewers who decide on the disposition of content are selected by the organization because they have the expertise and experience to know if items are still needed or can progress to final disposition. It’s also possible to configure a custom automated disposition process using Power Automate.

Viewing disposition review items for a retention label
Figure 1: Viewing disposition review items for a retention label

Exporting Disposition Review Items

The Get-ReviewItems cmdlet doesn’t affect disposition outcomes. It’s a utility cmdlet to export details of disposition review items for a specific retention label in a pending or disposed (processed) state. The reason why the cmdlet exists is that the Purview GUI (Figure 1) supports export of up to 50,000 items. Although it’s unlikely that an organization will have more than 50,000 items awaiting disposition review, it is possible that they might have more than 50,000 disposed (processed) items. The Get-ReviewItems cmdlet can export details of all those items.

Microsoft’s documentation for Get-ReviewItems includes examples of using the cmdlet. One in particular is noteworthy because it explains how to fetch pages of review items until all items have been recovered. Fetching pages of data is common practice in the Graph API world and it’s done to reduce the strain on the service imposed if administrators requested very large numbers of items at one time.

I expanded the example to create a report of all disposition review items for a tenant (all items for all retention labels with a disposition review). Here’s the code:

Connect-IPPSSession

[array]$ReviewTags = Get-ComplianceTag | Where-Object {$_.IsReviewTag -eq $True} | Sort-Object Name
If (!($ReviewTags)) { Write-Host "No retention tags with manual disposition found - exiting"; break }

Write-Host ("Looking for Review Items for {0} retention tags: {1}" -f $ReviewTags.count, ($ReviewTags.Name -join ", "))

$Report = [System.Collections.Generic.List[Object]]::new() 

[array]$ItemsForReport = $Null
ForEach ($ReviewTag in $ReviewTags) {
 Write-Host ("Processing disposition items for the {0} label" -f $ReviewTag.Name)
 [array]$ItemDetails = $Null; [array]$ItemDetailsExport = $Null
 # Fetch first page of review items for the tag and extract the items to an array
 [array]$ReviewItems = Get-ReviewItems -TargetLabelId $ReviewTag.ImmutableId -IncludeHeaders $True -Disposed $False  
 $ItemDetails += $ReviewItems.ExportItems
 # If more pages of data are available, fetch them and add to the Item details array
 While (![string]::IsNullOrEmpty($ReviewItems.PaginationCookie))
 {
    $ReviewItems = Get-ReviewItems -TargetLabelId $ReviewTag.ImmutableId -IncludeHeaders $True -PagingCookie $ReviewItems.PaginationCookie
    $ItemDetails += $ReviewItems.ExportItems
 }
 # Convert data from CSV
 If ($ItemDetails) {
   [array]$ItemDetailsExport = $ItemDetails | ConvertFrom-Csv -Header $ReviewItems.Headers 
   ForEach ($Item in $ItemDetailsExport) {
     # Sometimes the data doesn't include the label name, so we add the label name to be sure
     $Item | Add-Member -NotePropertyName Label -NotePropertyValue $ReviewTag.Name }
   $ItemsForReport += $ItemDetailsExport
 }
}

ForEach ($Record in $ItemsForReport) {
  If ($Record.ItemCreationTime) {
   $RecordCreationDate =  Get-Date($Record.ItemCreationTime) -format g 
  } Else {
   $RecordCreationDate = "Unknown" }
 
   $DataLine  = [PSCustomObject] @{
     TimeStamp       = $RecordCreationDate
     Subject         = $Record.Subject
     Label           = $Record.Label
     AppliedBy       = $Record.LabelAppliedBy
     RecordType      = $Record.RecordType
     'Last Reviewed' = Get-Date($Record.ItemLastModifiedTime) -format g
     'Review Action' = $Record.ReviewAction
     Comment         = $Record.Comment
     'Deleted Date'  = $Record.DeletedDate
     Author          = $Record.Author
     Link            = $Record.InternetMessageId
     Location        = $Record.Location
   } 
   $Report.Add($DataLine)
}

Everything works – until you meet an item with a comma in its subject or the comment captured when a reviewer decides upon a disposition outcome. After discussing the issue with Microsoft, its root cause is that the export is in CSV format and the comma in these fields causes problems when converting from CSV format. Microsoft is working on a fix which might be present as you read this.

The Lesson of Export

The Get-ReviewItems cmdlet will be a useful tool for those involved in disposition processing. They can extract details of items and report that information in whatever way they wish. The comma issue proves that documentation is not always perfect. It’s important to test examples to make sure that they work as they should.


Insight like this doesn’t come easily. You’ve got to know the technology and understand how to look behind the scenes. Benefit from the knowledge and experience of the Office 365 for IT Pros team by subscribing to the best eBook covering Office 365 and the wider Microsoft 365 ecosystem.

✇Office 365 for IT Pros

Why Some Outlook Clients Encrypt Outbound Messages Differently

Outlook Sensitivity Labels Processed in Different Ways

An observant reader noticed that Outlook clients encrypt messages using sensitivity labels in different ways. If you look at Figure 1, you see three messages sent to the same person using Outlook Mobile, OWA (or Monarch), and Outlook for Windows. The Ultra Confidential sensitivity label protects all messages with encryption, but only the copy sent from Outlook for Windows is protected in the sender’s mailbox. The other copies sent from Outlook Mobile and OWA are protected when they arrive in the recipient mailbox.

Outlook lists three messages from different clients with different outcomes from Outlook sensitivity labels
Figure 1: Outlook lists three messages from different clients

The obvious question is why this situation happens. Shouldn’t all Outlook clients produce the same result? Alas, this is not the case. As explained in Microsoft documentation, “When a sensitivity label is configured with encryption, the encryption process depends on the client platform.” In effect, Outlook desktop is the only client that contains the code necessary to encrypt an outbound message.

Other Outlook clients rely on passing messages through the Exchange Online transport service. The transport service has super-user capabilities and can apply the necessary protection. When transport detects that a message has a sensitivity label with encryption that isn’t yet protected, it does the necessary work to protect the message by placing the message and its attachments in a rpmsg “wrapper” before sending the message on to the next hop in its journey.

Client Processing for Protected Messages

The rpmsg wrapper is how Outlook sensitivity labels impose rights management for protected messages. The receiving client must unpack the message from the wrapper and respect the rights assigned to the recipient by the publishing license that’s included in the wrapper. The receiving client sends the publishing license to the information protection service to obtain a use license that allows the client to open the message.

Clients perform the processing to allow users to read protected messages without being prompted for credentials. If the client can’t obtain a use license, it displays information from the rpmsg to direct the user to the Office 365 Message Encryption (OME) Portal. If the user can prove their rights to open the message by signing into the OME portal with an account included in the recipient list, they can view the message contents online.

The reason why two out of the three messages are unencrypted in the Sent Items folder is that these are the messages that clients didn’t protect. Outlook desktop protected the other message before it submitted the item to transport. In

all cases, the sender can be confident that the message was fully protected when it left the transport service for onward routing.

Clients and the MIP SDK

Microsoft could incorporate the code (using the Microsoft Information Protection SDK) to protect messages in OWA and Outlook mobile. However, this approach doesn’t seem to make sense. Apart from the extra complexity introduced into the client code base, OWA can only be used online. Outlook mobile clients could protect files, but they usually work in a connected mode (either Wi-Fi or a cellular network). Outlook desktop has always been able to work offline, so its developers incorporated the code to process protected inbound and outbound messages when working offline.

Growing Use of Outlook Sensitivity Labels

The number of messages protected by Outlook sensitivity labels is steadily increasing. I do not have firm data to back this assertion, just anecdotal evidence from customer interactions. Microsoft continues to pour engineering effort into making sensitivity labels more accessible and useful, so I expect the trend to continue. And when your tenant starts to use sensitivity labels to protect email, you’ll know why some Outlook clients protect messages in a different manner to others.


Learn about using Exchange Online, Outlook clients, and the rest of Office 365 by subscribing to the Office 365 for IT Pros eBook. Use our experience to understand what’s important and how best to protect your tenant.

✇Office 365 for IT Pros

Generate a HTML Report of Managers and Direct Reports with the Graph SDK

Creating a Report From Azure AD Manager and Direct Reports Data with PowerShell

It’s always good to be able to build on the knowledge contributed by someone else. This brings me to a post by Vasil Michev, the esteemed technical editor for the Office 365 for IT Pros eBook. The post covers how to Create an All Managers group in Microsoft 365 and covers how to do this in different ways for different types of group. It brought back some memories of Microsoft’s initiative in April 2017 to auto-generate a Microsoft 365 group for every manager with its membership populated with the manager’s direct report.

Retrieving Azure AD Manager and Direct Reports

In any case, Vasil discussed how the Get-Recipient (but not Get­ExoRecipient) and Get-User cmdlets have a filter to find accounts that have direct reports using the backlink from users to their managers. By definition, these accounts are managers, so you can use the commands as the basis to control the membership of distribution lists, dynamic distribution lists, or Microsoft 365 groups.

Get-Recipient -Filter {DirectReports -ne $Null}
Get-User -Filter {DirectReports -ne $Null}

The only problem is that the output of the two cmdlets is imperfect. The cmdlets find accounts with direct reports, but their results include some accounts that don’t have any direct reports. In my tenant, I found that the cmdlets found three accounts with no direct reports. I believe that these accounts had direct reports at some point in the past, but they don’t now. For instance, when I queried the accounts to see the set of direct reports reported by Get-User, I see a blank:

Get-User -Identity Ben.Owens | Select-Object Name, Manager, DirectReports

Name      Manager      DirectReports
----      -------      -------------
Ben Owens tony.redmond {}

The same is true when viewing details of the account through Exchange address lists, the organization chart in Teams, or the Outlook Org Explorer (Figure 1).

Outlook Org Explorer lists no direct reports for a manager
Figure 1: Outlook Org Explorer lists no direct reports for a manager

According to message center notification MC492902 (updated 7 February 2023), the Outlook Org Explorer is only available to users with the “Microsoft Viva Suite” or “Microsoft Viva Suite with Glint” licenses, which is why you might not be seeing it. Originally, Microsoft said that the Org Explorer would be available to accounts with Microsoft 365 E3/E5 or Microsoft 365 Business licenses, but they decided to align this feature with the Viva initiative. The Org Explorer is not available for OWA.

My conclusion is that synchronization between Azure AD and Exchange Online leaves some vestige behind in the DirectReports property following the removal of the last direct report for a manager. It’s enough to stop the filter working accurately.

Reporting Azure AD Managers and Direct Reports

Which brings me back to considering how to report the links between managers and employees using the information stored in Azure AD. I covered this ground in an article two years ago, but I didn’t realize the flaw in Get-User at the time, so the script I wrote (available from GitHub) can produce incorrect results. A different approach is needed.

Given that Azure AD is the source of the information, it makes sense to use Graph APIs to retrieve data. I chose to use the Microsoft Graph PowerShell SDK to avoid the necessity to create a registered app.

The new script (also available from GitHub) does the following:

  • Finds user accounts with at least one assigned license. This step filters out accounts created for purposes like room and shared mailboxes.
  • Use the Get-MgUserManager cmdlet to check each account to see if it has a manager. If not, note this fact.
  • Use the Get-MgUserDirectReport cmdlet to see if the account has direct reports. If it does, record the details of the manager’s reports.
  • Create an HTML report detailing each manager and their reports.
  • At the end of the report, add a section detailing accounts without managers.
  • Output the HTML file and a CSV file containing details of managers and reports.

Figure 2 shows some example output. Because the code is PowerShell, it’s easy to tweak it to include other information about each employee.

Reporting managers and their direct reports

Azure AD Managers
Figure 2: Reporting managers and their direct reports

Go to the Source to Find Azure AD Managers and Direct Reports

It’s never nice to discover that a technique you thought worked well is no longer fit for purpose and it’s necessary to rework a script. The Get-User and Get-Recipient cmdlets return accurate information about managers and direct reports, but only if managers always have at least one report. I guess that’s possible, but it’s better to make sure by using Graph APIs to retrieve data about managers and their direct reports. At least then you’ll know that your reports show the same reporting relationships that surface elsewhere in Microsoft 365.


Support the work of the Office 365 for IT Pros team by subscribing to the Office 365 for IT Pros eBook. Your support pays for the time we need to track, analyze, and document the changing world of Microsoft 365 and Office 365.

✇Office 365 for IT Pros

Microsoft Limits Graph API Requests for User Account Data

Old Limit with SignInActivity was 999 – New Limit for Azure AD Accounts is 120

Because it retrieves details of Azure AD accounts, the List Users API is one of the most heavily used of the Microsoft Graph APIs. It also underpins the Get-MgUser cmdlet from the Microsoft Graph PowerShell SDK. Microsoft generates the cmdlet from the API using a process called AutoRest, which means that changes made to the API show up soon afterward in the cmdlet.

I’ve documented some of the issues that developers must deal with when coding with the cmdlets from the Microsoft Graph PowerShell SDK. The cmdlets have been stable recently, which is a relief because tenants are migrating scripts from the Azure AD and MSOL modules. However, last week an issue erupted in a GitHub discussion that caused a lot of disruption.

In a nutshell, if you use List Users to fetch Azure AD accounts and include the SignInActivity property, the API limits the page size for results to 120 items. Calls made without specifying SignInActivity can set the page size to be anything up to 999 items.

An Unannounced Change

To help manage demand on the service, all Graph API requests limit the number of items that they return. To retrieve all matching items for a request, developers must fetch pages of results until nothing remains. When a developer knows that large numbers of items must be fetched, they often increase the page size to reduce the number of requests.

Microsoft didn’t say anything about the new restriction on requests that fetch Azure AD account data with sign-in activity. Developers only discovered the problem when programs and scripts failed. I first learned of the issue when some of the users of the Office 365 for IT Pros GitHub repository reported that a Graph request which included a $top query parameter to increase the page size to 999 items failed. For example:

$uri = "https://graph.microsoft.com/beta/users?`$select=displayName,userPrincipalName,mail,id,CreatedDateTime,signInActivity,UserType&`$top=999"
[array]$Data = Invoke-RestMethod -Method GET -Uri $Uri -ContentType "application/json" -Headers $Headers
Invoke-RestMethod : The remote server returned an error: (400) Bad Request.
At line:1 char:16
+ ... ray]$Data = Invoke-RestMethod -Method GET -Uri $Uri -ContentType "app ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest)
   [Invoke-RestMethod], WebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.I

As shown in Figure 2, testing with the Get-MgUser cmdlet revealed some more information in the error (“Cannot query data for more than 120 users at a time”). This was the first time I learned about a query limit:

Get-MgUser reports more useful error information

Cannot query data for more than 120 users at a time (SignInActivity)
Figure 2: Get-MgUser reports more useful error information

According to a response reported in the GitHub discussion, Microsoft support reported

The PG have confirmed that this endpoint will be transitioning from beta to General Availability (GA).

As part of this transition, changes to its behavior has been made, this includes not requesting more than 120 results per call. They recommend requesting less than 120 results per call, which can be done by setting the top parameter to, say 100.”

It’s likely that Microsoft made the change because retrieving sign-in activity data for Azure AD accounts is an expensive operation. Reducing the page size to 120 possibly makes it easier to process a request than if it asked for 999 items.

Beta Version of List Users Moving to Production

When the product group (PG) says that the endpoint is transitioning from beta to GA, it means that instead of needing to use https://graph.microsoft.com/beta/users to access sign-in activity, the data will be available through https://graph.microsoft.com/V1.0/users. If you use the Microsoft Graph PowerShell SDK, you won’t have to run the Select-MgProfile cmdlet to choose the beta endpoint. Moving the beta version of the API to the production endpoint is a good thing because there are many other account properties now only available through the beta endpoint (like license assignments).

If you use the Microsoft Graph PowerShell SDK, the Get-MgUser cmdlet is unaffected by the change if you specify the All parameter. This is because the cmdlet handles pagination internally and fetches all pages automatically without the need to specify a page size. For instance, this works:

$AccountProperties = @( ‘Id’, ‘DisplayName’, ‘SignInActivity’)
[array]$Users = Get-MgUser -All -Property $AccountProperties | Select-Object $AccountProperties

Moving to Production

Although it’s good that Microsoft is (slowly) moving the beta versions of the List Users API towards production, it’s a pity that they introduced a change that broke so many scripts and programs without any warning. At worse, this so exhibits a certain contempt for the developer community. At best, it’s a bad sign when communication with the developer community is not a priority. That’s just sad.


Insight like this doesn’t come easily. You’ve got to know the technology and understand how to look behind the scenes. Benefit from the knowledge and experience of the Office 365 for IT Pros team by subscribing to the best eBook covering Office 365 and the wider Microsoft 365 ecosystem.

✇Office 365 for IT Pros

Time Running Out for Azure AD and MSOL PowerShell Modules

Last Gasp for Azure AD PowerShell Deprecation as June Deadline Approaches

Microsoft’s original announcement about the deprecation of the Azure AD and Microsoft Online Services (MSOL) PowerShell modules goes back to 26 August, 2021. At that time, Microsoft wanted to have the retirement done by June 30, 2022. Customer pushback duly ensued and Microsoft decided to push the dates out another year to allow customers more time to upgrade their scripts.

This was the only sensible course of action. The Graph APIs for dealing with many Azure AD account interactions, especially license assignments, were sadly undocumented. The suggestion of using cmdlets from the Microsoft Graph PowerShell SDK ran into difficulties because the production version (V1.0) of cmdlets like Get-MgUser didn’t return license information. Allied to that, the documentation for the SDK cmdlets remains poor and inscrutable at times.

Time Helped Improve the Situation

Time is a great healer and allows for improvements to be made. The Graph Explorer works better and the Graph X-Ray tool reveals details about how Microsoft uses Graph calls in places like the Azure AD admin center (or rather, the Microsoft Entra admin center).

In addition, Microsoft developed documentation to help people migrate scripts, including a cmdlet map to translate old cmdlets to new. The important thing to realize here is that automatic translation from one set of cmdlets to the other is difficult. People code in PowerShell in different ways and it’s not always clear how to translate code to a new cmdlet. Some community-based projects do exist (here’s a new one that is spinning up), but any attempt to covert to SDK cmdlets must take the SDK foibles into consideration, like its fundamental disregard for the PowerShell pipeline.

But mostly time allowed people to share their knowledge about how to use SDK cmdlets to automate administrative tasks like user and group management. For instance, here’s a writeup I did about license management for Azure AD accounts using the SDK, and here’s another covering how to create a license report for Azure AD accounts.

What Will Happen Between Now and June 30, 2023

But time eventually runs out and we are now at the point where Microsoft is progressing the retirement of the Azure AD and MSOL modules. Here’s my understanding of the situation based on some discussions with Microsoft:

  • The licensing cmdlets from the Azure AD and MSOL modules do not work for tenants created after November 1, 2022. These tenants must use Graph APIs or SDK cmdlets to manage license assignments for Azure AD accounts.
  • For all tenants, March 31, 2023, marked the official retirement date for the licensing cmdlets in the Azure AD and MSOL modules.
  • Retirement doesn’t mean “stop working on March 31.” Instead, Microsoft now throttles cmdlets that assign licenses to Azure AD accounts so that they’re not as responsive as before. This is in line with the warning posted on July 29, 2022, that “Customers may notice performance delays as we approach the retirement deadline,” The affected cmdlets are:
    • Set-MsolUserLicenseSet-AzureADUserLicense
    • New-MsolUser (where the creation of an account includes a license assignment)
The Set-AzureADUserLicense cmdlet will stop working before June 30, 2023

Azure AD PowerShell deprecation
Figure 1: The Set-AzureADUserLicense cmdlet will stop working before June 30, 2023
  • From now on, Microsoft will increase the throttling rate to make the licensing cmdlets less attractive. Shortly, Microsoft will initiate short outages to gauge the effect of stopping the cmdlets completely. Doing this allows Microsoft to understand if any major pain is caused to customers.
  • Before or on June 30, 2023, the licensing cmdlets “will no longer receive a successful response.” In other words, no throttling, no short delays, just nothing. The exact date when the shut-off happens depends on the information Microsoft gains about customer usage. What’s for sure is that the licensing cmdlets in the Azure AD and MSOL modules will stop working soon.
  • After June 30, 2023, the Azure AD and MSOL modules are unsupported. Cmdlets may still run, but no guarantees exist that they will be successful. Given that the modules have been around for many years, you could anticipate that the cmdlets that don’t interact with the Microsoft 365 licensing platform will be OK. You might be right, but you don’t know how long that state will last because the modules are officially retired.

The Bottom Line About Azure AD PowerShell Deprecation

The Azure AD and MSOL modules are now on borrowed time. If you haven’t already started to upgrade scripts to use the Graph APIs or the Microsoft Graph PowerShell SDK, scripts that use these modules could encounter an unpleasant failure very soon. It’s time to get busy to make sure that all scripts can run after June 30, 2023.


Stay updated with developments across the Microsoft 365 ecosystem by subscribing to the Office 365 for IT Pros eBook. We do the research to make sure that our readers understand the technology.

✇Office 365 for IT Pros

Office 365 for IT Pros April 2023 Update Available

Files for Monthly Update #94 for the Most Comprehensive Office 365 Book Available for Download

Office 365 for IT Pros 2023 edition

The Office 365 for IT Pros team is delighted to announce the availability of monthly update #94. The files for the April 2023 update are now available from Gumroad.com and Amazon Kindle. Details of the changes made to individual chapters are available in our change log.  We’d appreciate if subscribers download and use the updated content because a lot has changed over the last few months and it would be a pity to refer to old information after it has been updated. You can always access the latest files through your Gumroad account or by using the link in your original receipt. See our FAQ for more information.

Major Microsoft Announcements in March

March 2023 featured several major Microsoft announcements that will affect Microsoft 365 operations over the coming years. The most important announcements are:

  • Microsoft 365 Copilot: We don’t expect to see this in production until much later in the year, perhaps after the Ignite conference. No details are available about licensing. The Security Copilot announcement might also affect how Microsoft 365 organizations work in the future. There’s a lot of hype around artificial intelligence and machine learning at present, and we plan to take a pragmatic approach to assessing how the technology works when exposed to the rigors of day-to-day operations.
  • The Loop app: Now in public preview, but Microsoft must resolve important issues like compliance and eDiscovery before general availability. Loop components are already available in OWA, Teams, Outlook desktop, and the Office web apps. The biggest issue we have with Loop technology is that it’s very inward-focused and currently doesn’t support collaboration with external people.
  • The Teams 2.1 desktop client is now available in public preview. Many features work in the public preview but some major chunks of functionality are missing (like breakout rooms).
  • The plan to block email from unsupported on-premises Exchange servers. Starting initially with Exchange 2007 servers in hybrid organizations, this plan will evolve to bring all Exchange on-premises servers into scope. Our recommendation is that hybrid organizations should eliminate unsupported Exchange servers from their roster as soon as possible.

We mention these changes in the current edition of the Office 365 for IT Pros eBook. However, there’s not much that we can say at this point about the operational and practical aspects of these technologies as they’re either incomplete or unavailable. We will keep a close eye on what happens and incorporate the information into future Office 365 for IT Pros updates as time goes by.

Other Changes

Alongside these important topics, day-to-day change continued unabated. Among the changes are:

We can only predict that a similar batch of changes will appear in April.

On to the 2024 Edition

The Office 365 for IT Pros eBook first appeared in 2015. We even had a print version then, something that’s impossible now given the volume and type of change that happens monthly. The size of the book is also a challenge for on-demand print runs, most of which are designed to cater for much smaller books (like novels). We moved to annual editions in 2016 and the current version is the ninth in the series.

We’ve started work on the tenth (2024) edition. If all goes well, we will deliver the new edition on July 1, 2023. We issue new editions on July 1 because it aligns with the start of the Microsoft fiscal year. We hope that our subscribers will stay with us for another year when the 2024 edition is available. Meanwhile, on to update #95 as we continue to improve the 2023 edition.

✇Office 365 for IT Pros

Not a Rant About Microsoft’s Plan to Stop Old Exchange Servers Sending Email to Exchange Online

Clarifying Why Some Unsupported Exchange Servers Need an Upgrade

Yesterday, I was walking the dog and listening to the March 29 edition of the Windows Weekly podcast featuring Paul Thurrott and Richard Campbell. Typically, I listen to pass time without needing to engage my brain too highly, but then Richard mentioned that I could deliver a good “half-hour of rant” about Microsoft’s grand plan to force customers to upgrade unsupported Exchange servers.

I can’t deny that I have been known to rant in the past, maybe even when hosted by Richard on his RunAs Radio talk show, but that’s when I am pointed to a microphone and Richard goads me into action. In this case, I think it might be a reflection that people are struggling to understand what’s going on. Certainly, a fair degree of miscomprehension is apparent in some of the comments posted to Microsoft’s announcement. Let me try to summarize what’s happening without ranting even a little bit.

What Microsoft is Doing with Unsupported Exchange Servers

First, Microsoft is not targeting every on-premises Exchange server. You can absolutely continue to run on-premises Exchange if that’s the best option for your organization. However, if you have a hybrid organization, the rules of the game are changing to force you to use supported software to send email from the on-premises side.

Initially, Microsoft is targeting on-premises Exchange servers with two characteristics:

  • The servers run unsupported software. Any Exchange 2007 or Exchange 2010 server is now unsupported. Exchange 2013 servers become unsupported on April 11, 2023.
  • The servers send email to Exchange Online over an inbound connector of the on-premises type. In other words, the problem servers act as the routing point of contact with Exchange Online – Microsoft knows about the servers because they’re part of a hybrid organization connected to Exchange Online. These servers are also connected to the internet (otherwise they can’t route email to Exchange Online) and are therefore vulnerable to attack, and because they route messages direct to Exchange Online, they can be the vector used by attackers to inject malware into Exchange Online.

Servers that do not handle the transmission of email to Exchange Online via an inbound connector are unaffected. Anything that happens inside the privacy of an on-premises organization is up its administrators. For now, you could even connect in some Exchange 5.5 servers running a Wolfpack cluster if you wanted – if the server handling email to Exchange Online runs supported software.

Microsoft says that “The enforcement system will eventually apply to all versions of Exchange Server and all email coming into Exchange Online.” This seems a little harsh but it is intended to make sure that email flowing into Exchange Online is safe. The way things seem likely to pan out is that Microsoft will gradually bring Exchange 2010, Exchange 2013, Exchange 2016, and Exchange 2019 into the program. After they’ve made sure that only Exchange servers running supported software can communicate with Exchange Online, Microsoft will extend the requirement to all Exchange servers that communicate with Exchange Online using any means. In other words, even servers that communicate with Exchange Online via an intermediary are subject to throttling and then blocking.

The final stage is to protect Exchange Online against any server that sends email to Exchange Online over SMTP. I’m not quite sure how Microsoft plans to validate that remote SMTP servers are up to scratch, but that’s where they seem to be heading. This part of the plan is likely more of a long-term strategy than a well-defined plan. Practical issues such as identifying what is and is not a supported version of any particular SMTP server that communicates with Exchange Online need to be resolved.

The end game is to ensure that Exchange Online is not exposed to malware or other issues that come in from external servers (outside Exchange Online). In many respects, this is no different to what happens today when Exchange Online Protection blocks spam and malware. Judgement is passed at a server level rather than individual messages.

Initial Focus on Exchange 2007

The initial focus is on Exchange 2007 servers (Figure 1). As you might expect, this is a very small subset of servers in hybrid organizations. I’ve heard that there might be a couple of thousand servers in this category worldwide. Exchange 2007 reached end of life six years ago (April 2017). It has not received any support or security patches since.

These servers are vulnerable to a wide range of known threats. They should not be in active use. The potential exists that an attacker could compromise these servers and use this route to attempt to penetrate Exchange Online. This is the crux of the matter: Exchange Online will not accept email from organizations that transmit email to Exchange Online using obsolete and vulnerable Exchange servers.

Exchange 2007 run in a world where less external threat existed

Unsupported exchange servers
Figure 1: Exchange 2007 run in a world where less external threat existed. Now it’s an unsupported Exchange Server

Blocking of Unsupported Exchange Servers Starts in July

Microsoft will use a three-phase report-throttle-block process to “encourage” customers to upgrade the problem servers. Details are in this article. Microsoft will start to throttle traffic from Exchange 2007 servers in June and move to block traffic from those servers in July. It is entirely the responsibility of tenant administrators to respond before a block descends on their on-premises email to Exchange Online. Three options are available:

  • Upgrade the problem server(s) to a supported version of Exchange Server (2016 or later, patched with the latest cumulative and security updates). This might involve replacement hardware. The load imposed by mail routing to Exchange Online is not likely to stress modern hardware, so a low-end server will suffice.
  • Move the on-premises side of the inbound connector to a server running a supported version of Exchange Server.
  • Direct email from Exchange on-premises to Exchange Online via a third-party mail gateway. (note: if the third-party gateway uses unsupported Exchange servers, its traffic is liable to be blocked).

In any of these cases, it makes absolutely no sense to keep vulnerable Exchange servers in production. It’s time to let Exchange 2007 die. Software designed twenty years ago simply cannot cope with the threat that exists today.

Microsoft is clear that Exchange 2007 is only the start. After they finish dealing with Exchange 2007, they will move on to Exchange 2010 and then Exchange 2013 servers that send email to Exchange Online over inbound connectors. It’s probable that the program will extend to Exchange 2016 and Exchange 2019 servers (that are not kept updated) as they age, and maybe even encompass third-party servers with known problem configurations.

The point is that the project is all about closing a potential attack vector into Microsoft 365. Just like stopping people using basic authentication to connect to Exchange Online (now almost done), this is the right thing to do.

Nothing to do with Consumer Email

Some reaction to the announcement focuses on spam generated from Microsoft cloud accounts. I believe this refers to consumer email accounts. At least one incident occurred where Exchange Online was hijacked and used for spam, but most spam does come from consumer accounts. Microsoft could tighten the use of consumer (Outlook.com) accounts for email, but that’s got nothing to do with the server initiative.

ISVs and Inbound Connectors

Speaking of inbound connectors, in February 2023 Microsoft disabled the ability of new Exchange Online tenants to activate inbound connectors of the on-premises type. This caused a bunch of problems for ISVs that depend on being able to route email for processing to a service that they run before sending messages back to Exchange Online for final delivery. The application of email signatures by a company like Code Two Software is a good example.

Microsoft has now issued guidance about how to handle the issue. Essentially, they have whitelisted some ISVs to reduce the friction caused by the restriction. In other cases, you’ll need to request activation through Microsoft support. According to the ISVs I have spoken with, the new scheme is acceptable. Let’s hope that this proves to be the case in practice.

Microsoft will hold an Ask Me Anything event on May 10 at 9AM PST on the topic of the Exchange Online transport enforcement system. For more details, check out this page. If you have any further questions, that’s the place to bring them.


Insight like this doesn’t come easily. You’ve got to know the technology and understand how to look behind the scenes. Benefit from the knowledge and experience of the Office 365 for IT Pros team by subscribing to the best eBook covering Office 365 and the wider Microsoft 365 ecosystem.

✇Office 365 for IT Pros

How the Request Files Feature Works in SharePoint Online

Similar but Different to Request Files in OneDrive for Business

In January 2020, I wrote about the feature that allows OneDrive for Business users to ask people to upload files to a folder. Time moves on and message center MC495329 (7 January 2023) announced the arrival of a similar feature for SharePoint Online document libraries. According to Microsoft 365 roadmap it 103625, rollout started in February. It’s taken a while for it to show up in my tenant, or maybe I just haven’t looked hard enough.

In any case, Microsoft says that the feature is “an easy and secure way to request and obtain files from anyone.” Essentially, you select a folder in a document library that you want to use as a target for uploads. You then create a request files link that you give to the people who have the information you want. For instance, these might be professional advisors working on some documents relating to a project. They use the link to upload the files to the target folder, which site members can then interact with as normal.

Any site member can generate a link by selecting the target folder and choosing the Request files option from the […] menu. SharePoint Online generates a link (Figure 1), which the user can share using whatever method they like.

SharePoint Online creates a Request Files link
Figure 1: SharePoint Online creates a Request Files link

People who upload files don’t have any visibility into site contents and can’t see the files once they upload them to the site. This is a one-way transmission.

Getting SharePoint Online Ready for Request Files

The support documentation for the Request Files feature is available online. I don’t intend to repeat it here. However, some points from the feature documentation deserve emphasis.

First, the Request Files feature depends on Anyone sharing links. If your tenant doesn’t allow people to create Anyone links, they won’t be able to request external people to upload files to a folder. The permissions allowed for the link must include upload rather than just view and edit.

Second, Microsoft checks if Anyone links are enabled in a tenant when they deploy the software update for the Request files feature. If the tenant allows Anyone links, Microsoft enables all sites to support the feature. Originally, my tenant blocked Anyone links, which meant that the default condition applied (disabled) for all sites. After enabling Anyone links, I had to explicitly enable Request files for sites to make the option available.

Other restrictions can interfere with the ability of users to create Request Files links. For example, if you apply the file download block policy to a site, the option to request a link is unavailable.

Apart from enabling Anyone links (through the SharePoint Online admin center), control over how the Request files work is via PowerShell. The Set-SPOTenant cmdlet enables or disables the feature across the entire tenant. This command makes sure that the feature is enabled for the tenant and sets the expiration for request files links to seven days:

Set-SPOTenant -CoreRequestFilesLinkEnabled $False -CoreRequestFilesLinkExpirationInDays 7

While this command disables the feature for a specific site:

$SiteURL = "https://office365itpros.sharepoint.com/sites/SecureSite"
Set-SPOSite -Identity $SiteURL -RequestFilesLinkEnabled $False 

To check the site settings, run:

Get-SPOSite -Identity $SiteURL -Detailed | Select-Object Request*

RequestFilesLinkEnabled RequestFilesLinkExpirationInDays
----------------------- --------------------------------
                  False                                7

Like any change to SharePoint Online settings, it can take up to a day before updates are effective.

By default, the site inherits the value for the link expiration setting from the tenant configuration, but you can define a more restrictive expiration period if you like. You can’t override the tenant configuration and define a less restrictive expiration period for a site. The link expiration period can be anything from 0 (zero) to 730 days (two years). Usually, the more secure the site, the lower the link expiration period.

OneDrive for Business Settings

As noted above, OneDrive for Business also supports the Request Files feature. The OneDriveRequestFilesLinkEnabled setting in the tenant configuration controls if the feature is available in OneDrive for Business accounts while the OneDriveRequestFilesLinkExpirationInDays sets the expiration period for the sharing links. You can’t prohibit Request Files for selected OneDrive for Business accounts. The feature is either enabled or disabled for all.

Set-SPOTenant -OneDriveRequestFilesLinkEnabled $True –OneDriveRequestFilesLinkExpirationInDays 7

Using Request Files

When someone uses a Request Files link, SharePoint redirects them to a special page where they can select files to upload together with some personal details (First and Last Name) to let the requestor know who uploaded files to the folder (Figure 2).

Uploading files using a Files Request link
Figure 2: Uploading files using a Files Request link

The person who created the request files link receives email from SharePoint when someone uses the link to successfully upload files to the document library (Figure 3).

Email notification from SharePoint Online about newly uploaded files
Figure 3: Email notification from SharePoint Online about newly uploaded files

Figure 4 shows a set of files uploaded to a folder in a document library. SharePoint Online doesn’t validate the details of a person who uploads a file, so the name recorded as a prefix for the filename could be incorrect or false. That’s not important because it’s assumed that the person who requests file uploads will process whatever comes in afterward to decide what’s useful (or not), rename files, and so on.

 Files uploaded by external users to SharePoint Online
Figure 4: Files uploaded by external users to SharePoint Online

In terms of tracking the use of the Files Request feature, SharePoint Online captures when a link is used and a file is uploaded in the audit log. This PowerShell code finds the events for the last 14 days and reports them.

Connect-ExchangeOnline
[array]$Records = (Search-UnifiedAuditLog -StartDate (Get-Date).AddDays(-14) -EndDate (Get-Date) -Operations FileRequestUsed, FileUploaded -ResultSize 1000)
If (!($Records)) {Write-Host "No File upload records found - exiting" ; break}

$Report = [System.Collections.Generic.List[Object]]::new()
Write-Host "Processing" $Records.Count "audit records..."
ForEach ($Rec in $Records) {
  $AuditData = ConvertFrom-Json $Rec.Auditdata
  Switch ($AuditData.Operation) {
    "FileUploaded" {
       $FileName  = $AuditData.SourceFileName.SubString(7,($AuditData.SourceFileName.Length-7))
    }
    "FileRequestUsed" {
       $FileName = $Null 
    }
  } # End Switch
  $ReportLine = [PSCustomObject]@{
      TimeStamp    = Get-Date $AuditData.CreationTime -format g
      UploadedBy   = $AuditData.UserId
      Action       = $AuditData.Operation
      ClientIP     = $AuditData.ClientIP
      Folder       = $AuditData.SourceRelativeUrl.Split("/")[1] 
      FileName     = $FileName
      SiteURL      = $AuditData.SiteURL
      Site         = $AuditData.SiteURL.Split("/")[4]           }
  $Report.Add($ReportLine)
  
} #End Foreach Record

# Remove normal uploads
$Report = $Report | Where-Object {$_.UploadedBy -notlike "*@*"}
$Report | Select-Object Timestamp, Site, Folder, FileName  -Unique

Control Over Files Request

Some people might be cautious about using a feature that allows external people to upload files to SharePoint Online. It could, after all, be a vector that an attacker could abuse to upload infected files. On the other hand, is it any more dangerous than asking external people to email attachments to an internal user so that they can upload the files to SharePoint Online.

Control is available by

  • Limiting the number of sites that support Files request.
  • Limiting the validity of file request links.
  • Training users to use the Files Request feature sparingly, and if they use it, they should take the responsibility of restricting access to the upload link and checking whatever files external people upload before making those files available more broadly within the tenant.

Like any new feature, it will take time for tenants to operationalize Files Request. Happy uploading!


Support the work of the Office 365 for IT Pros team by subscribing to the Office 365 for IT Pros eBook. Your support pays for the time we need to track, analyze, and document the changing world of Microsoft 365 and Office 365.

✇Office 365 for IT Pros

Microsoft Enforces New License Rules for Teams Room Devices

Teams Room Devices Need Proper Licenses by July 1, 2023

Teams Rooms Devices for All (source: Microsoft)
Teams Rooms Devices for All (source: Microsoft)

On March 24, Microsoft announced a major change in the licensing regime for Teams Rooms devices. In a nutshell, Microsoft wants to stop tenants assigning user subscription licenses (like Office 365 E3 or Microsoft 365 E5) to certified Teams Rooms systems like a Surface Hub. Instead, they will require tenants to assign a Teams Rooms Basic or Teams Rooms Pro license to each device (details of the licenses are available here).

In fact, you don’t assign licenses to a Teams Rooms device. Instead, you assign the license to the Exchange Online room mailbox that manages the calendar for the device. An Exchange Online room mailbox comes with an Azure AD account that holds the license.

Microsoft says that after July 1, 2023, tenants cannot assign user subscription licenses to Teams Rooms devices. More importantly, Microsoft will block sign-ins from devices with user subscription licenses until the devices receive a Teams Rooms license.

License Types

Small organizations can rely on the Basic (no cost) license. The basic license covers “core meeting experiences” meaning that the device can schedule and join meetings and share content and whiteboarding during meetings. However, Microsoft limits these licenses to 25 Teams Rooms devices per tenant and doesn’t allow tenants to assign basic licenses to Teams panels, which require Teams Rooms Pro or Teams Shared Device licenses.

After a tenant operates more than 25 Teams Rooms devices, they must buy Pro licenses (each costing $480 for the annual subscription). If you’ve assigned user subscription licenses to Teams Rooms devices in the past, this is roughly equivalent to the annual cost of an Office 365 E5 license. The extra cost pays for “enhanced in-room meeting experiences” like better audio and video and “advanced management” like remote device management. For more details about the functionality enabled by Teams Pro licenses, see Microsoft’s comparison.

Using PowerShell to Find Licensed Room Mailboxes

The process of switching from user subscription licenses involves finding devices with those licenses, removing the licenses, and assigning a new license. To help, Microsoft created a script using Microsoft Graph PowerShell SDK cmdlets to examine and report the licenses assigned to the accounts used by room mailboxes.

Microsoft’s script uses this code to find the room mailboxes.

$Room_UPNs = get-mailbox | Where-Object { $_.recipientTypeDetails -eq "roomMailbox" } | Select-Object DisplayName, PrimarySmtpAddress, ExternalDirectoryObjectId

It’s a good example of code that works perfectly in a test environment that will be horribly slow in production. First, the code uses the old Get-Mailbox cmdlet to find mailboxes. Second, it uses a client-side filter to extract room mailboxes from the set of mailboxes. That set could be tens of thousands, so deriving the set of room mailboxes will be very slow. This version is better:

[array]$Room_UPNs = Get-ExoMailbox -Filter {recipientTypeDetails -eq "RoomMailbox" } | Select-Object DisplayName, PrimarySmtpAddress, ExternalDirectoryObjectId

Apart from using Get-ExoMailbox to fetch mailboxes and taking advantage of the much better performance of the new REST-based cmdlets together with their ability to survive transient network failures, the code uses a server-side filter to force Exchange Online to do the heavy lifting of finding room mailboxes and only transmitting their details to the client. The golden rule is that time the Get-ExoMailbox cmdlet needs to filter objects, use a server-side filter.

Oddly, the original code doesn’t declare the variable to receive the result of Get-Mailbox to be an array and ends up reporting the count of room mailboxes using the Length rather than the Count property. Another golden rule is to always declare an array to receive results from cmdlets that return PowerShell objects as it makes it much easier to check the returned values.

Always Best to Be Efficient

A case exists that this script is a one-time operation that doesn’t need to be ultra-efficient. That might be so, but it’s nice when a few tweaks make the code run much faster, especially for large tenants that are likely to have many Teams Rooms devices that might need a license check.

❌