From 21fa6468c2f725fe294e0958129db9d5a4d055d9 Mon Sep 17 00:00:00 2001 From: Sekers <46898253+Sekers@users.noreply.github.com> Date: Wed, 30 Sep 2026 16:37:52 -0500 Subject: [PATCH 1/3] Record the group chat lookup timing, and which account listed the chats Section 9 attributes its count of 6 group chats to the signed-in sender, but that read-only run signed in as one of the recipient accounts, and the section has no timing for the two lookup calls. Say which account the count came from, add the timing of the Chat.Read and Chat.ReadBasic calls, and list what the timing leaves open. --- Research_Notes/Microsoft-Graph-Behavior.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Research_Notes/Microsoft-Graph-Behavior.md b/Research_Notes/Microsoft-Graph-Behavior.md index c7b8b2b..2fd8c8a 100644 --- a/Research_Notes/Microsoft-Graph-Behavior.md +++ b/Research_Notes/Microsoft-Graph-Behavior.md @@ -330,9 +330,9 @@ accounts the tester controls: the signed-in sender and two recipients. **Measured:** - `Get-MgChat -All -Filter "ChatType eq 'group'"` with `-ExpandProperty 'Members', 'LastMessagePreview'`, the - call the module makes, succeeded: Graph accepts both expansions in one request. Each of the signed-in account's - 6 group chats came back with its members' `email` values and a `LastMessagePreview`, and no two of them had the - same members. + call the module makes, succeeded: Graph accepts both expansions in one request. In a separate read-only run, + signed in as one of the recipient accounts instead of the sender, each of that account's 6 group chats came + back with its members' `email` values and a `LastMessagePreview`, and no two of them had the same members. - **A group chat with the same members as an existing one is a new chat.** `New-MgChat -BodyParameter`, with `chatType` `group` and the same three members as an existing group chat, returned a chat with a new ID and a `CreatedDateTime` of that moment. @@ -360,6 +360,10 @@ accounts the tester controls: the signed-in sender and two recipients. `user@odata.bind` value was present but named a user that does not exist (a quoted list of addresses passed as one address). The message says the field is missing when it is there but wrong. Both the `-Members` form and the `-BodyParameter` form gave it. +- **Timing** (read-only, signed in as the sender, 21 group chats, five alternating runs of each call): the + `Chat.Read` path's call, expanding `Members` and `LastMessagePreview`, took 580 to 780 ms, median 668 ms. The + `Chat.ReadBasic` path's call, expanding only `Members`, took 541 to 646 ms, median 573 ms. The `Chat.Read` call + was slower in all five pairs. **From documentation:** the chat resource type page defines `lastUpdatedDateTime` as "Date and time at which the chat was renamed or the list of members was last changed", and says `lastMessagePreview` is "Null if no messages @@ -397,4 +401,6 @@ values are exactly the sender plus the recipients, and creates a new group chat tested. - **Unverified:** whether permissions a user consented to for themselves, rather than ones an administrator granted for the organization, are carried the same way. Only administrator grants were measured. +- How the timing gap grows with many more chats, and whether sorting on the server by + `lastMessagePreview/createdDateTime` would make the `Chat.Read` path faster. - Nothing in this section was measured on Windows PowerShell 5.1 or with an SDK release other than 2.25.0. From cf6e1afc950c9704106b4b5578807742e13addef Mon Sep 17 00:00:00 2001 From: Sekers <46898253+Sekers@users.noreply.github.com> Date: Thu, 1 Oct 2026 12:55:50 -0500 Subject: [PATCH 2/3] Record the live group chat creation and plus sign attachment results The research notes list the module's own New-MgChat -Members call as unverified, and say nothing about what OneDrive names a chat attachment whose name contains a plus sign. Add the 2026-10-01 measurements: a Group send with no matching chat creates a group chat with exactly the sender and recipients, a second send finds it, a member's email can differ in letter case from the address given and still matches, and a recipient who leaves a chat drops out of the members the sender's listing returns. Record that a plus sign in an attachment name is kept in OneDrive and in Teams. --- Research_Notes/Microsoft-Graph-Behavior.md | 37 ++++++++++++++++++---- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/Research_Notes/Microsoft-Graph-Behavior.md b/Research_Notes/Microsoft-Graph-Behavior.md index 2fd8c8a..f2d3b5f 100644 --- a/Research_Notes/Microsoft-Graph-Behavior.md +++ b/Research_Notes/Microsoft-Graph-Behavior.md @@ -4,11 +4,11 @@ What Microsoft Graph and the Microsoft Graph PowerShell SDK do in the areas this permissions, what a successful send returns, chat creation and reuse, attachment and upload limits, how SDK sign-in persists, and what disconnecting after a send changes. Each claim is tied to the part of the module it affects. -**Only sections 7 and 9 were measured against a tenant**, on **2026-09-16** and **2026-09-30**; each section -gives its environment. Documentation was read on **2026-09-15** from the pages listed under Sources, and the SDK -source on **2026-09-16**, except for section 8, whose pages and SDK source were read on **2026-09-21**, and -section 9, whose pages were read on **2026-09-30**. Microsoft revises these pages, so re-read a page before -relying on a limit or a permission. +**Only sections 7 and 9, and one finding in section 5, were measured against a tenant**, on **2026-09-16**, +**2026-09-30**, and **2026-10-01**; each section gives its environment. Documentation was read on **2026-09-15** +from the pages listed under Sources, and the SDK source on **2026-09-16**, except for section 8, whose pages and +SDK source were read on **2026-09-21**, and section 9, whose pages were read on **2026-09-30**. Microsoft revises +these pages, so re-read a page before relying on a limit or a permission. **Claims are labelled with their evidence.** @@ -147,6 +147,12 @@ requests `Mail.Send` only. Chat attachments are uploaded with a simple `PUT` to that name is taken), shared with the chat recipients as read-only with sign-in required and no invitation email, and then referenced from the chat message. +**Measured** (2026-10-01, in the environment section 9 gives for that date): a chat attachment named +`plus+sign test.txt`, in a folder whose name also contains a `+`, was stored in OneDrive under exactly that name, +and Teams showed it under that name in the chat. The module escapes the name with `[uri]::EscapeDataString`, +which turns `+` into `%2B` in both PowerShell editions (measured locally the same day), so the `+` is kept rather +than read as a space. + ### What this does not establish - **Unverified:** the largest attachment, or total request size, that `sendMail` accepts inline. The 3 MB figure @@ -158,6 +164,8 @@ email, and then referenced from the chat message. comment in the module says it overwrites, and the module renames the file to avoid the question. - **Unverified:** that `Microsoft Teams Chat Files` is the folder Teams itself uses for chat attachments. The module assumes it; none of the pages above mention it. +- The `+` result was seen from the sender's side only; whether the recipients can open the shared file was not + checked. No other special character in a file name was tested. ## 6. From documentation: how SDK sign-in persists, and other clouds @@ -365,6 +373,21 @@ accounts the tester controls: the signed-in sender and two recipients. `Chat.ReadBasic` path's call, expanding only `Members`, took 541 to 646 ms, median 573 ms. The `Chat.Read` call was slower in all five pairs. +**Measured on 2026-10-01** in the same environment, with `Microsoft.Graph.Files` 2.25.0 added, `Send-ScriptMessage` +from `develop` at `32282b7`, and the same three accounts: + +- **A recipient leaving a group chat in Teams changes the members the sender's listing returns.** One recipient + left both group chats holding all three accounts; afterwards the sender's `Get-MgChat` listing still returned + both, with only the two remaining members, so neither matched a send to all three. +- **The module's own `New-MgChat -Members` call creates a group chat with valid members.** With no group chat + holding exactly the sender and both recipients, `Send-ScriptMessage -ChatType Group` created one, of type + `group`, with exactly those three members, and posted its message into it. +- **A second send finds the chat the first one created.** The same send again posted into that chat, and the + sender still had only that one group chat with those three members. +- **A member's `email` can differ in letter case from the address the caller gave.** One recipient, given in + lower case, came back as a member `email` with capital letters. The match still succeeded: `Compare-Object` + ignores letter case unless given `-CaseSensitive`, in both PowerShell editions (measured locally the same day). + **From documentation:** the chat resource type page defines `lastUpdatedDateTime` as "Date and time at which the chat was renamed or the list of members was last changed", and says `lastMessagePreview` is "Null if no messages were sent in the chat" and that only the list chats operation supports it. The List chats page lists @@ -393,12 +416,12 @@ values are exactly the sender plus the recipients, and creates a new group chat ### What this does not establish -- **Unverified:** the module's own `New-MgChat -Members` call creating a group chat with valid members. A matching - chat already existed, so that path was not exercised. - **Unverified:** whether the Teams client ever creates a second group chat with the same members, and whether anything besides a rename or a member change moves `LastUpdatedDateTime` (only the documentation says so). - **Unverified:** the 25-member cap, the UPN mismatch, and the alias failure in the inferences above. None was tested. +- Only a three-member group chat was created. A `Group` send to a single recipient, which would match or create a + two-member group chat, was not tested. - **Unverified:** whether permissions a user consented to for themselves, rather than ones an administrator granted for the organization, are carried the same way. Only administrator grants were measured. - How the timing gap grows with many more chats, and whether sorting on the server by From 47201e0072d095c340b33cc4f2986bcb0fcd1559 Mon Sep 17 00:00:00 2001 From: Sekers <46898253+Sekers@users.noreply.github.com> Date: Fri, 2 Oct 2026 12:02:03 -0500 Subject: [PATCH 3/3] Record which forms of address find a user in Microsoft Graph The research notes list the UPN mismatch and the alias failure as untested inferences, and say nothing about which forms of a user's address Graph accepts when a chat is created, an attachment is shared, or mail is sent. Add section 10 with the measurements from 2026-10-01 and 2026-10-02: a UPN and a primary email that is not the UPN both find the user for a chat, a secondary address that was never a UPN fails in New-MgChat with a 404 while the module's warning names the recipient, an attachment can be shared with a UPN, and mail to a UPN is delivered. Cite the Entra documentation that always adds a mailbox user's UPN as a proxy address, and say why the results still do not show whether Graph resolves a primary email that is not the UPN, and what would settle it. In section 9, record the duplicate group chat that a recipient given by a UPN gets, and point to section 10 for the forms of address. --- Research_Notes/Microsoft-Graph-Behavior.md | 115 ++++++++++++++++++--- 1 file changed, 102 insertions(+), 13 deletions(-) diff --git a/Research_Notes/Microsoft-Graph-Behavior.md b/Research_Notes/Microsoft-Graph-Behavior.md index f2d3b5f..f4eedfa 100644 --- a/Research_Notes/Microsoft-Graph-Behavior.md +++ b/Research_Notes/Microsoft-Graph-Behavior.md @@ -2,13 +2,15 @@ What Microsoft Graph and the Microsoft Graph PowerShell SDK do in the areas this module relies on: permissions, what a successful send returns, chat creation and reuse, attachment and upload limits, how SDK sign-in -persists, and what disconnecting after a send changes. Each claim is tied to the part of the module it affects. +persists, what disconnecting after a send changes, and which forms of address find a user. Each claim is tied to +the part of the module it affects. -**Only sections 7 and 9, and one finding in section 5, were measured against a tenant**, on **2026-09-16**, -**2026-09-30**, and **2026-10-01**; each section gives its environment. Documentation was read on **2026-09-15** -from the pages listed under Sources, and the SDK source on **2026-09-16**, except for section 8, whose pages and -SDK source were read on **2026-09-21**, and section 9, whose pages were read on **2026-09-30**. Microsoft revises -these pages, so re-read a page before relying on a limit or a permission. +**Only sections 7, 9, and 10, and one finding in section 5, were measured against a tenant**, on **2026-09-16**, +**2026-09-30**, **2026-10-01**, and **2026-10-02**; each section gives its environment. Documentation was read on +**2026-09-15** from the pages listed under Sources, and the SDK source on **2026-09-16**, except for section 8, +whose pages and SDK source were read on **2026-09-21**, section 9, whose pages were read on **2026-09-30**, and +section 10, whose pages were read on **2026-10-01** and **2026-10-02**. Microsoft revises these pages, so re-read a +page before relying on a limit or a permission. **Claims are labelled with their evidence.** @@ -53,6 +55,8 @@ these pages, so re-read a page before relying on a limit or a permission. | [Microsoft Graph PowerShell SDK authentication source, branch `main`](https://github.com/microsoftgraph/msgraph-sdk-powershell/tree/main/src/Authentication) | none (branch, read 2026-09-21) | | [List chats](https://learn.microsoft.com/en-us/graph/api/chat-list?view=graph-rest-1.0) | 2026-04-13 | | [chat resource type](https://learn.microsoft.com/en-us/graph/api/resources/chat?view=graph-rest-1.0) | 2026-08-05 | +| [Integrate Microsoft Entra Agent ID with third-party identity providers](https://learn.microsoft.com/en-us/microsoft-agent-365/developer/third-party-identity-providers) | 2026-08-13 | +| [How the proxyAddresses attribute is populated in Microsoft Entra ID](https://learn.microsoft.com/en-us/troubleshoot/entra/entra-id/user-prov-sync/proxyaddresses-attribute-populate) | 2026-09-17 | ## 1. From documentation: permissions for each operation the module performs @@ -387,6 +391,12 @@ from `develop` at `32282b7`, and the same three accounts: - **A member's `email` can differ in letter case from the address the caller gave.** One recipient, given in lower case, came back as a member `email` with capital letters. The match still succeeded: `Compare-Object` ignores letter case unless given `-CaseSensitive`, in both PowerShell editions (measured locally the same day). +- **A recipient given by a UPN that differs from their primary email gets a new group chat instead of the + existing one.** One recipient's UPN was changed in Microsoft Entra ID to a name other than their primary email, + which stayed as it was. The sender's listing still showed that member's `email` as the primary address. A + `Group` send naming that recipient by the new UPN, with the other two members as before, found no match, + created a second group chat with the same three members as the existing one, and posted into it. Its `Error` + was empty, so the caller got no warning. Section 10 covers which forms of address find a user. **From documentation:** the chat resource type page defines `lastUpdatedDateTime` as "Date and time at which the chat was renamed or the list of members was last changed", and says `lastMessagePreview` is "Null if no messages @@ -408,18 +418,18 @@ values are exactly the sender plus the recipients, and creates a new group chat the same holds for every setting that only chooses which delegated permission is asked for. - A group chat with more than 25 members never matches, if the 25-member cap applies to `-All` paging too, so the module would create a new chat on every send to it. -- A recipient given by a UPN that differs from their primary email address never matches either, with the same - result: the module names each member as `users('
')`, which going by Graph's - `/users/{id | userPrincipalName}` form takes a user ID or UPN, but matches on the member's `email`, the primary - address. Matching on each member's `userId` would avoid it. A true alias, neither the UPN nor the primary - address, probably fails when the chat is created instead. +- The UPN mismatch measured above happens because the module names each member as `users('')`, which + going by Graph's `/users/{id | userPrincipalName}` form takes a user ID or UPN, but matches on the member's + `email`, the primary address. Each later send by UPN finds no match in the same way, so it creates yet another + chat. Matching on each member's `userId` would avoid it. ### What this does not establish - **Unverified:** whether the Teams client ever creates a second group chat with the same members, and whether anything besides a rename or a member change moves `LastUpdatedDateTime` (only the documentation says so). -- **Unverified:** the 25-member cap, the UPN mismatch, and the alias failure in the inferences above. None was - tested. +- **Unverified:** the 25-member cap in the inferences above; it was not tested. +- The UPN mismatch was measured with one send. The account syncs from on-premises Active Directory, and its UPN + was changed in Microsoft Entra ID only. - Only a three-member group chat was created. A `Group` send to a single recipient, which would match or create a two-member group chat, was not tested. - **Unverified:** whether permissions a user consented to for themselves, rather than ones an administrator granted @@ -427,3 +437,82 @@ values are exactly the sender plus the recipients, and creates a new group chat - How the timing gap grows with many more chats, and whether sorting on the server by `lastMessagePreview/createdDateTime` would make the `Chat.Read` path faster. - Nothing in this section was measured on Windows PowerShell 5.1 or with an SDK release other than 2.25.0. + +## 10. Measured: which forms of address find a user + +**Environment:** measured on 2026-10-01 and 2026-10-02 in the environment section 9 gives for 2026-10-01, with +the same code and the same three accounts. Chat sends used a delegated sign-in, and the mail send the +`Mail.Send` application permission. The accounts sync from on-premises Active Directory. On 2026-10-01 one +recipient's UPN was changed in Microsoft Entra ID only, to a name other than their primary email, which stayed +as it was, and it stayed changed through every test below. + +**Measured:** + +- **A chat member given by UPN resolves.** A `Group` send naming that recipient by the new UPN created a group + chat with them as a member (section 9). On 2026-10-02 a `OneOnOne` send to the same UPN posted into the + existing one-on-one chat between the two accounts, created in 2024, with `Error` empty. +- **A chat member given by primary email resolves while it is not the UPN.** On 2026-10-01, and again on + 2026-10-02, a `OneOnOne` send to that recipient's primary email posted into the same one-on-one chat, with + `Error` empty. +- **A secondary email address that was never a UPN does not resolve.** On 2026-10-01 a `OneOnOne` send with + `From` set to one of the sender's own secondary SMTP addresses, which had never been their UPN, failed in + `New-MgChat` with 404 `Failed to find users with user principal name ''`. Nothing was posted. The + result's `Error` held only the module's warning `Cannot create a chat with the recipient '