Mail never moved to the cloud. It runs on Exchange on-premises, so when the E5 licences went in, someone switched off the Exchange Online service plan. It felt like good housekeeping: nobody gets a second, empty mailbox, and nobody's mail ends up in the wrong place.
Two years later, legal asks for the Teams chats of an employee who left. eDiscovery comes back empty. Not because the chats were deleted. Because they were never kept.
Where Teams keeps its compliance copy
Teams stores its messages in an Azure-powered chat service. That's what the app shows you. But eDiscovery, holds and retention never look there. They work on a compliance copy in Exchange Online: chats land in a hidden folder in the mailbox of every participant, and channel messages in the mailbox of the team's Microsoft 365 group. Microsoft is blunt about the difference:
Messages visible in the Teams app are not an accurate reflection of whether they're retained or permanently deleted for compliance requirements.
For users whose mailbox lives on-premises, Microsoft creates a separate cloud-based storage area in Exchange Online, just for their Teams chats. That's the "shadow mailbox" people talk about. And it comes with a condition.
The licence condition nobody reads
From Microsoft's documentation on Teams and Exchange:
- That cloud storage requires a Microsoft Teams licence and at least Exchange Online Plan 1.
- To preserve or retain those chats (eDiscovery holds and retention policies), Microsoft's article on on-premises users says the user needs Exchange Online Plan 2. That article now carries a banner saying its guidance applies to 21Vianet, so check it against your own licensing guidance. It does match the general rule: an Exchange Online mailbox also needs Plan 2 (or Plan 1 plus Exchange Online Archiving) to go on litigation hold.
Switch off the Exchange Online service plan in the licence, never switch it on, and that storage isn't there. For cloud-only users the story is simpler: their chats go into their own Exchange Online mailbox, so no Exchange Online plan means no mailbox to put them in. Either way, that user's chats sit outside eDiscovery, holds and retention.
The cruel part is that switching the plan off is often the responsible choice. Microsoft's own docs warn that in an organization without an Exchange hybrid deployment, assigning that licence to someone whose mailbox is on-premises, without syncing the on-premises Exchange schema, risks creating a duplicate cloud mailbox. So admins switch it off to avoid one mess and walk straight into another.
A few nuances before you panic, or relax:
- Every participant gets a copy. If the unlicensed user chatted with a colleague who does have Exchange Online, the chat still exists in that colleague's mailbox. But you have to know whom to search, and a hold on the departed user's account protects nothing. Chats between unlicensed users have no compliance copy at all: they're visible in the Teams app, and that's it.
- Channel messages are fine. They're stored in the team's group mailbox, and eDiscovery and holds on channel messages are supported whatever the user's mailbox situation.
- Leavers are where it hurts. Retention keeps a departed user's chats in an inactive mailbox. No mailbox, no inactive mailbox.
- Don't count on backfill. Learn doesn't say whether chats from before the licence was turned on get stored afterwards. Treat the date you switch it on as the date your coverage starts.
It's not only Teams
The mailbox is Microsoft 365's filing cabinet for more than mail. According to the eDiscovery documentation, Copilot prompts and responses, To Do tasks, Microsoft Forms and private Viva Engage messages are also stored in, or associated with, Exchange Online mailboxes. The same logic applies: no mailbox, no compliance copy.
Find the users it already applies to
This read-only script reads licence data from Microsoft Graph and lists every user who has the Teams service plan but no Exchange Online Plan 1 or Plan 2. It changes nothing; it only reads.
#Requires -Modules Microsoft.Graph.Authentication, Microsoft.Graph.Users, Microsoft.Graph.Identity.DirectoryManagement
<#
.SYNOPSIS
Lists users who have Teams but no Exchange Online Plan 1 or Plan 2.
.DESCRIPTION
Read-only. Teams chats are kept for compliance in Exchange Online. Users with
the Teams service plan enabled but no Exchange Online Plan 1 or Plan 2
enabled have no place for that copy, so their chats fall outside
eDiscovery, holds and retention.
.NOTES
Modules : Microsoft.Graph.Authentication, Microsoft.Graph.Users,
Microsoft.Graph.Identity.DirectoryManagement
Scopes : User.Read.All, LicenseAssignment.Read.All (delegated, read-only)
Plan IDs: from "Product names and service plan identifiers for licensing"
on Microsoft Learn. Checks TEAMS1, the Teams plan in the
Microsoft 365 and Office 365 suites; add other Teams plan IDs if
you use standalone or government SKUs.
Licence data only: it can't see where a hybrid user's mailbox lives.
#>
$ErrorActionPreference = 'Stop'
Connect-MgGraph -Scopes 'User.Read.All', 'LicenseAssignment.Read.All' -NoWelcome
$teamsPlan = '57ff2da0-773e-42df-b2af-ffb7a2317929' # TEAMS1
$exoPlans = @{
'9aaf7827-d63c-4b61-89c3-182f06f82e5c' = 'Plan 1' # EXCHANGE_S_STANDARD
'efb87545-963c-4e0d-99df-69c6916d9eb0' = 'Plan 2' # EXCHANGE_S_ENTERPRISE
'4a82b400-a79f-41a4-b4e2-e94f5787b113' = 'Kiosk' # EXCHANGE_S_DESKLESS
}
# 1. Which service plans each licence (SKU) in the tenant contains
$skuPlans = @{}
foreach ($sku in Get-MgSubscribedSku -All) {
$skuPlans["$($sku.SkuId)"] = @($sku.ServicePlans | ForEach-Object { "$($_.ServicePlanId)" })
}
# 2. Per user: enabled plans = the SKU's plans minus the disabled ones.
# assignedLicenses includes group-based licences.
$report = foreach ($u in Get-MgUser -All -Property Id, UserPrincipalName, AccountEnabled, AssignedLicenses) {
$enabled = foreach ($lic in $u.AssignedLicenses) {
$disabled = @($lic.DisabledPlans | ForEach-Object { "$_" })
$skuPlans["$($lic.SkuId)"] | Where-Object { $_ -notin $disabled }
}
if ($teamsPlan -notin $enabled) { continue } # no Teams, no Teams chats
$exo = @($exoPlans.Keys | Where-Object { $_ -in $enabled } | ForEach-Object { $exoPlans[$_] })
if ($exo -contains 'Plan 1' -or $exo -contains 'Plan 2') { continue }
[pscustomobject]@{
User = $u.UserPrincipalName
Enabled = $u.AccountEnabled
Exchange = $(if ($exo) { $exo -join ', ' } else { 'none' })
Note = $(if ($exo) { 'Kiosk mailbox: fine in the cloud, below the Plan 1 minimum if the mailbox is on-premises' }
else { 'No Exchange Online plan: chats not kept for compliance' })
}
}
$report | Sort-Object Exchange, User | Format-Table -AutoSize -Wrap
'{0} Teams users without Exchange Online Plan 1 or Plan 2.' -f @($report).Count
Reading the result. Every none is a user whose Teams chats aren't kept for compliance, and Enabled = False rows are the leavers you'll be asked about first. A Kiosk row is usually fine for a cloud mailbox, but below the documented minimum if that mailbox is on-premises. And for hybrid users, look one step further than this script can: according to Microsoft's on-premises article, holds and retention on their chats need Plan 2, not Plan 1.
Switching off Exchange Online in a licence looks like housekeeping. For Teams, it's a compliance decision. Make it on purpose, and find out who it already applies to before someone from legal does.
Sources: Search for Teams chat data for on-premises users, How Exchange and Microsoft Teams interact, Learn about retention for Microsoft Teams, Finding content in mailboxes in eDiscovery, Product names and service plan identifiers for licensing, Place a mailbox on litigation hold.