Script for Teams-Chat backup

%3CLINGO-SUB%20id%3D%22lingo-sub-1547371%22%20slang%3D%22de-DE%22%3EScript%20for%20Teams%20chat%20backup%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-1547371%22%20slang%3D%22de-DE%22%3E%3CP%3E%3CSPAN%3ESometimes%20it%20is%20necessary%20to%20save%20the%20chat%20history%20of%20a%20Teams%20channel.%20I%20wrote%20a%20simple%20script%2C%20where%20you%20can%20select%20the%20needed%20team(s)%20and%20outputting%20the%20chat%20content%20to%20an%20html%20file.%20If%20there%20are%20any%20comments%2C%20I'm%20open%20for%20suggestions.%20%3C%2FSPAN%3E%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3E%3CSPAN%3EHere%20is%20the%20Script%3A%3C%2FSPAN%3E%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CPRE%20class%3D%22lia-code-sample%20language-powershell%22%3E%3CCODE%3E%23Install-Module%20-Name%20SharePointPnPPowerShellOnline%0A%0A%24SecurityScope%20%3D%20%40(%22Group.Read.All%22)%0AConnect-PnPOnline%20-Scopes%20%24SecurityScope%0A%24PnPGraphAccessToken%20%3D%20Get-PnPGraphAccessToken%0A%2C%24Headers%20%3D%20%40%7B%0A%20%20%20%20%20%20%20%20%22Content-Type%22%20%3D%20%22application%2Fjson%22%0A%20%20%20%20%20%20%20%20Authorization%20%20%3D%20%22Bearer%20%24PnPGraphAccessToken%22%20%20%20%20%0A%20%20%20%20%7D%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%24Date%20%3D%20Get-Date%20-Format%20%22dd.MM.yyyy%2C%20HH%3Amm%22%0A%20%20%20%20%20%20%20%20%24DOCTYPE%20%3D%20%22%22%0A%20%20%20%20%20%20%20%20%24Style%20%3D%22%3CSTYLE%3Etable%20%7Bborder-collapse%3A%20collapse%3B%20width%3A100%25%3B%7D%20table%20th%20%7Btext-align%3Aleft%3B%20background-color%3A%20%23004C99%3B%20color%3A%23fff%3B%20padding%3A%204px%2030px%204px%208px%3B%7D%20table%20td%20%7Bborder%3A%201px%20solid%20%23004C99%3B%20padding%3A%204px%208px%3B%7D%20td%20%7Bbackground-color%3A%20%23DDE5FF%7D%3C%2FSTYLE%3E%22%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%24Head%20%3D%20%22%3CTITLE%3EBackup%3A%20Teams-Chat%3C%2FTITLE%3E%22%0A%20%20%20%20%20%20%20%20%24Body%20%3D%20%22%3CDIV%20style%3D%22width%3A%20100%25%3B%22%3E%3CTABLE%3E%3CTBODY%3E%3CTR%3E%3CTH%20style%3D%22text-align%3Acenter%22%3E%3CH1%20id%3D%22toc-hId-498934244%22%20id%3D%22toc-hId-498934244%22%20id%3D%22toc-hId-498907301%22%3EBackup%3A%20Teams-Chat%20from%20%24Date%3C%2FH1%3E%3C%2FTH%3E%3C%2FTR%3E%3C%2FTBODY%3E%3C%2FTABLE%3E%22%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%24Table_body%20%3D%20%22%3CDIV%20style%3D%22width%3A%20100%25%3B%22%3E%3CTABLE%3E%3CTBODY%3E%3CTR%3E%3CTH%3ETimeStamp%3C%2FTH%3E%3CTH%3EUser%20Name%3C%2FTH%3E%3CTH%3EMessage%3C%2FTH%3E%3C%2FTR%3E%22%0A%20%20%20%20%20%20%20%20%24Content%20%3D%22%22%0A%20%20%20%20%20%20%20%20%24Footer%20%3D%20%22%22%0A%20%20%20%20%20%20%20%20%24response_teams%20%3D%20Invoke-RestMethod%20-Uri%20%20%22https%3A%2F%2Fgraph.microsoft.com%2Fbeta%2Fgroups%22%20-Method%20Get%20-Headers%20%24Headers%20-UseBasicParsing%0A%20%20%20%20%20%20%20%20%24response_teams.value%20%7C%20Where-Object%20%7B%24_.groupTypes%20-eq%20%22Unified%22%7D%20%7C%20Select-Object%20-Property%20displayName%2C%20ID%20%20%7C%20Out-GridView%20-PassThru%20-Title%20'Which%20Team-Chat%20do%20you%20want%20to%20backup%3F'%20%7C%0A%20%20%20%20%20%20%20%20ForEach-Object%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24Team_ID%20%3D%20%24_.ID%0A%20%20%20%20%20%20%20%20%20%20%20%20%24Team_displayName%20%3D%20%24_.displayName%0A%20%20%20%20%20%20%20%20%20%20%20%20Write-Progress%20-Activity%20%22Bckup%20Team%20Chat%20Mesasages%22%20%20-Status%20%22Get%20Team%3A%20%24(%24Team_displayName)%22%0A%20%20%20%20%20%20%20%20%20%20%20%20Start-Sleep%20-Milliseconds%2050%0A%20%20%20%20%20%20%20%20%20%20%20%20%24Content%20%2B%3D%20%22%3CHR%20%2F%3E%3CH2%20id%3D%22toc-hId-1189495718%22%20id%3D%22toc-hId-1189495718%22%20id%3D%22toc-hId-1189468775%22%3ETeam%3A%20%22%20%2B%20%24Team_displayName%20%2B%20%22%3C%2FH2%3E%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%24response_channels%20%3D%20Invoke-RestMethod%20-Uri%20%20%22https%3A%2F%2Fgraph.microsoft.com%2Fbeta%2Fteams%2F%24Team_ID%2Fchannels%22%20-Method%20Get%20-Headers%20%24Headers%20-UseBasicParsing%0A%20%20%20%20%20%20%20%20%20%20%20%20%24response_channels.value%20%7C%20Select-Object%20-Property%20ID%2C%20displayName%20%7C%0A%20%20%20%20%20%20%20%20%20%20%20%20ForEach-Object%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24Channel_ID%20%3D%20%24_.ID%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24Channel_displayName%20%3D%20%24_.displayName%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Write-Progress%20-Activity%20%22Bckup%20Team%20Chat%20Mesasages%22%20%20-Status%20%22Get%20Channel%3A%20%24(%24Channel_displayName)%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Start-Sleep%20-Milliseconds%2050%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24Content%20%2B%3D%20%22%3CH3%20id%3D%22toc-hId-1880057192%22%20id%3D%22toc-hId-1880057192%22%20id%3D%22toc-hId-1880030249%22%3EChannel%3A%20%22%20%2B%20%24Channel_displayName%20%2B%20%22%3C%2FH3%3E%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24response_messages%20%3D%20Invoke-RestMethod%20-Uri%20%20%22https%3A%2F%2Fgraph.microsoft.com%2Fbeta%2Fteams%2F%24Team_ID%2Fchannels%2F%24Channel_ID%2Fmessages%22%20-Method%20Get%20-Headers%20%24Headers%20-UseBasicParsing%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24response_messages.value%20%7C%20Select-Object%20-Property%20ID%2C%20createdDateTime%2C%20from%20%7C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20ForEach-Object%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24Message_ID%20%3D%20%24_.ID%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24Message_TimeStamp%20%3D%20%24_.createdDateTime%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24Message_from%20%3D%20%24_.from%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24response_content%20%3D%20Invoke-RestMethod%20-Uri%20%20%22https%3A%2F%2Fgraph.microsoft.com%2Fbeta%2Fteams%2F%24Team_ID%2Fchannels%2F%24Channel_ID%2Fmessages%2F%24Message_ID%22%20-Method%20Get%20-Headers%20%24Headers%20-UseBasicParsing%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Write-Progress%20-Activity%20%22Bckup%20Team%20Chat%20Mesasages%22%20%20-Status%20%22Get%20Team%3A%20%24(%24Team_displayName)%2C%20Gett%20Message-ID%3A%20%24(%24Message_ID)%2C%20from%20Channel%3A%20%24(%24Channel_displayName)%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Start-Sleep%20-Milliseconds%2050%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24Content%20%2B%3D%20%24Table_body%20%2B%20%22%3CTR%3E%3CTD%3E%22%20%2B%20%24Message_TimeStamp%20%2B%20%22%3C%2FTD%3E%3CTD%20style%3D%22width%3A%2010%25%3B%22%3E%22%20%2B%20%24Message_from.user.displayName%20%2B%20%22%3C%2FTD%3E%3CTD%20style%3D%22width%3A%2075%25%3B%22%3E%22%20%2B%20%24response_content.body.content%20%2B%20%24response_content.attachments.id%20%2B%20%22%3C%2FTD%3E%3C%2FTR%3E%3C%2FTBODY%3E%3C%2FTABLE%3E%3C%2FDIV%3E%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24response_Reply%20%3D%20Invoke-RestMethod%20-Uri%20%20%22https%3A%2F%2Fgraph.microsoft.com%2Fbeta%2Fteams%2F%24Team_ID%2Fchannels%2F%24Channel_ID%2Fmessages%2F%24Message_ID%2Freplies%22%20-Method%20Get%20-Headers%20%24Headers%20-UseBasicParsing%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24response_Reply.value%20%7C%20Select-Object%20-Property%20ID%2C%20createdDateTime%2C%20from%20%7C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20ForEach-Object%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24Reply_ID%20%3D%20%24_.ID%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24Reply_TimeStamp%3D%20%24_.createdDateTime%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24Reply_from%20%3D%20%24_.from%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24response_Reply%20%3D%20Invoke-RestMethod%20-Uri%20%20%22https%3A%2F%2Fgraph.microsoft.com%2Fbeta%2Fteams%2F%24Team_ID%2Fchannels%2F%24Channel_ID%2Fmessages%2F%24Message_ID%2Freplies%2F%24Reply_ID%22%20-Method%20Get%20-Headers%20%24Headers%20-UseBasicParsing%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Write-Progress%20-Activity%20%22Bckup%20Team%20Chat%20Mesasages%22%20%20-Status%20%22Gett%20Reply-Message-ID%3A%20%24(%24Reply_ID)%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Start-Sleep%20-Milliseconds%2050%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20ForEach-Object%20%7B%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24Content%20%2B%3D%20%24Table_body%20%2B%20%22%22%20%2B%20%24Reply_TimeStamp%20%2B%20%22%22%20%2B%20%24Reply_from.user.displayName%20%2B%20%22%22%20%2B%20%24response_Reply.body.content%20%2B%20%24response_Reply.attachments.id%20%2B%20%24response_Reply.attachments.name%20%2B%20%22%3C%2FDIV%3E%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%24DOCTYPE%20%2B%20%24Style%20%2B%20%24Head%20%2B%20%24Body%20%2B%20%24Content%20%2B%20%24Footer%20%7C%20%20Out-File%20-FilePath%20%22C%3A%5CBackup.html%22%0A%20%20%20%20%20%20%20%20%26amp%3B%20%22C%3A%5CProgram%20Files%20(x86)%5CMicrosoft%5CEdge%5CApplication%5Cmsedge.exe%22%20%22C%3A%5CBackup.html%22%3C%2FCODE%3E%3C%2FPRE%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CPRE%3E%26nbsp%3B%3C%2FPRE%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-LABS%20id%3D%22lingo-labs-1547371%22%20slang%3D%22de-DE%22%3E%3CLINGO-LABEL%3EOffice%20365%3C%2FLINGO-LABEL%3E%3CLINGO-LABEL%3ESharepoint%3C%2FLINGO-LABEL%3E%3CLINGO-LABEL%3ETeams%3C%2FLINGO-LABEL%3E%3CLINGO-LABEL%3EWindows%20PowerShell%3C%2FLINGO-LABEL%3E%3C%2FLINGO-LABS%3E%3CLINGO-SUB%20id%3D%22lingo-sub-1750976%22%20slang%3D%22en-US%22%3ERe%3A%20Script%20for%20Teams-Chat%20backup%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-1750976%22%20slang%3D%22en-US%22%3EGood%20work!%20Is%20There%20anyway%20to%20import%20after%20the%20export%3F%3C%2FLINGO-BODY%3E
New Contributor

