msgraph-sdk-powershell icon indicating copy to clipboard operation
msgraph-sdk-powershell copied to clipboard

Remove-MgUserContactFolder

Open silente opened this issue 1 year ago • 23 comments

Describe the bug

Contact folders created with microsoft graph can no longer be deleted via microsoft graph. If the contacts folder was created manually, you can delete them via microsoft graph.

Expected behavior

The contact folder created with graph, previously it was also possible to delete it.

How to reproduce

New-MgUserContactFolder -UserId <String> -DisplayName "Name Of Folder" Remove-MgUserContactFolder -UserId <String> -ContactFolderId (Get-MgUserContactFolder -UserId <String> | Where-Object {$_.DisplayName -eq "Name Of Folder"}).Id

SDK Version

2.18.0

Latest version known to work for scenario above?

No response

Known Workarounds

None

Debug output

Click to expand log ```

Remove-MgUserContactFolder_Delete: Object cannot be deleted.

Status: 403 (Forbidden) ErrorCode: ErrorCannotDeleteObject Date:

Headers: Cache-Control : private Vary : Accept-Encoding Strict-Transport-Security : max-age=31536000 request-id : 8634d56a-3414-4f00-99a9-d0a59bf2a7b6 client-request-id : 9b809062-fd7f-4bc5-a7ab-58dcb483d473 x-ms-ags-diagnostic : {"ServerInfo":{"DataCenter":"Switzerland North","Slice":"E","Ring":"3","ScaleUnit":"002","RoleInstance":"ZR2PEPF000000BD"}}
Date : Tue, 14 May 2024 18:37:25 GMT

</details>


### Configuration

PSVersion                      7.4.2
PSEdition                      Core
GitCommitId                    7.4.2
OS                             Microsoft Windows 10.0.22631
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Windows 11 x64

### Other information

I use an app registered on azure with the permissions Contacts.ReadWrite and User.Read.All applied to the entire organization. 

silente avatar May 14 '24 18:05 silente

Hi @silente ,

I was able to test this scenario and I can not reproduce the issue you are describing, the deletion works well for me. Could you please try upgrading to the latest 2.19 and trying again, and also trying the same steps in your tenant using Graph Explorer?

Thanks!

petrhollayms avatar May 21 '24 20:05 petrhollayms

Hi @petrhollayms,

I updated the module version to 2.19 but I have the same problem; I am able to replicate the problem, I am sending you the code I am using for testing, but I was previously using to run this type of task

$TenantID = ""
$ClientID = ""
$ClientSecret = ""

function Login {
    Param(
        [parameter(Mandatory = $true)]
        [String]
        $ClientID,
        [parameter(Mandatory = $true)]
        [String]
        $TenantID,
        [parameter(Mandatory = $true)]
        [String]
        $ClientSecret
    )
         
    Try { 
        $ClientSecretPass = ConvertTo-SecureString -String $ClientSecret -AsPlainText -Force
        $ClientSecretCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $ClientID, $ClientSecretPass

        Connect-MgGraph -TenantId $TenantID -ClientSecretCredential $ClientSecretCredential -NoWelcome
    }
    catch {
        throw "Error Login"
        break
    }
}

$UserId = ''
$FolderName = ''

Login -TenantID $TenantID -ClientID $ClientID -ClientSecret $ClientSecret
New-MgUserContactFolder -UserId $UserId -DisplayName $FolderName
Remove-MgUserContactFolder -UserId $UserId -ContactFolderId (Get-MgUserContactFolder -UserId $UserId | Where-Object {$_.DisplayName -eq $FolderName}).Id

The error I have running the script is

PS C:\Data\GAL2> . 'C:\Data\GAL2\_DEV_\2743.ps1'

Id                                                                                                                       DisplayName        ParentFolderId
--                                                                                                                       -----------        --------------
AAMkADc0YTllNzJjLTRiMzMtNGM4OS1iOWRhLTY0NGI4ZGRmZjAwMQAuAAAAAABABblSsib5TImJA6o109F_AQCPtR5Z8B27ToTvDR0eRBrBAAGJ0LEOAAA= Contats Test AAMkADc0YTllNzJjLTRiMzMtNGM4OS1iOWRhLTY0NGI4ZGRmZjAwMQAuAAAAAABABblSsib5TImJA6… 
Remove-MgUserContactFolder_Delete: C:\Data\GAL2\_DEV_\2743.ps1:35:1
Line |
  35 |  Remove-MgUserContactFolder -UserId $UserId -ContactFolderId (Get-MgUs …
     |  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | Object cannot be deleted.  Status: 403 (Forbidden) ErrorCode: ErrorCannotDeleteObject Date:   Headers: Cache-Control                 : private Vary                          : Accept-Encoding
     | Strict-Transport-Security     : max-age=31536000 request-id                    : 64c615e6-fa92-447f-93f9-3c98aeb02140 client-request-id             : 9d5bbab9-1e7d-43a8-9c7a-092c4f57cd3a x-ms-ags-diagnostic       
     | : {"ServerInfo":{"DataCenter":"Italy North","Slice":"E","Ring":"3","ScaleUnit":"002","RoleInstance":"MI3PEPF000001C5"}} Date                          : Fri, 24 May 2024 16:44:55 GMT

The permissions assigned to the app are: Contacts.ReadWrite Application Read and write contacts in all mailboxes User.Read.All Application Read all users' full profile

silente avatar May 24 '24 16:05 silente

hi @silente ,

Could you please share the output of the Connect-MgGraph command to check the Scopes assigned to the app? It looks like a permission issue. It would be also helpful if you could run the Remove cmdlet with the -Debug parameter and share the output. See https://learn.microsoft.com/en-us/powershell/microsoftgraph/troubleshooting?view=graph-powershell-1.0#using--debug

petrhollayms avatar May 27 '24 20:05 petrhollayms

Hi @petrhollayms

Here you should find all the information you requested from me. I don't think it's a permissions problem; it was working until 1 month ago.

DEBUG: [CmdletBeginProcessing]: - Remove-MgUserContactFolder begin processing with parameterSet 'Delete'.
DEBUG: [Authentication]: - AuthType: 'AppOnly', TokenCredentialType: 'ClientSecret', ContextScope: 'Process', AppName: 'GAL'.
DEBUG: [Authentication]: - Scopes: [Contacts.ReadWrite, User.Read.All].

Confirm
Are you sure you want to perform this action?
Performing the operation "Remove-MgUserContactFolder_Delete" on target "Call remote 'DELETE /users/{user-id}/contactFolders/{contactFolder-id}' operation".     
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "Y"): A
DEBUG: ============================ HTTP REQUEST ============================

HTTP Method:
DELETE

Absolute Uri:
https://graph.microsoft.com/v1.0/users/[email protected]/contactFolders/AAMkADc0YTllNzJjLTRiMzMtNGM4OS1iOWRhLTY0NGI4ZGRmZjAwMQAuAAAAAABABblSsib5TImJA6o109F_AQCPtR5Z8B27ToTvDR0eRBrBAAGNNV-xAAA%3D

Headers:
FeatureFlag                   : 00000043
Cache-Control                 : no-store, no-cache
User-Agent                    : Mozilla/5.0,(Windows NT 10.0; Microsoft Windows 10.0.22631; it-IT),PowerShell/2024.2.2
Accept-Encoding               : gzip
SdkVersion                    : graph-powershell/2.19.0
client-request-id             : 50f7cca8-83bd-4726-ab45-b944184b38b7

Body:



DEBUG: ============================ HTTP RESPONSE ============================

Status Code:
Forbidden

Headers:
Cache-Control                 : private
Vary                          : Accept-Encoding
Strict-Transport-Security     : max-age=31536000
request-id                    : dceada7d-3d8e-492c-a97a-b88bc4ff8e98
client-request-id             : 50f7cca8-83bd-4726-ab45-b944184b38b7
x-ms-ags-diagnostic           : {"ServerInfo":{"DataCenter":"Switzerland North","Slice":"E","Ring":"3","ScaleUnit":"001","RoleInstance":"ZRH2EPF000000E5"}}     
Date                          : Mon, 27 May 2024 20:21:47 GMT

Body:
{
  "error": {
    "code": "ErrorCannotDeleteObject",
    "message": "Object cannot be deleted."
  }
}


Remove-MgUserContactFolder_Delete: C:\Data\GAL2\_DEV_\2743.ps1:35:1
Line |
  35 |  Remove-MgUserContactFolder -UserId $UserId -ContactFolderId (Get-MgUs …
     |  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | Object cannot be deleted.  Status: 403 (Forbidden) ErrorCode: ErrorCannotDeleteObject Date:   Headers: Cache-Control                 : private Vary      
     | : Accept-Encoding Strict-Transport-Security     : max-age=31536000 request-id                    : dceada7d-3d8e-492c-a97a-b88bc4ff8e98
     | client-request-id             : 50f7cca8-83bd-4726-ab45-b944184b38b7 x-ms-ags-diagnostic           : {"ServerInfo":{"DataCenter":"Switzerland
     | North","Slice":"E","Ring":"3","ScaleUnit":"001","RoleInstance":"ZRH2EPF000000E5"}} Date                          : Mon, 27 May 2024 20:21:47 GMT
DEBUG: [CmdletEndProcessing]: - Remove-MgUserContactFolder end processing.

silente avatar May 27 '24 20:05 silente

Hi @silente ,

OK the permission looks good. Could you please share a debug output of the New-MgUserContactFolder cmdlet? It looks like you are not specifying the parent folder?

See the API parameters and PowerShell sample here: https://learn.microsoft.com/en-us/graph/api/user-post-contactfolders?view=graph-rest-1.0&tabs=powershell#request Will anything change if you also specify parentFolderId and displayName as a -BodyParameter parameter of New-MgUserContactFolder?

By looking on the API docs for the delete method, https://learn.microsoft.com/en-us/graph/api/contactfolder-delete?view=graph-rest-1.0&tabs=powershell Delete contactFolder other than the default contactFolder.

So, could it be that by not passing the parent folder ID, you are creating a default contact folder?

Btw. I see a typo in your folder name but this shall not have any impact if you pass it everywhere by using the same variable: "Contats Test"

petrhollayms avatar May 27 '24 21:05 petrhollayms

Hi @petrhollayms

Certainly, this is the output.

Performing the operation "New-MgUserContactFolder_CreateExpanded" on target "Call remote 'POST /users/{user-id}/contactFolders' operation".
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "Y"): Y
DEBUG: ============================ HTTP REQUEST ============================

HTTP Method:
POST

Absolute Uri:
https://graph.microsoft.com/v1.0/users/[email protected]/contactFolders

Headers:
FeatureFlag                   : 00000043
Cache-Control                 : no-store, no-cache
User-Agent                    : Mozilla/5.0,(Windows NT 10.0; Microsoft Windows 10.0.22631; it-IT),PowerShell/2024.2.2
Accept-Encoding               : gzip
SdkVersion                    : graph-powershell/2.19.0
client-request-id             : 20e1d5a5-4e53-47fd-87a5-ab3531d5595a

Body:
{
  "displayName": "Contatti Aziendali"
}


DEBUG: ============================ HTTP RESPONSE ============================

Status Code:
Created

Headers:
Cache-Control                 : private
Location                      : https://graph.microsoft.com/v1.0/users('[email protected]')/contactFolders('AAMkADc0YTllNzJjLTRiMzMtNGM4OS1iOWRhLTY0NGI4ZGRmZjAwMQAuAAAAAABABblSsib5TImJA6o109F_AQCPtR5Z8B27ToTvDR0eRBrBAAGOgFnSAAA=')
Vary                          : Accept-Encoding
Strict-Transport-Security     : max-age=31536000
request-id                    : 7c65a3e1-d077-4c8c-bb20-754ca6223e48
client-request-id             : 20e1d5a5-4e53-47fd-87a5-ab3531d5595a
x-ms-ags-diagnostic           : {"ServerInfo":{"DataCenter":"Switzerland North","Slice":"E","Ring":"3","ScaleUnit":"001","RoleInstance":"ZRH2EPF000000E8"}}     
Date                          : Fri, 31 May 2024 10:06:10 GMT

Body:
{
  "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('[email protected]')/contactFolders/$entity",
  "id": "AAMkADc0YTllNzJjLTRiMzMtNGM4OS1iOWRhLTY0NGI4ZGRmZjAwMQAuAAAAAABABblSsib5TImJA6o109F_AQCPtR5Z8B27ToTvDR0eRBrBAAGOgFnSAAA=",
  "parentFolderId": "AAMkADc0YTllNzJjLTRiMzMtNGM4OS1iOWRhLTY0NGI4ZGRmZjAwMQAuAAAAAABABblSsib5TImJA6o109F_AQCPtR5Z8B27ToTvDR0eRBrBAAAAAAEOAAA=",
  "displayName": "Contatti Aziendali"
}



DEBUG: [CmdletEndProcessing]: - New-MgUserContactFolder end processing.
Id                                                                                                                       DisplayName        ParentFolderId      
--                                                                                                                       -----------        --------------      
AAMkADc0YTllNzJjLTRiMzMtNGM4OS1iOWRhLTY0NGI4ZGRmZjAwMQAuAAAAAABABblSsib5TImJA6o109F_AQCPtR5Z8B27ToTvDR0eRBrBAAGOgFnSAAA= Contatti Aziendali AAMkADc0YTllNzJjLT… 

I set up the folder creation by removing the -DisplayName and using -Body. The result is the same.

The tests I have done is to change the name of the folder. If I change the name from “Contatti Aziendali” to another name, the deletion also works.

It sounds strange to me that it does not work, the text does not contain any special characters. I tried another folder name containing a space and it works.

silente avatar May 31 '24 10:05 silente

I wanted to chime in. I seem to have similar problem. I do not use commandlets, only API calls to MS graph to delete folder, create it anew, and fill it with contacts. The job runs on the weekends and was working fine till 12.05.2024, the last successful run was on 05.05,2024. Now all my attempts to delete the folder via the API are met with 403 error. Our Azure admin says that nothing was changed in the Azure setup during that week.

My setup was partially using /beta endpoint instead of /v1.0 endoint due to this bug Shortly - you cannot GET all created folders via v1.0 for some reason, but beta is showing them all. So I was deleting and creating folders via /beta and filling the contacts sending batches via /v1.0.

I was able to reproduce the issue somewhat, and I think the problem is parentFolderId. When creating folders via /beta it is possible sometimes to create a duplicated name (I haven't yet figured out the exact sequence yet, but I've reproduced the issue twice). Then /beta shows both of those folders (but they have slighty different parentFolderId), /v1.0 shows only one. But you cannot delete either of those - you will get 403 error. If you rename the one you can see via v1.0 - you can delete it now safely via API. But the duplicate is still stuck in /beta. Any attempt then to delete it with folderId will return 204, but the folder is not deleted and can be seen via /beta. You cannot see the folder in the UI, but you still can see contacts from it if you flip "New contacts" switch.

So @silente - try to call https://graph.microsoft.com/beta/users/{{UserName}}/contactFolders. If you see your supposely deleted folders there - then our problem is the same.

Now the questions - how to delete those folders seen via /beta? Is there a way to add parentFolderId to DELETE call? Why do we even have several parentFolderId for the user?

Tsubasanut avatar May 31 '24 10:05 Tsubasanut

When I run a GET of the folders I display the following. I actually see many folders with the same name, inexplicably.

{
    "@odata.context": "https://graph.microsoft.com/beta/$metadata#users('[email protected]')/contactFolders",
    "value": [
        {
            "id": "AAMkADc0YTllNzJjLTRiMzMtNGM4OS1iOWRhLTY0NGI4ZGRmZjAwMQAuAAAAAABABblSsib5TImJA6o109F_AQCPtR5Z8B27ToTvDR0eRBrBAAAAAAEOAAA=",
            "parentFolderId": "AAMkADc0YTllNzJjLTRiMzMtNGM4OS1iOWRhLTY0NGI4ZGRmZjAwMQAuAAAAAABABblSsib5TImJA6o109F_AQCPtR5Z8B27ToTvDR0eRBrBAAAAAAEIAAA=",
            "displayName": "Contacts",
            "wellKnownName": "contacts"
        },
        {
            "id": "AAMkADc0YTllNzJjLTRiMzMtNGM4OS1iOWRhLTY0NGI4ZGRmZjAwMQAuAAAAAABABblSsib5TImJA6o109F_AQCPtR5Z8B27ToTvDR0eRBrBAAGOgFnJAAA=",
            "parentFolderId": "AAMkADc0YTllNzJjLTRiMzMtNGM4OS1iOWRhLTY0NGI4ZGRmZjAwMQAuAAAAAABABblSsib5TImJA6o109F_AQCPtR5Z8B27ToTvDR0eRBrBAAAAAAEKAAA=",
            "displayName": "Contatti Azienda",
            "wellKnownName": null
        },
        {
            "id": "AAMkADc0YTllNzJjLTRiMzMtNGM4OS1iOWRhLTY0NGI4ZGRmZjAwMQAuAAAAAABABblSsib5TImJA6o109F_AQCPtR5Z8B27ToTvDR0eRBrBAAGOgFm1AAA=",
            "parentFolderId": "AAMkADc0YTllNzJjLTRiMzMtNGM4OS1iOWRhLTY0NGI4ZGRmZjAwMQAuAAAAAABABblSsib5TImJA6o109F_AQCPtR5Z8B27ToTvDR0eRBrBAAAAAAEKAAA=",
            "displayName": "Contatti Aziendali",
            "wellKnownName": null
        },
        {
            "id": "AAMkADc0YTllNzJjLTRiMzMtNGM4OS1iOWRhLTY0NGI4ZGRmZjAwMQAuAAAAAABABblSsib5TImJA6o109F_AQCPtR5Z8B27ToTvDR0eRBrBAAGOgFnHAAA=",
            "parentFolderId": "AAMkADc0YTllNzJjLTRiMzMtNGM4OS1iOWRhLTY0NGI4ZGRmZjAwMQAuAAAAAABABblSsib5TImJA6o109F_AQCPtR5Z8B27ToTvDR0eRBrBAAAAAAEKAAA=",
            "displayName": "Contatti Aziendali_1a500f2b",
            "wellKnownName": null
        },
        {
            "id": "AAMkADc0YTllNzJjLTRiMzMtNGM4OS1iOWRhLTY0NGI4ZGRmZjAwMQAuAAAAAABABblSsib5TImJA6o109F_AQCPtR5Z8B27ToTvDR0eRBrBAAGOgFnBAAA=",
            "parentFolderId": "AAMkADc0YTllNzJjLTRiMzMtNGM4OS1iOWRhLTY0NGI4ZGRmZjAwMQAuAAAAAABABblSsib5TImJA6o109F_AQCPtR5Z8B27ToTvDR0eRBrBAAAAAAEKAAA=",
            "displayName": "Contatti Aziendali_1b619d2b",
            "wellKnownName": null
        },
        {
            "id": "AAMkADc0YTllNzJjLTRiMzMtNGM4OS1iOWRhLTY0NGI4ZGRmZjAwMQAuAAAAAABABblSsib5TImJA6o109F_AQCPtR5Z8B27ToTvDR0eRBrBAAGOgFm3AAA=",
            "parentFolderId": "AAMkADc0YTllNzJjLTRiMzMtNGM4OS1iOWRhLTY0NGI4ZGRmZjAwMQAuAAAAAABABblSsib5TImJA6o109F_AQCPtR5Z8B27ToTvDR0eRBrBAAAAAAEKAAA=",
            "displayName": "Contatti Aziendali_558236a2",
            "wellKnownName": null
        },
        {
            "id": "AAMkADc0YTllNzJjLTRiMzMtNGM4OS1iOWRhLTY0NGI4ZGRmZjAwMQAuAAAAAABABblSsib5TImJA6o109F_AQCPtR5Z8B27ToTvDR0eRBrBAAGOgFnNAAA=",
            "parentFolderId": "AAMkADc0YTllNzJjLTRiMzMtNGM4OS1iOWRhLTY0NGI4ZGRmZjAwMQAuAAAAAABABblSsib5TImJA6o109F_AQCPtR5Z8B27ToTvDR0eRBrBAAAAAAEKAAA=",
            "displayName": "Contatti Aziendali_66b6349a",
            "wellKnownName": null
        },
        {
            "id": "AAMkADc0YTllNzJjLTRiMzMtNGM4OS1iOWRhLTY0NGI4ZGRmZjAwMQAuAAAAAABABblSsib5TImJA6o109F_AQCPtR5Z8B27ToTvDR0eRBrBAAGOgFm7AAA=",
            "parentFolderId": "AAMkADc0YTllNzJjLTRiMzMtNGM4OS1iOWRhLTY0NGI4ZGRmZjAwMQAuAAAAAABABblSsib5TImJA6o109F_AQCPtR5Z8B27ToTvDR0eRBrBAAAAAAEKAAA=",
            "displayName": "Contatti Aziendali_68352bf1",
            "wellKnownName": null
        },
        {
            "id": "AAMkADc0YTllNzJjLTRiMzMtNGM4OS1iOWRhLTY0NGI4ZGRmZjAwMQAuAAAAAABABblSsib5TImJA6o109F_AQCPtR5Z8B27ToTvDR0eRBrBAAGOgFnSAAA=",
            "parentFolderId": "AAMkADc0YTllNzJjLTRiMzMtNGM4OS1iOWRhLTY0NGI4ZGRmZjAwMQAuAAAAAABABblSsib5TImJA6o109F_AQCPtR5Z8B27ToTvDR0eRBrBAAAAAAEKAAA=",
            "displayName": "Contatti Aziendali_86631d24",
            "wellKnownName": null
        },
        {
            "id": "AAMkADc0YTllNzJjLTRiMzMtNGM4OS1iOWRhLTY0NGI4ZGRmZjAwMQAuAAAAAABABblSsib5TImJA6o109F_AQCPtR5Z8B27ToTvDR0eRBrBAAGOgFnPAAA=",
            "parentFolderId": "AAMkADc0YTllNzJjLTRiMzMtNGM4OS1iOWRhLTY0NGI4ZGRmZjAwMQAuAAAAAABABblSsib5TImJA6o109F_AQCPtR5Z8B27ToTvDR0eRBrBAAAAAAEKAAA=",
            "displayName": "Contatti Aziendali_9e486cc4",
            "wellKnownName": null
        }
    ],
    "@odata.nextLink": "https://graph.microsoft.com/beta/users/[email protected]/contactFolders?%24skip=10"
}

I will do some more tests later

silente avatar May 31 '24 13:05 silente

Hi everybody.

This issue is reproducable even through MS Graph API explorer. See the screenshot.

2024-06-03_16h17_36

I think this issue is on the backend and not raleted to any lib updates.

MaxKasich avatar Jun 03 '24 13:06 MaxKasich

Hi everybody.

This issue is reproducable even through MS Graph API explorer. See the screenshot.

2024-06-03_16h17_36 I think this issue is on the backend and not raleted to any lib updates.

Absolutely agree, I'm not using the lib itself, only the API. I just outlined a possible source of the problem (hidden duplicated folders). Do you have the same issue with hidden duplicates if you use MS Graph API explorer with /beta endpoint?

Tsubasanut avatar Jun 04 '24 09:06 Tsubasanut

Hi everybody. This issue is reproducable even through MS Graph API explorer. See the screenshot. 2024-06-03_16h17_36 I think this issue is on the backend and not raleted to any lib updates.

Absolutely agree, I'm not using the lib itself, only the API. I just outlined a possible source of the problem (hidden duplicated folders). Do you have the same issue with hidden duplicates if you use MS Graph API explorer with /beta endpoint?

I have the same issue, but I don't have hidden duplicates (single folder, created via API) and I am using general API, not beta. When I request "get all folders" - I receive only one (which I am trying to delete).

MaxKasich avatar Jun 04 '24 12:06 MaxKasich

I have just encountered this exact error and can reproduce it as well. The permissions are correct since I had successfully executed the command before. I also don't have hidden duplicates with the get-command.

Mezzo25 avatar Jun 10 '24 13:06 Mezzo25

@MaxKasich @Mezzo25 You will not see duplicates unless you use /beta endpoint. They are not strictly say duplicates as they are listed with a different parentFolderId (see what silente posted). But since MS Graph do not let us see or manipulate parent folders - we cannot understand the problem from our side of the fence. I tried to update contact folder PArentFolderId withPATCH but no success.

Tsubasanut avatar Jun 12 '24 06:06 Tsubasanut

@Tsubasanut, you're right. I've switched to /beta and now I see hidden duplicates. So that might be a root cause of the problem.

MaxKasich avatar Jun 12 '24 08:06 MaxKasich

Hi Together.

I also had this issue, but I found a workaround. It looks like MS is putting a deleted folder in a kind of recycle bin. If you then delete a folder with the same name in the magic recycle bin, the deletions fail with the error above. My workaround is to first rename the folder to a unique name. That is my process:

            $folder=@(Get-MgUserContactFolder -UserId $userId -Filter "DisplayName eq '$folderName'")
            if ($folder.Count -gt 0) {
                Write-Host "Folder exist. Deleting folder(s): $($folder.Count)"
                $folder | ForEach-Object {
                    $id=$_.Id
		$newName=(New-Guid).Guid # Magic 1: Random name
		Update-MgUserContactFolder -ContactFolderId $id -UserId $userId -DisplayName $newName # Magic 2: Rename the folders display name
                    Remove-MgUserContactFolder -ContactFolderId $id -UserId $userId  | Out-Null
                }
            }

The magic / renaming happens with the two lines: $newName=(New-Guid).Guid and Update-MgUserContactFolder -ContactFolderId $id -UserId $userId -DisplayName $newName

Let me know if this also works for you.

Marcel

MarcelMeurer avatar Jun 18 '24 13:06 MarcelMeurer

I've been having this same issue while using the PHP SDK and previously it worked as intended. It's not a permissions problem and as someone else already mentioned it doesn't seem to be a lib issue but more like a backend problem on microsoft side. It doesn't work both using the PHP SDK and normal HTTP request using Postman.

DiogoCordas avatar Jun 19 '24 08:06 DiogoCordas

I've been having this same issue while using the PHP SDK and previously it worked as intended. It's not a permissions problem and as someone else already mentioned it doesn't seem to be a lib issue but more like a backend problem on microsoft side. It doesn't work both using the PHP SDK and normal HTTP request using Postman.

Hi @DiogoCordas : Can you test my workaround also in PHP (first renaming the folder and then deleting the folder)?

MarcelMeurer avatar Jun 19 '24 08:06 MarcelMeurer

I've been having this same issue while using the PHP SDK and previously it worked as intended. It's not a permissions problem and as someone else already mentioned it doesn't seem to be a lib issue but more like a backend problem on microsoft side. It doesn't work both using the PHP SDK and normal HTTP request using Postman.

Hi @DiogoCordas : Can you test my workaround also in PHP (first renaming the folder and then deleting the folder)?

Hi @MarcelMeurer I've just tested first updating the contact folder by changing the display name then deleting it and I ended up with 1 more "ghost" folder unfortunately.

DiogoCordas avatar Jun 19 '24 09:06 DiogoCordas

I have the same problem and can confirm/reproduce that the problem is that the deleted folder is moved into the deleted items box instead of completely removed. Once it is in the deleted items it has duplicate ID's for the same folder and cannot be deleted anymore. If the deleted items folder is purged, then it works again for one time (because there are no duplicate items)... Now as a workaround we have to find a way to purge the deleted items (I wasn't able to remove it with it's corresponding id) before the deleted command or maybe there is a now option with the delete api to NOT move it into deleted items folder, but to force remove it...? Maybe someone can find out?

nermal007 avatar Jun 27 '24 08:06 nermal007

@nermal007 Confirming that as well. Worse - all contacts inside the "deleted" folder still exist and can be seen even via standard v1.0 endpoint. DELETE works fine on them, removing them totally. PATCHing them to different parentFolderId do not work.

So from my standpoint, between 5th and 12th of May 2024 (my code worked before that period just fine) Microsoft changed some default policy concerning the deletion of contact folders. Now they are not deleted but moved to the hidden "recycle bin" Parent folder with all contacts. This move prevents you from deleting newly created folders with the same name. I cannot explain why some of the deleted folders have a random 8-symbols postfix as reported by @silente. I have the same case, but not for all deleted folders. But that is a minor thing. Having, in my case, dozens of "ghosted" folders with hundreds of contacts in them is not a long-term solution.

What we need is to find a way to purge the folders and/or the ability to control this new policy. Maybe someone has ideas about how to find this policy? I looked in Azure Q&A but was not able to find anything related.

Tsubasanut avatar Jun 27 '24 10:06 Tsubasanut

@Tsubasanut Yes can confirm that. My code worked since more than a year without any hickups. My current workaround is to rename the folder to xxxxxxx-timestamp and then delete it (so there will be no future conflicts with the same name), but as you said, it will fill up the users deleted items folder with ghosted items (which he has to purge manually as there is no automatic way of doing that - at least not so far). Microsoft needs to extend their DELETE Api to eith revert to the previous functionality or to have an option if it should be purged immediately or moved into Deleted items folder. Unfortunately I don't have contact to any Microsoft support - maybe someone here can let them know?

nermal007 avatar Jun 27 '24 10:06 nermal007

No updates on this issue so far from MS. I re-wrote my job to PATCH user mailboxes with updated/new contacts. I hash the contacts to outside DBs and compare them on each run. Still works faster than the old solution with folder delete/create. So I'm dropping out of this conversation. Good luck to everyone.

Tsubasanut avatar Aug 06 '24 05:08 Tsubasanut

any news?

EDIT: it seems that now you can permanently delete a contact folder using the beta endpoint...

Smig0l avatar Aug 27 '24 15:08 Smig0l

Is there any news about this? What is appropriate to do?

silente avatar Nov 21 '24 21:11 silente

@silente have you tried to open a graph ticket on graph support? Reason being that the issue cuts across different SDKs and not only PowerShell. For API related issues/questions we are not best placed to give an answer. Kindly raise an issue here https://developer.microsoft.com/en-us/graph/support so that the API owner can respond to it.

timayabi2020 avatar Feb 15 '25 08:02 timayabi2020

This issue has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for 4 days. It will be closed if no further activity occurs within 3 days of this comment.