Sometimes it is necessary to save the chat history of a Teams-Channel. I wrote a simple script, where you can select the needed Team(s) and outputting the Chat-Content to a html File. If there are any comments, I'm open for suggestions.

 

Here is the Script:

 

#Install-Module -Name SharePointPnPPowerShellOnline

$SecurityScope = @("Group.Read.All")
Connect-PnPOnline -Scopes $SecurityScope
$PnPGraphAccessToken = Get-PnPGraphAccessToken
,$Headers = @{
        "Content-Type" = "application/json"
        Authorization  = "Bearer $PnPGraphAccessToken"    
    }        
        $Date = Get-Date -Format "dd.MM.yyyy, HH:mm"
        $DOCTYPE = "<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'><html xmlns='http://www.w3.org/1999/xhtml'>"
        $Style ="<style>table {border-collapse: collapse; width:100%;} table th {text-align:left; background-color: #004C99; color:#fff; padding: 4px 30px 4px 8px;} table td {border: 1px solid #004C99; padding: 4px 8px;} td {background-color: #DDE5FF}</style>"     
        $Head = "<head><title>Backup: Teams-Chat</title></head>"
        $Body = "<body><div style='width: 100%;'><table><tr><th style='text-align:center'><h1>Backup: Teams-Chat from $Date</h1></th></tr></table>"               
        $Table_body = "<div style='width: 100%;'><table><tr><th>TimeStamp</th><th>User Name</th><th>Message</th></tr>"
        $Content =""
        $Footer = "</body>"
        $response_teams = Invoke-RestMethod -Uri  "https://graph.microsoft.com/beta/groups" -Method Get -Headers $Headers -UseBasicParsing
        $response_teams.value | Where-Object {$_.groupTypes -eq "Unified"} | Select-Object -Property displayName, ID  | Out-GridView -PassThru -Title 'Which Team-Chat do you want to backup?' |
        ForEach-Object {
            $Team_ID = $_.ID
            $Team_displayName = $_.displayName
            Write-Progress -Activity "Bckup Team Chat Mesasages"  -Status "Get Team: $($Team_displayName)"
            Start-Sleep -Milliseconds 50
            $Content += "</br></br><hr><h2>Team: " + $Team_displayName + "</h2>"
            $response_channels = Invoke-RestMethod -Uri  "https://graph.microsoft.com/beta/teams/$Team_ID/channels" -Method Get -Headers $Headers -UseBasicParsing
            $response_channels.value | Select-Object -Property ID, displayName |
            ForEach-Object {
                $Channel_ID = $_.ID
                $Channel_displayName = $_.displayName
                Write-Progress -Activity "Bckup Team Chat Mesasages"  -Status "Get Channel: $($Channel_displayName)"
                Start-Sleep -Milliseconds 50    
                $Content += "<h3>Channel: " + $Channel_displayName + "</h3>"
                $response_messages = Invoke-RestMethod -Uri  "https://graph.microsoft.com/beta/teams/$Team_ID/channels/$Channel_ID/messages" -Method Get -Headers $Headers -UseBasicParsing
                $response_messages.value | Select-Object -Property ID, createdDateTime, from |
                ForEach-Object {
                    $Message_ID = $_.ID
                    $Message_TimeStamp = $_.createdDateTime
                    $Message_from = $_.from                    
                    $response_content = Invoke-RestMethod -Uri  "https://graph.microsoft.com/beta/teams/$Team_ID/channels/$Channel_ID/messages/$Message_ID" -Method Get -Headers $Headers -UseBasicParsing
                    Write-Progress -Activity "Bckup Team Chat Mesasages"  -Status "Get Team: $($Team_displayName), Gett Message-ID: $($Message_ID), from Channel: $($Channel_displayName)"
                    Start-Sleep -Milliseconds 50                                                         
                    $Content += $Table_body + "<td>" + $Message_TimeStamp + "</td><td style='width: 10%;'>" + $Message_from.user.displayName + "</td><td style='width: 75%;'>" + $response_content.body.content + $response_content.attachments.id + "</td></table></div>"
                    $response_Reply = Invoke-RestMethod -Uri  "https://graph.microsoft.com/beta/teams/$Team_ID/channels/$Channel_ID/messages/$Message_ID/replies" -Method Get -Headers $Headers -UseBasicParsing
                    $response_Reply.value | Select-Object -Property ID, createdDateTime, from |
                    ForEach-Object {
                        $Reply_ID = $_.ID
                        $Reply_TimeStamp= $_.createdDateTime
                        $Reply_from = $_.from                        
                        $response_Reply = Invoke-RestMethod -Uri  "https://graph.microsoft.com/beta/teams/$Team_ID/channels/$Channel_ID/messages/$Message_ID/replies/$Reply_ID" -Method Get -Headers $Headers -UseBasicParsing
                        Write-Progress -Activity "Bckup Team Chat Mesasages"  -Status "Gett Reply-Message-ID: $($Reply_ID)"
                        Start-Sleep -Milliseconds 50
                        ForEach-Object {                                                                          
                        $Content += $Table_body + "<td>" + $Reply_TimeStamp + "</td><td style='width: 10%;'>" + $Reply_from.user.displayName + "</td><td style='width: 75%;'>" + $response_Reply.body.content + $response_Reply.attachments.id + $response_Reply.attachments.name + "</td></table></div>"
                        }
                    }
                }                                
            }
        }
        $DOCTYPE + $Style + $Head + $Body + $Content + $Footer |  Out-File -FilePath "C:\Backup.html"
        & "C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe" "C:\Backup.html"

 

 

 

2 Replies
Good work! Is There anyway to import after the export?

@Jojo90 


Doesn't seem to work for me:

AADSTS70011: The provided request must include a 'scope' input parameter. The provided value for the input parameter 'scope' is not valid. The scope https://graph.microsoft.com/.default https://graph.microsoft.com/Group.Read.All offline_access openid profile is not valid. .default scope can't be combined with resource-specific scopes.